Companion.php (42048B)
1 <?php 2 3 namespace Materialis; 4 5 class Companion 6 { 7 8 private static $instance = null; 9 private static $functionsFiles = array(); 10 11 private $_customizer = null; 12 13 private $cpData = array(); 14 private $remoteDataURL = null; 15 16 private $theme = null; 17 public $themeName = null; 18 private $themeSlug = null; 19 public $version = null; 20 private $path = null; 21 22 private $getCustomizerDataCache = array(); 23 24 25 private $__configsLoaded = array(); 26 27 public function __construct($root = null) 28 { 29 $theme = wp_get_theme(); 30 $this->themeName = $theme->get('Name'); 31 $this->path = $root; 32 33 // check for current theme in customize.php 34 if ($previewedTheme = $this->checkForThemePreviewedInCustomizer()) { 35 $this->themeSlug = $previewedTheme["TextDomain"]; 36 $this->themeName = $previewedTheme["Name"]; 37 } else { 38 // current theme is a child theme 39 if ($this->theme->get('Template')) { 40 $template = $this->theme->get('Template'); 41 $templateThemeData = wp_get_theme($template); 42 $this->themeSlug = $templateThemeData->get('TextDomain'); 43 $this->themeName = $templateThemeData->get('Name'); 44 } else { 45 $this->themeSlug = $this->theme->get('TextDomain'); 46 } 47 48 } 49 50 if ( ! $this->isCurrentThemeSupported()) { 51 return; 52 } 53 54 if (file_exists($this->themeDataPath("/functions.php"))) { 55 require_once $this->themeDataPath("/functions.php"); 56 } 57 58 if (file_exists($this->themeDataPath("/integrations/index.php"))) { 59 require_once $this->themeDataPath("/integrations/index.php"); 60 } 61 62 if ( ! self::$instance) { 63 self::$instance = $this; 64 add_action('init', array($this, 'initCompanion')); 65 $this->registerActivationHooks(); 66 } else { 67 global $wp_customize; 68 if ($wp_customize && ! $this->isCustomizePreview()) { 69 add_filter('cloudpress\companion\cp_data', array($this, 'getInstanceData')); 70 } 71 } 72 73 $this->version = $this->getCustomizerData('version'); 74 } 75 76 public function checkForThemePreviewedInCustomizer() 77 { 78 $theme = false; 79 $is_customize_admin_page = (is_admin() && 'customize.php' == basename($_SERVER['PHP_SELF'])); 80 $keys = array('changeset_uuid', 'customize_changeset_uuid', 'customize_theme', 'theme', 'customize_messenger_channel', 'customize_autosaved'); 81 $input_vars = array_merge( 82 wp_array_slice_assoc($_GET, $keys), 83 wp_array_slice_assoc($_POST, $keys) 84 ); 85 86 if ($is_customize_admin_page && isset($input_vars['theme'])) { 87 $theme = $input_vars['theme']; 88 } else if (isset($input_vars['customize_theme'])) { 89 $theme = $input_vars['customize_theme']; 90 } 91 92 $themeData = wp_get_theme($theme); 93 $textDomain = $themeData->get('TextDomain'); 94 $name = $themeData->get('Name'); 95 96 if ($themeData->get('Template')) { 97 $parentThemeData = wp_get_theme($themeData->get('Template')); 98 $textDomain = $parentThemeData->get('TextDomain'); 99 $name = $parentThemeData->get('Name'); 100 } 101 102 return array( 103 'TextDomain' => $textDomain, 104 'Name' => $name, 105 ); 106 } 107 108 public function registerActivationHooks() 109 { 110 $self = $this; 111 112 register_activation_hook($this->path, function () use ($self) { 113 do_action('cloudpress\companion\activated\\' . $self->getThemeSlug(), $self); 114 }); 115 116 register_deactivation_hook($this->path, function () use ($self) { 117 do_action('cloudpress\companion\deactivated\\' . $self->getThemeSlug(), $self); 118 }); 119 } 120 121 public function setPageContent($data, $filter_context) 122 { 123 $status = $filter_context['status']; 124 125 $pages_content = false; 126 127 $data_key = "materialis-pro::page_content"; 128 129 if (isset($data[$data_key])) { 130 $pages_content = $data[$data_key]; 131 } else { 132 if (isset($data["materialis::page_content"])) { 133 $data_key = "materialis::page_content"; 134 $pages_content = $data[$data_key];; 135 } 136 } 137 138 if ($status == "draft" && $pages_content) { 139 $page_id = isset($_POST['customize_post_id']) ? intval($_POST['customize_post_id']) : -1; 140 141 $encode = false; 142 $pages_content = $pages_content["value"]; 143 if (is_string($pages_content)) { 144 $pages_content = json_decode(urldecode($pages_content), true); 145 $encode = true; 146 } 147 148 $page_content = $pages_content[$page_id]; 149 $page_content = preg_replace('/<!--@@CPPAGEID\[(.*)\]@@-->/s', '', $page_content); 150 151 if ($page_id != -1) { 152 153 $post = get_post($page_id); 154 155 wp_create_post_autosave(array( 156 'post_ID' => $page_id, 157 'post_content' => $page_content, 158 'post_title' => $post->post_title, 159 )); 160 161 //unset($pages_content[$page_id]); 162 163 if ($encode) { 164 $data[$data_key]["value"] = json_encode($pages_content); 165 } else { 166 $data[$data_key]["value"] = $pages_content; 167 } 168 169 } 170 } 171 172 do_action('cloudpress\companion\clear_caches'); 173 174 return $data; 175 } 176 177 public function initCompanion() 178 { 179 180 $this->checkNotifications(); 181 182 $this->checkIfCompatibleChildTheme(); 183 184 $this->_customizer = new \Materialis\Customizer\Customizer($this); 185 \Materialis\Customizer\Template::load($this); 186 \Materialis\Customizer\ThemeSupport::load(); 187 188 add_action('wp_ajax_create_home_page', array($this, 'createFrontPage')); 189 190 add_action('wp_ajax_cp_open_in_customizer', array($this, 'openPageInCustomizer')); 191 add_action('wp_ajax_cp_shortcode_refresh', array($this, 'shortcodeRefresh')); 192 193 add_filter('page_row_actions', array($this, 'addEditInCustomizer'), 0, 2); 194 195 add_action('admin_footer', array($this, 'addAdminScripts')); 196 197 add_action('media_buttons', array($this, 'addEditInCustomizerPageButtons')); 198 199 add_filter('is_protected_meta', array($this, 'isProtectedMeta'), 10, 3); 200 201 add_filter("customize_changeset_save_data", array($this, 'setPageContent'), -10, 2); 202 203 // loadKirkiCss Output Components; 204 $this->setKirkiOutputFields(); 205 206 // look for google fonts 207 $this->addGoogleFonts(); 208 209 do_action('cloudpress\companion\ready', $this); 210 211 add_action('customize_register', function ($wp_customize) { 212 \Materialis\KirkiControls\SectionSettingControl::load(); 213 $wp_customize->register_control_type("Materialis\\KirkiControls\\SectionSettingControl"); 214 215 add_filter('kirki/control_types', function ($controls) { 216 217 if (class_exists("Materialis\\KirkiControls\\SectionSettingControl")) { 218 $controls['sectionsetting'] = "Materialis\\KirkiControls\\SectionSettingControl"; 219 } 220 221 return $controls; 222 }); 223 224 }); 225 226 // add post meta revisions (to revert from a page editable back to normal); 227 $this->addMaintainableMetaToRevision(); 228 } 229 230 public function getMaintainableKeysLabelPair($fields = array()) 231 { 232 $fields = array_merge($fields, array( 233 'is_' . $this->themeSlug . '_front_page' => 'Is ' . $this->themeName . ' Front Page', 234 'is_' . $this->themeSlug . '_maintainable_page' => 'Is ' . $this->themeName . ' FMaintainable Page', 235 )); 236 237 return $fields; 238 } 239 240 public function getMaintainableMetaKeys() 241 { 242 $keys = $this->getMaintainableKeysLabelPair(); 243 244 return array_keys($keys); 245 246 } 247 248 public function addMaintainableMetaToRevision() 249 { 250 $keys = $this->getMaintainableMetaKeys(); 251 foreach ($keys as $key) { 252 add_filter("_wp_post_revision_field_{$key}", array($this, 'getMetaFieldRevision'), 10, 2); 253 } 254 255 // add_filter('_wp_post_revision_fields', array($this, 'getMaintainableKeysLabelPair')); 256 add_action('save_post', array($this, 'saveMetaFieldRevision'), 10, 2); 257 add_action('wp_restore_post_revision', array($this, 'restoreMetaFieldRevision'), 10, 2); 258 259 } 260 261 public function getMetaFieldRevision($value, $field) 262 { 263 global $revision; 264 265 return get_metadata('post', $revision->ID, $field, true); 266 267 } 268 269 public function saveMetaFieldRevision($post_id, $post) 270 { 271 if ($parent_id = wp_is_post_revision($post_id)) { 272 273 $parent = get_post($parent_id); 274 275 $keys = $this->getMaintainableMetaKeys(); 276 foreach ($keys as $key) { 277 $meta_value = get_post_meta($parent->ID, $key, true); 278 if ($meta_value) { 279 add_metadata('post', $post_id, $key, $meta_value); 280 } 281 } 282 } 283 } 284 285 public function restoreMetaFieldRevision($post_id, $revision_id) 286 { 287 if ($parent_id = wp_is_post_revision($revision_id)) { 288 289 $keys = $this->getMaintainableMetaKeys(); 290 foreach ($keys as $key) { 291 $meta_value = get_metadata('post', $revision_id, $key, true); 292 293 if ($meta_value) { 294 update_post_meta($post_id, $key, $meta_value); 295 } else { 296 delete_post_meta($post_id, $key); 297 } 298 } 299 } 300 } 301 302 public function checkNotifications() 303 { 304 $notifications = $this->themeDataPath("/notifications.php"); 305 if (file_exists($notifications)) { 306 $notifications = require_once $notifications; 307 } else { 308 $notifications = array(); 309 } 310 311 \Materialis\Notify\NotificationsManager::load($notifications); 312 } 313 314 public function setKirkiOutputFields() 315 { 316 global $wp_customize; 317 318 if ( ! class_exists("\Kirki")) { 319 return; 320 } 321 322 // is managed in customizer; 323 if ($wp_customize) { 324 return; 325 } 326 327 $settings = (array)$this->getCustomizerData("customizer:settings"); 328 329 foreach ($settings as $id => $data) { 330 $controlClass = self::getTreeValueAt($data, "control:class", ""); 331 if (strpos($controlClass, "kirki:") === 0 && self::getTreeValueAt($data, "control:wp_data:output")) { 332 $configArgs = self::getTreeValueAt($data, "wp_data", array()); 333 \Kirki::add_config($id, $configArgs); 334 335 $fieldArgs = self::getTreeValueAt($data, "control:wp_data", array()); 336 $fieldArgs['type'] = str_replace("kirki:", "", $controlClass); 337 $fieldArgs['settings'] = $id; 338 $fieldArgs['section'] = self::getTreeValueAt($data, "section"); 339 340 if ( ! isset($fieldArgs['default'])) { 341 $fieldArgs['default'] = self::getTreeValueAt($data, "wp_data:default", array()); 342 } 343 344 \Kirki::add_field($id, $fieldArgs); 345 } 346 } 347 348 } 349 350 public function loadJSON($path) 351 { 352 353 if ( ! file_exists($path)) { 354 return array(); 355 } 356 357 $content = file_get_contents($path); 358 359 return json_decode($content, true); 360 } 361 362 public function loadConfig($path, $default = array()) 363 { 364 365 if (isset($this->__configsLoaded[$path])) { 366 return $this->__configsLoaded[$path]; 367 } 368 369 if ( ! file_exists($path)) { 370 return $default; 371 } 372 373 $content = require $path; 374 375 $this->__configsLoaded[$path] = $content; 376 377 return $content; 378 } 379 380 public function requireCPData($filter = true) 381 { 382 $cpData = get_theme_mod('theme_options', null); 383 if ( ! $cpData) { 384 $site = site_url(); 385 $site = preg_replace("/http(s)?:\/\//", "", $site); 386 $key = get_theme_mod('theme_pro_key', 'none'); 387 388 $cpData = $this->loadJSON($this->themeDataPath("/data.json")); 389 390 if ( ! $cpData) { 391 if ($this->remoteDataURL) { 392 require_once ABSPATH . WPINC . "/pluggable.php"; 393 394 $url = $this->remoteDataURL . "/" . $this->themeSlug; 395 396 // allow remote url 397 add_filter('http_request_args', function ($r, $_url) use ($url) { 398 if ($url === $_url) { 399 $r['reject_unsafe_urls'] = false; 400 } 401 402 return $r; 403 }, 10, 2); 404 405 $data = wp_safe_remote_get( 406 $url, 407 array( 408 'method' => 'GET', 409 'timeout' => 45, 410 'redirection' => 5, 411 'blocking' => true, 412 'httpversion' => '1.0', 413 'body' => array( 414 'site' => $site, 415 'key' => $key, 416 ), 417 ) 418 ); 419 if ($data instanceof \WP_Error) { 420 //TODO: Add a nicer message here 421 ob_get_clean(); 422 wp_die('There was an issue connecting to the theme server. Please contact the theme support!'); 423 } else { 424 //TODO: Load remote data 425 // $cpData = {}; 426 // set_theme_mod('theme_options',$this->cpData); 427 } 428 } 429 } 430 } 431 432 if ($filter) { 433 $cpData = apply_filters("cloudpress\companion\cp_data", $cpData, $this); 434 } 435 436 $this->cpData = $cpData; 437 438 return $cpData; 439 } 440 441 public function getInstanceData() 442 { 443 return $this->requireCPData(false); 444 } 445 446 public function getCustomizerData($key = null, $filter = true) 447 { 448 if (isset($this->getCustomizerDataCache[$key])) { 449 return $this->getCustomizerDataCache[$key]; 450 } 451 452 if ( ! is_array($this->cpData)) { 453 return array(); 454 } 455 456 $this->requireCPData($filter); 457 458 if ($key === null) { 459 return $this->cpData; 460 } 461 462 $result = self::getTreeValueAt($this->cpData, $key); 463 464 $this->getCustomizerDataCache[$key] = $result; 465 466 return $result; 467 } 468 469 public function isCurrentThemeSupported() 470 { 471 $supportedThemes = (array)$this->getCustomizerData('themes', false); 472 $currentTheme = $this->themeSlug; 473 474 $supported = (in_array($currentTheme, $supportedThemes) || in_array('*', $supportedThemes)); 475 476 return $supported; 477 } 478 479 public function checkIfCompatibleChildTheme() 480 { 481 $theme = wp_get_theme(); 482 $response = false; 483 if ($theme && $theme->get('Template')) { 484 $template = $theme->get('Template'); 485 486 if (in_array($template, $this->getCustomizerData('themes'))) { 487 add_filter('cloudpress\customizer\supports', "__return_true"); 488 $response = true; 489 } 490 491 } 492 493 return $response; 494 } 495 496 public function isMaintainable($post_id = false) 497 { 498 499 if ( ! $post_id) { 500 global $post; 501 $post_id = ($post && property_exists($post, "ID")) ? $post->ID : false; 502 } 503 504 if ( ! $post_id) { 505 return false; 506 } 507 508 $result = ( 509 ('1' === get_post_meta($post_id, 'is_' . $this->themeSlug . '_front_page', true)) 510 || ('1' === get_post_meta($post_id, 'is_' . $this->themeSlug . '_maintainable_page', true)) 511 ); 512 513 $result = $result || $this->applyOnPrimaryLanguage($post_id, array($this, 'isMaintainable')); 514 515 return $result; 516 } 517 518 public function isProtectedMeta($protected, $meta_key, $meta_type) 519 { 520 $is_protected = array( 521 'is_' . $this->themeSlug . '_front_page', 522 'is_' . $this->themeSlug . '_maintainable_page', 523 ); 524 if (in_array($meta_key, $is_protected)) { 525 return true; 526 } 527 528 return $protected; 529 } 530 531 public function isMultipage() 532 { 533 return $this->getCustomizerData('theme_type') === "multipage"; 534 } 535 536 public function getCurrentPageId() 537 { 538 global $post; 539 $post_id = ($post && property_exists($post, "ID")) ? $post->ID : false; 540 541 if ( ! $post_id) { 542 return false; 543 } 544 545 $editablePostTypes = apply_filters('cloudpress\companion\editable_post_types', array("page")); 546 547 if ( ! in_array($post->post_type, $editablePostTypes)) { 548 return false; 549 } 550 551 return $post_id; 552 } 553 554 private function applyOnPrimaryLanguage($post_id, $callback) 555 { 556 $result = false; 557 global $post; 558 559 if (function_exists('pll_get_post') && function_exists('pll_default_language')) { 560 $slug = pll_default_language('slug'); 561 $defaultID = pll_get_post($post_id, $slug); 562 $sourceID = isset($_REQUEST['from_post']) ? $_REQUEST['from_post'] : null; 563 $defaultID = $defaultID ? $defaultID : $sourceID; 564 565 if ($defaultID && ($defaultID !== $post_id)) { 566 $result = call_user_func($callback, $defaultID); 567 } 568 } 569 570 global $sitepress; 571 if ($sitepress) { 572 $defaultLanguage = $sitepress->get_default_language(); 573 global $wpdb; 574 575 $sourceTRID = isset($_REQUEST['trid']) ? $_REQUEST['trid'] : null; 576 $trid = $sitepress->get_element_trid($post_id); 577 $trid = $trid ? $trid : $sourceTRID; 578 $defaultID = $wpdb->get_var( 579 $wpdb->prepare( 580 "SELECT element_id FROM {$wpdb->prefix}icl_translations WHERE trid=%d AND language_code=%s", 581 $trid, 582 $defaultLanguage)); 583 584 if ($defaultID && ($defaultID !== $post_id)) { 585 $result = call_user_func($callback, $defaultID); 586 } 587 } 588 589 return $result; 590 } 591 592 public function isFrontPage($post_id = false) 593 { 594 595 if ( ! $post_id) { 596 global $post; 597 $post_id = ($post && property_exists($post, "ID")) ? $post->ID : false; 598 } 599 600 if ( ! $post_id) { 601 return false; 602 } 603 604 $isFrontPage = '1' === get_post_meta($post_id, 'is_' . $this->themeSlug . '_front_page', true); 605 606 $isWPFrontPage = is_front_page() && ! is_home(); 607 608 if ($isWPFrontPage && ! $isFrontPage && $this->isMaintainable($post_id)) { 609 update_post_meta($post_id, 'is_' . $this->themeSlug . '_front_page', '1'); 610 delete_post_meta($post_id, 'is_' . $this->themeSlug . '_maintainable_page'); 611 $isFrontPage = true; 612 } 613 614 $isFrontPage = $isFrontPage || $this->applyOnPrimaryLanguage($post_id, array($this, 'isFrontPage')); 615 616 return $isFrontPage; 617 } 618 619 public function getFrontPage() 620 { 621 $query = new \WP_Query( 622 array( 623 "post_status" => "publish", 624 "post_type" => 'page', 625 "meta_key" => 'is_' . $this->themeSlug . '_front_page', 626 ) 627 ); 628 if (count($query->posts)) { 629 return $query->posts[0]; 630 } 631 632 return null; 633 } 634 635 public function loadMaintainablePageAssets($post, $template) 636 { 637 do_action('cloudpress\template\load_assets', $this, $post, $template); 638 } 639 640 public function rootPath() 641 { 642 return dirname($this->path); 643 } 644 645 public function rootURL() 646 { 647 $templateDir = wp_normalize_path(get_stylesheet_directory()); 648 $pluginDir = wp_normalize_path(plugin_dir_path($this->path)); 649 $path = wp_normalize_path($this->path); 650 $url = site_url(); 651 if (strpos($path, $templateDir) === 0) { 652 $path = dirname($path); 653 $abs = wp_normalize_path(ABSPATH); 654 $path = str_replace($abs, '/', $path); 655 $url = get_stylesheet_directory_uri() . $path; 656 } else { 657 $url = plugin_dir_url($this->path); 658 } 659 660 return untrailingslashit($url); 661 } 662 663 public function themeDataPath($rel = "") 664 { 665 return $this->rootPath() . "/theme-data/" . $this->themeSlug . $rel; 666 } 667 668 public function themeDataURL($rel = "") 669 { 670 return $this->rootURL() . "/theme-data/" . $this->themeSlug . $rel; 671 } 672 673 public function assetsRootURL() 674 { 675 return $this->rootURL() . "/assets"; 676 } 677 678 public function assetsRootPath() 679 { 680 return $this->rootPath() . "/assets"; 681 } 682 683 public function customizer() 684 { 685 return $this->_customizer; 686 } 687 688 public function getThemeSlug($as_fn_prefix = false) 689 { 690 $slug = $this->themeSlug; 691 692 if ($as_fn_prefix) { 693 $slug = str_replace("-", "_", $slug); 694 } 695 696 return $slug; 697 } 698 699 public function __createFrontPage() 700 { 701 $page = $this->getFrontPage(); 702 703 update_option($this->themeSlug . '_companion_old_show_on_front', get_option('show_on_front')); 704 update_option($this->themeSlug . '_companion_old_page_on_front', get_option('page_on_front')); 705 706 if ( ! $page) { 707 $content = apply_filters('cloudpress\companion\front_page_content', "", $this); 708 709 $post_id = wp_insert_post( 710 array( 711 'comment_status' => 'closed', 712 'ping_status' => 'closed', 713 'post_name' => $this->themeName, 714 'post_title' => 'Front Page', 715 'post_status' => 'publish', 716 'post_type' => 'page', 717 'page_template' => apply_filters('cloudpress\companion\front_page_template', "page-templates/homepage.php"), 718 'post_content' => $content, 719 ) 720 ); 721 722 set_theme_mod($this->themeSlug . '_page_content', $content); 723 update_option('show_on_front', 'page'); 724 update_option('page_on_front', $post_id); 725 update_post_meta($post_id, 'is_' . $this->themeSlug . '_front_page', "1"); 726 727 if (null == get_page_by_title('Blog')) { 728 $post_id = wp_insert_post( 729 array( 730 'comment_status' => 'closed', 731 'ping_status' => 'closed', 732 'post_name' => 'blog', 733 'post_title' => 'Blog', 734 'post_status' => 'publish', 735 'post_type' => 'page', 736 ) 737 ); 738 } 739 740 $blog = get_page_by_title('Blog'); 741 update_option('page_for_posts', $blog->ID); 742 } else { 743 update_option('show_on_front', 'page'); 744 update_option('page_on_front', $page->ID); 745 update_post_meta($page->ID, 'is_' . $this->themeSlug . '_front_page', "1"); 746 } 747 } 748 749 public function createFrontPage() 750 { 751 $nonce = @$_POST['create_home_page_nounce']; 752 if ( ! wp_verify_nonce($nonce, 'create_home_page_nounce')) { 753 die(); 754 } 755 756 $this->__createFrontPage(); 757 } 758 759 public function restoreFrontPage() 760 { 761 if ($this->getFrontPage()) { 762 update_option('show_on_front', get_option($this->themeSlug . '_companion_old_show_on_front')); 763 update_option('page_on_front', get_option($this->themeSlug . '_companion_old_page_on_front')); 764 } 765 } 766 767 public function isWCPage($post) 768 { 769 if (function_exists('wc_get_page_id')) { 770 $shopId = wc_get_page_id('shop'); 771 $cartId = wc_get_page_id('cart'); 772 $checkoutId = wc_get_page_id('checkout'); 773 $myaccountId = wc_get_page_id('myaccount'); 774 775 switch ($post->ID) { 776 case $shopId: 777 case $cartId: 778 case $checkoutId: 779 case $myaccountId: 780 return true; 781 break; 782 default: 783 return false; 784 785 } 786 787 } else { 788 return false; 789 } 790 } 791 792 public function canEditInCustomizer($post = null) 793 { 794 $canEdit = false; 795 796 if ( ! $post) { 797 global $post; 798 } 799 800 if (is_numeric($post)) { 801 $post = get_post($post); 802 } 803 804 $editablePostTypes = apply_filters('cloudpress\companion\editable_post_types', array("page")); 805 806 if ( ! $post || ! in_array($post->post_type, $editablePostTypes)) { 807 return false; 808 } else { 809 if ($this->isWCPage($post)) { 810 return false; 811 } else { 812 if ($this->isMaintainable($post->ID) || $this->isFrontPage($post->ID)) { 813 $canEdit = true; 814 } 815 } 816 } 817 818 return apply_filters('cloudpresss\companion\can_edit_in_customizer', $canEdit, $post); 819 820 } 821 822 public function addEditInCustomizer($actions, $post) 823 { 824 if ($this->canEditInCustomizer($post)) { 825 826 $actions = array_merge( 827 array( 828 "cp_page_builder" => '<a href="javascript:void();" onclick="cp_open_page_in_customizer(' . $post->ID . ')" >Edit in Customizer</a>', 829 ), 830 $actions 831 ); 832 } 833 834 return $actions; 835 } 836 837 public function addEditInCustomizerPageButtons() 838 { 839 global $post; 840 841 if ($this->canEditInCustomizer($post)) { 842 echo '<a href="javascript:void();" onclick="cp_open_page_in_customizer(' . $post->ID . ')" class="button button-primary">' . __('Edit In Customizer', 'cloudpress-companion') . '</a>'; 843 } 844 } 845 846 public function addAdminScripts() 847 { 848 849 ?> 850 851 <style type="text/css"> 852 a:not(.button)[onclick*="cp_open_page_"] { 853 background-color: #0073aa; 854 color: #ffffff; 855 padding: 0.2em 0.8em; 856 line-height: 150%; 857 border-radius: 4px; 858 display: inline-block; 859 text-transform: uppercase; 860 font-size: 0.82em; 861 } 862 863 a:not(.button)[onclick*="cp_open_page_"]:hover { 864 background-color: #0081bd; 865 } 866 </style> 867 <?php 868 869 global $post; 870 871 if ( ! $post) { 872 return; 873 } 874 875 if ($this->isMultipage()) { 876 877 $title_placeholder = apply_filters('enter_title_here', __('Enter title here', 'materialis'), $post); 878 879 ?> 880 <style> 881 input[name=new-page-name-val] { 882 padding: 3px 8px; 883 font-size: 1.7em; 884 line-height: 100%; 885 height: 1.7em; 886 width: 100%; 887 outline: none; 888 margin: 0 0 3px; 889 background-color: #fff; 890 border-style: solid; 891 border-color: #c3c3c3; 892 border-width: 1px; 893 margin-bottom: 10px; 894 margin-top: 10px; 895 } 896 897 input[name=new-page-name-val].error { 898 border-color: #f39e9e; 899 border-style: solid; 900 color: #f39e9e; 901 } 902 903 h1.cp-open-in-custmizer { 904 font-size: 23px; 905 font-weight: 400; 906 margin: 0; 907 padding: 9px 0 4px 0; 908 line-height: 29px; 909 } 910 911 </style> 912 <div style="display: none;" id="open_page_in_customizer_set_name"> 913 <h1 class="cp-open-in-custmizer"><?php _e('Set a name for the new page', 'cloudpress-companion'); ?></h1> 914 <input placeholder="<?php echo $title_placeholder ?>" class="" name="new-page-name-val"/> 915 <button class="button button-primary" name="new-page-name-save"> <?php _e('Set Page Name', 'cloudpress-companion'); ?></button> 916 </div> 917 <script> 918 function cp_open_page_in_customizer(page) { 919 920 var isAutodraft = jQuery('[name="original_post_status"]').length ? jQuery('[name="original_post_status"]').val() === "auto-draft" : false; 921 922 function doAjaxCall(pageName) { 923 var data = { 924 action: 'cp_open_in_customizer', 925 page: page 926 }; 927 928 if (pageName) { 929 data['page_name'] = pageName; 930 } 931 932 jQuery.post(ajaxurl, data).done(function (response) { 933 934 window.location = response.trim(); 935 }); 936 } 937 938 if (isAutodraft) { 939 940 alert("<?php echo __('Page needs to be published before editing it in customizer', 'cloudpress-companion'); ?>"); 941 return; 942 943 var title = jQuery('[name="post_title"]').val(); 944 tb_show('Set Page Name', '#TB_inline?inlineId=open_page_in_customizer_set_name&height=150', false); 945 var TB_Window = jQuery('#TB_window').height('auto'); 946 947 var titleInput = TB_Window.find('[name="new-page-name-val"]'); 948 949 titleInput.val(title).on('keypress', function () { 950 jQuery(this).removeClass('error'); 951 }); 952 953 TB_Window.find('[name="new-page-name-save"]').off('click').on('click', function () { 954 var newTitle = titleInput.val().trim(); 955 if (newTitle.length == 0) { 956 titleInput.addClass('error'); 957 return; 958 } else { 959 doAjaxCall(newTitle); 960 } 961 }); 962 963 } else { 964 doAjaxCall(); 965 } 966 967 } 968 </script> 969 <?php 970 971 } 972 } 973 974 public function wrapPostContentInSection($post_id) 975 { 976 $post = get_post($post_id); 977 $content = $post->post_content; 978 979 if (trim($content)) { 980 981 $content = wpautop($content); 982 983 $content = "<div data-id='initial-content-section' data-export-id='initial-content-section' data-label='Initial Content' id='initial-content-section' class='content-section content-section-spacing'>\n" . 984 " <div class='gridContainer'>\n" . 985 " <div class='row'>\n\n" . 986 " <div class='col-xs-12 col-sm-12'>" . 987 " {$content}\n" . 988 " </div>\n" . 989 " </div>\n" . 990 " </div>\n" . 991 "</div>\n"; 992 993 if ( ! has_action('pre_post_update', 'wp_save_post_revision')) { 994 add_action('pre_post_update', 'wp_save_post_revision'); 995 } 996 997 wp_update_post(array( 998 'ID' => $post_id, 999 'post_content' => $content, 1000 )); 1001 } 1002 } 1003 1004 public function openPageInCustomizer() 1005 { 1006 $post_id = intval($_REQUEST['page']); 1007 $toMark = isset($_REQUEST['mark_as_editable']); 1008 1009 $post = get_post($post_id); 1010 1011 if ($post) { 1012 1013 if ($post->post_status === "auto-draft" || $post->post_status === "draft") { 1014 1015 /* 1016 wp_publish_post($post_id); 1017 1018 $title = isset($_REQUEST['page_name']) ? wp_kses_post($_REQUEST['page_name']) : __('Untitled Page - ' . date("Y-m-d H:i:s"), 'cloudpress-companion'); 1019 $new_slug = sanitize_title($title); 1020 wp_update_post(array( 1021 'ID' => $post_id, 1022 'post_title' => $title, 1023 'post_name' => $new_slug // do your thing here 1024 ));*/ 1025 } 1026 1027 $isMarked = get_post_meta($post_id, 'is_' . $this->themeSlug . '_maintainable_page', true); 1028 1029 if ( ! intval($isMarked) && $toMark) { 1030 update_post_meta($post_id, 'is_' . $this->themeSlug . '_maintainable_page', "1"); 1031 $this->wrapPostContentInSection($post_id); 1032 $template = get_post_meta($post_id, '_wp_page_template', true); 1033 if ( ! $template || $template === "default") { 1034 update_post_meta($post_id, '_wp_page_template', apply_filters('materialis_maintainable_default_template', "full-width-page.php")); 1035 } 1036 1037 do_action('cloudpress\ajax\after_maintainable_mark', $post_id); 1038 } 1039 1040 } 1041 1042 $url = $this->get_page_link($post_id); 1043 1044 ?> 1045 <?php echo admin_url('customize.php') ?>?url=<?php echo urlencode($url) ?> 1046 <?php 1047 1048 exit; 1049 } 1050 1051 public function get_page_link($post_id) 1052 { 1053 global $sitepress; 1054 $url = false; 1055 if ($sitepress) { 1056 $url = get_page_link($post_id); 1057 $args = array('element_id' => $post_id, 'element_type' => 'page'); 1058 $language_code = apply_filters('wpml_element_language_code', null, $args); 1059 $url = apply_filters('wpml_permalink', $url, $language_code); 1060 } 1061 1062 if ( ! $url) { 1063 $url = get_permalink($post_id); 1064 } 1065 1066 return $url; 1067 } 1068 1069 public function shortcodeRefresh() 1070 { 1071 if ( ! is_user_logged_in() || ! current_user_can('edit_theme_options')) { 1072 die(); 1073 } 1074 1075 add_filter('materialis_is_shortcode_refresh', '__return_true'); 1076 1077 $shortcode = isset($_REQUEST['shortcode']) ? $_REQUEST['shortcode'] : false; 1078 $context = isset($_REQUEST['context']) ? $_REQUEST['context'] : array(); 1079 1080 if ( ! $shortcode) { 1081 die(); 1082 } 1083 1084 $shortcode = base64_decode($shortcode); 1085 1086 $query = isset($context['query']) ? $context['query'] : array(); 1087 $content = ""; 1088 // $wp_query = new \WP_Query($query); 1089 if (count($query)) { 1090 query_posts($query); 1091 while (have_posts()) { 1092 the_post(); 1093 $content .= do_shortcode($shortcode); 1094 } 1095 1096 wp_reset_query(); 1097 } else { 1098 $content .= do_shortcode($shortcode); 1099 } 1100 1101 die($content); 1102 1103 } 1104 1105 public function addGoogleFonts() 1106 { 1107 $self = $this; 1108 1109 /** 1110 * Add preconnect for Google Fonts. 1111 */ 1112 add_filter('wp_resource_hints', function ($urls, $relation_type) use ($self) { 1113 if (wp_style_is($self->getThemeSlug() . '-fonts', 'queue') && 'preconnect' === $relation_type) { 1114 $urls[] = array( 1115 'href' => 'https://fonts.gstatic.com', 1116 'crossorigin', 1117 ); 1118 } 1119 1120 return $urls; 1121 }, 10, 2); 1122 1123 1124 } 1125 1126 1127 // SINGLETON 1128 1129 public static function instance() 1130 { 1131 return self::$instance; 1132 } 1133 1134 public static function letToNum($size) 1135 { 1136 $l = substr($size, -1); 1137 $ret = substr($size, 0, -1); 1138 switch (strtoupper($l)) { 1139 case 'P': 1140 $ret *= 1024; 1141 case 'T': 1142 $ret *= 1024; 1143 case 'G': 1144 $ret *= 1024; 1145 case 'M': 1146 $ret *= 1024; 1147 case 'K': 1148 $ret *= 1024; 1149 } 1150 1151 return $ret; 1152 } 1153 1154 public static function load($pluginFile) 1155 { 1156 $currentMemoryLimit = @ini_get('memory_limit'); 1157 $desiredMemory = '256M'; 1158 1159 if ($currentMemoryLimit) { 1160 if (self::letToNum($currentMemoryLimit) && self::letToNum($desiredMemory)) { 1161 @ini_set('memory_limit', $desiredMemory); 1162 } 1163 } 1164 1165 new \Materialis\Companion($pluginFile); 1166 } 1167 1168 public static function getTreeValueAt($tree, $path, $default = null) 1169 { 1170 $result = $tree; 1171 $keyParts = explode(":", $path); 1172 if (is_array($result)) { 1173 foreach ($keyParts as $part) { 1174 if ($result && isset($result[$part])) { 1175 $result = $result[$part]; 1176 } else { 1177 return $default; 1178 } 1179 } 1180 } 1181 1182 return $result; 1183 } 1184 1185 public static function prefixedMod($mod, $prefix = null) 1186 { 1187 $prefix = $prefix ? $prefix : self::instance()->getThemeSlug(); 1188 $prefix = str_replace("-", "_", $prefix); 1189 1190 return $prefix . "_" . $mod; 1191 } 1192 1193 public static function getThemeMod($mod, $default = false) 1194 { 1195 global $wp_customize; 1196 1197 if ($wp_customize) { 1198 $settings = $wp_customize->unsanitized_post_values(); 1199 1200 $key = "CP_AUTO_SETTING[" . $mod . "]"; 1201 if (isset($settings[$key])) { 1202 return $settings[$key]; 1203 } else { 1204 $exists = apply_filters('cloudpress\customizer\temp_mod_exists', false, $mod); 1205 if ($exists) { 1206 return apply_filters('cloudpress\customizer\temp_mod_content', false, $mod); 1207 } 1208 } 1209 } 1210 1211 if ($default === false) { 1212 $default = self::instance()->getCustomizerData("customizer:settings:{$mod}:wp_data:default"); 1213 $alternativeTextDomains = (array)self::instance()->getCustomizerData('alternativeTextDomains:' . self::instance()->getThemeSlug()); 1214 1215 if ( ! $default) { 1216 foreach ($alternativeTextDomains as $atd) { 1217 $mod = self::prefixedMod($mod, $atd); 1218 $default = self::instance()->getCustomizerData("customizer:settings:{$mod}:wp_data:default"); 1219 if ($default !== null) { 1220 break; 1221 } 1222 } 1223 } 1224 } 1225 1226 $result = $default; 1227 $temp = get_theme_mod(self::prefixedMod($mod), "CP_UNDEFINED_THEME_MOD"); 1228 if ($temp !== "CP_UNDEFINED_THEME_MOD") { 1229 $result = $temp; 1230 } else { 1231 $result = "CP_UNDEFINED_THEME_MOD"; 1232 $alternativeTextDomains = (array)self::instance()->getCustomizerData('alternativeTextDomains:' . self::instance()->getThemeSlug()); 1233 foreach ($alternativeTextDomains as $atd) { 1234 $temp = get_theme_mod(self::prefixedMod($mod, $atd), "CP_UNDEFINED_THEME_MOD"); 1235 if ($temp !== "CP_UNDEFINED_THEME_MOD") { 1236 $result = $temp; 1237 break; 1238 } 1239 } 1240 1241 if ($result === "CP_UNDEFINED_THEME_MOD") { 1242 $result = get_theme_mod($mod, $default); 1243 } 1244 } 1245 1246 return $result; 1247 } 1248 1249 public static function echoMod($mod, $default = false) 1250 { 1251 echo self::getThemeMod($mod, $default); 1252 } 1253 1254 public static function echoURLMod($mod, $default = false) 1255 { 1256 $value = self::getThemeMod($mod, $default); 1257 $value = str_replace('[tag_companion_uri]', self::instance()->themeDataURL(), $value); 1258 echo esc_url($value); 1259 } 1260 1261 public static function filterDefault($data) 1262 { 1263 if (is_array($data)) { 1264 $data = self::filterArrayDefaults($data); 1265 } else { 1266 $data = str_replace('[tag_companion_uri]', \Materialis\Companion::instance()->themeDataURL(), $data); 1267 $data = str_replace('[tag_theme_uri]', get_template_directory_uri(), $data); 1268 1269 $data = str_replace('[tag_companion_dir]', \Materialis\Companion::instance()->themeDataPath(), $data); 1270 $data = str_replace('[tag_theme_dir]', get_template_directory(), $data); 1271 $data = str_replace('[tag_style_uri]', get_stylesheet_directory_uri(), $data); 1272 } 1273 1274 return $data; 1275 } 1276 1277 public static function filterArrayDefaults($data) 1278 { 1279 foreach ($data as $key => $value) { 1280 $data[$key] = \Materialis\Companion::filterDefault($value); 1281 } 1282 1283 return $data; 1284 } 1285 1286 public static function dataURL($path = '') 1287 { 1288 return self::instance()->themeDataURL($path); 1289 } 1290 1291 public static function translateArgs($data) 1292 { 1293 if (isset($data['title'])) { 1294 $data['title'] = __($data['title'], 'cloudpress-companion'); 1295 } 1296 1297 if (isset($data['label'])) { 1298 $data['label'] = __($data['label'], 'cloudpress-companion'); 1299 } 1300 1301 if (isset($data['choices'])) { 1302 foreach ($data['choices'] as $key => $value) { 1303 if (strpos($value, "#") === false && is_string($key)) { 1304 $data['choices'][$key] = __($value, 'cloudpress-companion'); 1305 } 1306 } 1307 } 1308 1309 return $data; 1310 } 1311 1312 public static function loadJSONFile($path) 1313 { 1314 Companion::instance()->loadJSON($path); 1315 } 1316 }