Commit 372ef8b1 authored by Christian Wach's avatar Christian Wach
Browse files

Make PHP compatible with civilint

parent 55995563
<?php /*
--------------------------------------------------------------------------------
Plugin Name: CiviCRM Gutenberg Blocks
Plugin URI: https://develop.tadpole.cc/plugins/civicrm-gutenberg-blocks
Description: CiviCRM Blocks for the Gutenberg Editor.
Author: Christian Wach, Andrei Mondoc
Version: 0.2
Author URI: http://haystack.co.uk
Text Domain: civicrm-gutenberg-blocks
Domain Path: /languages
--------------------------------------------------------------------------------
*/
<?php
/**
* Plugin Name: CiviCRM Gutenberg Blocks
* Plugin URI: https://develop.tadpole.cc/plugins/civicrm-gutenberg-blocks
* Description: CiviCRM Blocks for the Gutenberg Editor.
* Author: Christian Wach, Andrei Mondoc
* Version: 0.2
* Author URI: http://haystack.co.uk
* Text Domain: civicrm-gutenberg-blocks
* Domain Path: /languages
*/
// Version.
define( 'CIVICRM_GUTENBERG_BLOCKS_VERSION', '0.1' );
define('CIVICRM_GUTENBERG_BLOCKS_VERSION', '0.1');
// Store reference to this file.
define( 'CIVICRM_GUTENBERG_BLOCKS_PLUGIN_FILE', __FILE__ );
define('CIVICRM_GUTENBERG_BLOCKS_PLUGIN_FILE', __FILE__);
// Store URL to this plugin's directory.
if ( ! defined( 'CIVICRM_GUTENBERG_BLOCKS_PLUGIN_URL' ) ) {
define( 'CIVICRM_GUTENBERG_BLOCKS_PLUGIN_URL', plugin_dir_url( CIVICRM_GUTENBERG_BLOCKS_PLUGIN_FILE ) );
if (!defined('CIVICRM_GUTENBERG_BLOCKS_PLUGIN_URL')) {
define('CIVICRM_GUTENBERG_BLOCKS_PLUGIN_URL', plugin_dir_url(CIVICRM_GUTENBERG_BLOCKS_PLUGIN_FILE));
}
// Store PATH to this plugin's directory.
if ( ! defined( 'CIVICRM_GUTENBERG_BLOCKS_PLUGIN_PATH' ) ) {
define( 'CIVICRM_GUTENBERG_BLOCKS_PLUGIN_PATH', plugin_dir_path( CIVICRM_GUTENBERG_BLOCKS_PLUGIN_FILE ) );
if (!defined('CIVICRM_GUTENBERG_BLOCKS_PLUGIN_PATH')) {
define('CIVICRM_GUTENBERG_BLOCKS_PLUGIN_PATH', plugin_dir_path(CIVICRM_GUTENBERG_BLOCKS_PLUGIN_FILE));
}
/**
* CiviCRM Gutenberg Block class.
*
......@@ -40,596 +35,574 @@ if ( ! defined( 'CIVICRM_GUTENBERG_BLOCKS_PLUGIN_PATH' ) ) {
*/
class CiviCRM_Gutenberg_Blocks {
/**
* Initialise this object.
*
* @since 0.1
*/
public function __construct() {
// Init translation.
$this->translation();
// Init block and shortcode.
add_action('init', [$this, 'block_init']);
// Render block preview.
add_filter('rest_post_dispatch', [$this, 'render_block_preview'], 10, 3);
// Convert serialised civicrm content blocks to shortcode.
add_action('wp', [$this, 'prerender'], 5);
// Add CiviCRM core resources.
add_action('admin_head', [$this, 'maybe_add_core_resources'], 20);
}
/**
* Load translation.
*
* @since 0.1
*/
public function translation() {
load_plugin_textdomain(
'civicrm-gutenberg-blocks',
FALSE,
dirname(plugin_basename(__FILE__)) . '/languages/'
);
}
/**
* Register our block and shortcode.
*
* @since 0.1
*/
public function block_init() {
// Register our block editor script.
wp_register_script(
'civicrm-gutenberg-blocks',
plugins_url('build/index.js', CIVICRM_GUTENBERG_BLOCKS_PLUGIN_FILE),
['wp-blocks', 'wp-element', 'wp-components', 'wp-editor', 'wp-i18n'],
filemtime(CIVICRM_GUTENBERG_BLOCKS_PLUGIN_PATH . 'build/index.js')
);
// Register our block, and explicitly define the attributes we accept.
register_block_type('civicrm/civicrm-content-block', [
'attributes' => [
'component' => [
'type' => 'string',
'default' => 'profile',
],
'gid' => [
'type' => 'string',
'default' => '1',
],
'id' => [
'type' => 'string',
'default' => '1',
],
'mode' => [
'type' => 'string',
'enum' => ['test', 'live', 'create', 'edit', 'view', 'search'],
'default' => 'live',
],
'action' => [
'type' => 'string',
'enum' => ['info', 'register'],
'default' => 'info',
],
'hijack' => [
'type' => 'boolean',
'default' => FALSE,
],
'extra_attributes' => [
'type' => 'array',
'default' => [],
],
],
// The script name we gave in the wp_register_script() call:
'editor_script' => 'civicrm-gutenberg-blocks',
'render_callback' => [$this, 'block_render'],
]);
/*
* May be extended to:
* wp_set_script_translations('my-handle', 'my-domain', plugin_dir_path(MY_PLUGIN) . 'languages')).
* @see https://make.wordpress.org/core/2018/11/09/new-javascript-i18n-support-in-wordpress/
*/
wp_set_script_translations(
'civicrm-gutenberg-blocks',
'civicrm-gutenberg-blocks',
plugin_dir_path(CIVICRM_GUTENBERG_BLOCKS_PLUGIN_FILE) . 'languages'
);
}
/**
* Our combined block and shortcode renderer.
*
* @since 0.1
*
* @param array $attributes The attributes that were set on the block or shortcode.
* @return string $shortcode The constructed shortcode.
*/
public function block_render($attributes = []) {
$attributes = $this->cleanup_and_set_default_attributes($attributes);
// Add extra attributes.
if (!empty($attributes['extra_attributes'])) {
foreach ($attributes['extra_attributes'] as $attr) {
if (empty($attr['value'])) {
continue;
}
$attributes[$attr['name']] = $attr['value'];
}
}
unset($attributes['extra_attributes']);
$pairs = [];
foreach ($attributes as $key => $value) {
$pairs[] = esc_attr($key) . '="' . esc_attr($value) . '"';
}
$shortcode = '[civicrm ' . implode(' ', $pairs) . ']';
return $shortcode;
}
/**
* Filter the block-renderer route response and render the CiviCRM content block preview.
*
* @uses 'rest_post_dispatch' filter
*
* @since 1.0
*
* @param WP_REST_Response $response The existing response.
* @param WP_REST_Server $server The server object.
* @param WP_REST_Request $request The request object.
* @return WP_REST_Response $response The modified response.
*/
public function render_block_preview($response, WP_REST_Server $server, WP_REST_Request $request) {
if (!strpos($request->get_route(), 'civicrm/civicrm-content-block')) {
return $response;
}
$response->set_data([
'rendered' => $this->get_block_preview($request->get_param('attributes')),
]);
return $response;
}
/**
* Retreives CiviCRM's content block HTML preview.
*
* @since 1.0
*
* @param array $atts The block attributes.
* @return string $html The rendered content block HTML preview.
*/
public function get_block_preview(array $atts) {
switch ($atts['component']) {
case 'profile':
return $this->render_profile($atts);
case 'contribution':
return $this->render_contribution_page($atts);
case 'event':
return $this->render_event_page($atts);
case 'user-dashboard':
return $this->render_user_dashboard($atts);
case 'pcp':
return $this->render_pcp($atts);
case 'petition':
return $this->render_petition($atts);
}
}
/**
* Renders a profile's HTML.
*
* @since 0.1
*
* @param array $atts The block attributes.
* @return string $html The rendered profile HTML.
*/
public function render_profile(array $atts) {
if (empty($atts['gid'])) {
return '';
}
$args = [
'civicrm',
'profile',
$atts['mode'],
];
$_GET['gid'] = $_REQUEST['gid'] = $atts['gid'];
ob_start();
try {
if ($atts['mode'] == 'view') {
(new CRM_Profile_Page_View())->run();
}
elseif ($atts['mode'] == 'search') {
$_GET['reset'] = 1;
(new CRM_Profile_Page_Listings())->run();
}
else {
(new CRM_Profile_Page_Router())->run($args);
}
}
catch (Exception $e) {
return $e->getMessage();
}
return ob_get_clean();
}
/**
* Renders a Contribution Page's HTML.
*
* @since 0.1
*
* @param array $atts The block attributes.
* @return string $html The rendered HTML.
*/
public function render_contribution_page(array $atts) {
if (empty($atts['id'])) {
return '';
}
$_REQUEST['id'] = $atts['id'];
ob_start();
try {
(new CRM_Contribute_Controller_Contribution(
'CiviContribute',
CRM_Core_Action::ADD
))->run();
}
catch (Exception $e) {
return $e->getMessage();
}
return ob_get_clean();
}
/**
* Renders an Event Page's HTML.
*
* @since 0.1
*
* @param array $atts The block attributes.
* @return string $content The rendered HTML.
*/
public function render_event_page(array $atts) {
if (empty($atts['id'])) {
return '';
}
$_REQUEST['id'] = $atts['id'];
ob_start();
try {
if ($atts['action'] == 'register') {
(new CRM_Event_Controller_Registration())->run();
}
else {
(new CRM_Event_Page_EventInfo())->run();
}
}
catch (Exception $e) {
return $e->getMessage();
}
return ob_get_clean();
}
/**
* Renders the User Dashboard HTML.
*
* @since 0.1
*
* @param array $atts The block attributes.
* @return string $html The rendered HTML.
*/
public function render_user_dashboard(array $atts) {
ob_start();
try {
(new CRM_Contact_Page_View_UserDashBoard())->run();
}
catch (Exception $e) {
return $e->getMessage();
}
return ob_get_clean();
}
/**
* Renders a PCP's HTML.
*
* @since 0.1
*
* @param array $atts The block attributes.
* @return string $html The rendered HTML.
*/
public function render_pcp(array $atts) {
ob_start();
$_REQUEST['id'] = $atts['id'];
try {
(new CRM_PCP_Page_PCPInfo())->run();
}
catch (Exception $e) {
return $e->getMessage();
}
return ob_get_clean();
}
/**
* Renders a Petition's HTML.
*
* @since 0.1
*
* @param array $atts The block attributes.
* @return string $html The rendered HTML.
*/
public function render_petition(array $atts) {
ob_start();
$_REQUEST['sid'] = $atts['id'];
try {
(new CRM_Utils_Wrapper())->run('CRM_Campaign_Form_Petition_Signature', 'Sign Petition', NULL);
}
catch (Exception $e) {
return $e->getMessage();
}
return ob_get_clean();
}
/**
* Determine if a CiviCRM block is present.
*
* Looks at any of the posts about to be displayed and replaces the serialised
* block string with it's shortcode version.
*
* Based on CiviCRM_For_WordPress_Shortcodes::prerender().
*
* @uses 'wp' action.
*
* @since 0.1
*/
public function prerender() {
if (is_404()) {
return;
}
if (have_posts()) {
while (have_posts()) :
the_post();
global $post;
$post = $this->convert_serialised_block_to_shortcode($post);
endwhile;
}
// reset loop
rewind_posts();
}
/**
* Replaces all serialised content block strings with their shorcode string
* in post_content.
*
* @since 0.1
*
* @param WP_Post $post The WordPress Post to process.
* @return WP_Post $post The processed WordPress Post.
*/
public function convert_serialised_block_to_shortcode($post) {
if (is_null($post) || !($post instanceof WP_Post)) {
return $post;
}
if (!has_block('civicrm/civicrm-content-block', $post)) {
return $post;
}
// Get blocks.
$blocks = parse_blocks($post->post_content);
// Get all CiviCRM content blocks.
$civicrm_content_blocks = array_filter(
$blocks,
function ($block) {
return $block['blockName'] == 'civicrm/civicrm-content-block';
}
);
// Reset keys.
$civicrm_content_blocks = array_reduce(
$civicrm_content_blocks,
function($list, $block) {
$list[] = $block;
return $list;
},
[]
);
// Get all serialised content block strings.
preg_match_all(
'/<!-- wp:civicrm\/civicrm-content-block.*\/-->/',
$post->post_content,
$serialised_content_blocks
);
// Bail if no matches.
if (empty($serialised_content_blocks[0])) {
return $post;
}
// Replace serialised content block with shortcode.
array_map(
function($key, $block) use (&$post, $serialised_content_blocks) {
$post->post_content = str_replace(
$serialised_content_blocks[0][$key],
// Render with defaults:
$this->block_render($block['attrs']),
$post->post_content
);
},
array_keys($civicrm_content_blocks),
$civicrm_content_blocks
);
return $post;
}
/**
* Cleans up the attributes and sets default values.
*
* We need to set defaults because default values for attributes aren't
* converted into HTML comments.
*
* @see https://github.com/WordPress/gutenberg/issues/7342
*
* @since 0.1
*
* @param array $atts The existing block attributes.
* @return array $attributes The cleaned block attributes.
*/
public function cleanup_and_set_default_attributes(array $atts = []) {
$attributes = array_merge(
[
'component' => 'profile',
'mode' => ($atts['component'] ?? 'profile') == 'profile' ? 'create' : 'live',
'hijack' => 0,
],
$atts
);
if (empty($attributes['hijack'])) {
$attributes['hijack'] = 0;
}
// Clean up atts.
switch ($attributes['component']) {
case 'profile':
unset($attributes['action'], $attributes['id']);
break;
case 'contribution':
unset($attributes['gid']);
break;
case 'event':
$attributes['action'] = $attributes['action'] ?? 'info';
unset($attributes['gid']);
break;
case 'user-dashboard':
$attributes = ['component' => 'user-dashboard', 'hijack' => $attributes['hijack']];
break;
case 'petition':
case 'pcp':
unset($attributes['gid'], $attributes['action']);
break;
}
return $attributes;
}
/**
* Adds CiviCRM core resources in the Gutenberg editor if they are missing.
*
* @uses 'admin_head' action.
*
* @since 0.1
*/
public function maybe_add_core_resources() {
$screen = get_current_screen();
if (empty($screen)) {
return;
}
if (!$screen->is_block_editor()) {
return;
}
if (!has_action('admin_head', [civi_wp(), 'wp_head'])) {
add_action('admin_head', [civi_wp(), 'wp_head'], 50);
}
}
/**
* Initialise this object.
*
* @since 0.1
*/
public function __construct() {
// Init translation.
$this->translation();