File manager - Edit - /home/aresglob/public_html/wp/wp-includes/images/smilies/includes.tar
Back
functions.php 0000644 00000031301 15100113026 0007250 0 ustar 00 <?php /* * CookieAdmin * https://cookieadmin.net * (c) Softaculous Team */ // Are we being accessed directly ? if(!defined('COOKIEADMIN_PRO_VERSION')) { exit('Hacking Attempt !'); } function cookieadmin_pro_activation(){ update_option('cookieadmin_pro_version', COOKIEADMIN_PRO_VERSION); include_once(COOKIEADMIN_PRO_DIR . 'includes/database.php'); \CookieAdminPro\Database::activate(); } function cookieadmin_pro_is_network_active($plugin_name){ $is_network_wide = false; // Handling network site if(!is_multisite()){ return $is_network_wide; } $_tmp_plugins = get_site_option('active_sitewide_plugins'); if(!empty($_tmp_plugins) && preg_grep('/.*\/'.$plugin_name.'\.php$/', array_keys($_tmp_plugins))){ $is_network_wide = true; } return $is_network_wide; } function cookieadmin_pro_update_checker(){ $current_version = get_option('cookieadmin_pro_version', '0.0'); $version = (int) str_replace('.', '', $current_version); // No update required if($current_version == COOKIEADMIN_PRO_VERSION){ return true; } $is_network_wide = cookieadmin_pro_is_network_active('cookieadmin'); if($is_network_wide){ $free_ins = get_site_option('cookieadmin_free_installed'); }else{ $free_ins = get_option('cookieadmin_free_installed'); } // If plugin runing reached here it means CookieAdmin free installed if(empty($free_ins)){ if($is_network_wide){ update_site_option('cookieadmin_free_installed', time()); }else{ update_option('cookieadmin_free_installed', time()); } } update_option('cookieadmin_version_pro_nag', time()); update_option('cookieadmin_version_free_nag', time()); update_option('cookieadmin_pro_version', COOKIEADMIN_PRO_VERSION); } // Load license data function cookieadmin_pro_load_license($parent = 0){ global $cookieadmin, $lic_resp; $license_field = 'cookieadmin_license'; $license_api_url = COOKIEADMIN_API; // Save license if(!empty($parent) && is_string($parent) && strlen($parent) > 5){ $lic['license'] = $parent; // Load license of Soft Pro }elseif(!empty($parent)){ $license_field = 'softaculous_pro_license'; $lic = get_option('softaculous_pro_license', []); // My license }else{ $lic = get_option($license_field, []); } // Loaded license is a Soft Pro if(!empty($lic['license']) && preg_match('/^softwp/is', $lic['license'])){ $license_field = 'softaculous_pro_license'; $license_api_url = 'https://a.softaculous.com/softwp/'; $prods = apply_filters('softaculous_pro_products', []); }else{ $prods = []; } if(empty($lic['last_update'])){ $lic['last_update'] = time() - 86600; } // Update license details as well if(!empty($lic) && !empty($lic['license']) && (time() - @$lic['last_update']) >= 86400){ $url = $license_api_url.'/license.php?license='.$lic['license'].'&prods='.implode(',', $prods).'&url='.rawurlencode(site_url()); $resp = wp_remote_get($url); $lic_resp = $resp; //Did we get a response ? if(is_array($resp)){ $tosave = json_decode($resp['body'], true); //Is it the license ? if(!empty($tosave['license'])){ $tosave['last_update'] = time(); update_option($license_field, $tosave); $lic = $tosave; } } } // If the license is Free or Expired check for Softaculous Pro license if(empty($lic) || empty($lic['active'])){ if(function_exists('softaculous_pro_load_license')){ $softaculous_license = softaculous_pro_load_license(); if(!empty($softaculous_license['license']) && (!empty($softaculous_license['active']) || empty($lic['license'])) ){ $lic = $softaculous_license; } }elseif(empty($parent)){ $soft_lic = get_option('softaculous_pro_license', []); if(!empty($soft_lic)){ return cookieadmin_pro_load_license(1); } } } if(!empty($lic['license'])){ $cookieadmin['license'] = $lic; } } add_filter('softaculous_pro_products', 'cookieadmin_pro_softaculous_pro_products', 10, 1); function cookieadmin_pro_softaculous_pro_products($r = []){ $r['cookieadmin'] = 'cookieadmin'; return $r; } // Add our license key if ANY function cookieadmin_pro_updater_filter_args($queryArgs){ global $cookieadmin; if (!empty($cookieadmin['license']['license'])){ $queryArgs['license'] = $cookieadmin['license']['license']; } $queryArgs['url'] = rawurlencode(site_url()); return $queryArgs; } function cookieadmin_pro_ajax_handler(){ $cookieadmin_fn = (!empty($_REQUEST['cookieadmin_act']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_act'])) : ''); if(empty($cookieadmin_fn)){ wp_send_json_error(array('message' => 'Action not posted')); } // Define a whitelist of allowed functions $user_allowed_actions = array( 'save_consent' => 'save_consent' ); $admin_allowed_actions = array( 'export_logs' => 'export_logs', 'get_consent_logs' => 'get_consent_logs', 'dismiss_expired_licenses' => 'dismiss_expired_licenses', 'version_notice' => 'version_notice' ); if(array_key_exists($cookieadmin_fn, $user_allowed_actions)){ check_ajax_referer('cookieadmin_pro_js_nonce', 'cookieadmin_pro_security'); header_remove('Set-Cookie'); call_user_func('\CookieAdminPro\Enduser::'.$user_allowed_actions[$cookieadmin_fn]); }elseif(array_key_exists($cookieadmin_fn, $admin_allowed_actions)){ check_ajax_referer('cookieadmin_pro_admin_js_nonce', 'cookieadmin_pro_security'); if(!current_user_can('administrator')){ wp_send_json_error(array('message' => 'Sorry, but you do not have permissions to perform this action')); } call_user_func('\CookieAdminPro\Admin::'.$admin_allowed_actions[$cookieadmin_fn]); }else{ wp_send_json_error(array('message' => 'Unauthorized action')); } } // Handle the Check for update link and ask to install license key function cookieadmin_pro_updater_check_link($final_link){ global $cookieadmin; if(empty($cookieadmin['license']['license'])){ return '<a href="'.admin_url('admin.php?page=cookieadmin-license').'">'.esc_html__('Install CookieAdmin Pro License Key', 'cookieadmin-pro').'</a>'; } return $final_link; } // Prevent update of cookieadmin free function cookieadmin_pro_get_free_version_num(){ if(defined('COOKIEADMIN_VERSION')){ return COOKIEADMIN_VERSION; } // In case of cookieadmin deactive return cookieadmin_pro_file_get_version_num('cookieadmin/cookieadmin.php'); } // Prevent update of cookieadmin free function cookieadmin_pro_file_get_version_num($plugin){ // In case of cookieadmin deactive include_once(ABSPATH . 'wp-admin/includes/plugin.php'); $plugin_data = get_plugin_data(WP_PLUGIN_DIR . '/'.$plugin); if(empty($plugin_data)){ return false; } return $plugin_data['Version']; } // Prevent update of cookieadmin free function cookieadmin_pro_disable_manual_update_for_plugin($transient){ $plugin = 'cookieadmin/cookieadmin.php'; // Is update available? if(!isset($transient->response) || !isset($transient->response[$plugin])){ return $transient; } $free_version = cookieadmin_pro_get_free_version_num(); $pro_version = COOKIEADMIN_PRO_VERSION; if(!empty($GLOBALS['cookieadmin_pro_is_upgraded'])){ $pro_version = cookieadmin_pro_file_get_version_num('cookieadmin-pro/cookieadmin-pro.php'); } // Update the cookieadmin version to the equivalent of Pro version if(!empty($pro_version) && version_compare($free_version, $pro_version, '<')){ $transient->response[$plugin]->new_version = $pro_version; $transient->response[$plugin]->package = 'https://downloads.wordpress.org/plugin/cookieadmin.'.$pro_version.'.zip'; }else{ unset($transient->response[$plugin]); } return $transient; } // Auto update free version after update pro version function cookieadmin_pro_update_free_after_pro($upgrader_object, $options){ // Check if the action is an update for the plugins if($options['action'] != 'update' || $options['type'] != 'plugin'){ return; } // Define the slugs for the free and pro plugins $free_slug = 'cookieadmin/cookieadmin.php'; $pro_slug = 'cookieadmin-pro/cookieadmin-pro.php'; // Check if the pro plugin is in the list of updated plugins if( (isset($options['plugins']) && in_array($pro_slug, $options['plugins']) && !in_array($free_slug, $options['plugins'])) || (isset($options['plugin']) && $pro_slug == $options['plugin']) ){ // Trigger the update for the free plugin $current_version = cookieadmin_pro_get_free_version_num(); if(empty($current_version)){ return; } $GLOBALS['cookieadmin_pro_is_upgraded'] = true; // This will set the 'update_plugins' transient again wp_update_plugins(); // Check for updates for the free plugin $update_plugins = get_site_transient('update_plugins'); if(empty($update_plugins) || !isset($update_plugins->response[$free_slug]) || version_compare($update_plugins->response[$free_slug]->new_version, $current_version, '<=')){ return; } require_once(ABSPATH . 'wp-admin/includes/plugin.php'); require_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'); $skin = wp_doing_ajax()? new WP_Ajax_Upgrader_Skin() : null; $upgrader = new Plugin_Upgrader($skin); $upgraded = $upgrader->upgrade($free_slug); if(!is_wp_error($upgraded) && $upgraded){ // Re-active free plugins if( file_exists( WP_PLUGIN_DIR . '/'. $free_slug ) && is_plugin_inactive($free_slug) ){ activate_plugin($free_slug); // TODO for network } // Re-active pro plugins if( file_exists( WP_PLUGIN_DIR . '/'. $pro_slug ) && is_plugin_inactive($pro_slug) ){ activate_plugin($pro_slug); // TODO for network } } } } function cookieadmin_pro_api_url($main_server = 0, $suffix = 'cookieadmin'){ global $cookieadmin; $r = array( 'https://s0.softaculous.com/a/softwp/', 'https://s1.softaculous.com/a/softwp/', 'https://s2.softaculous.com/a/softwp/', 'https://s3.softaculous.com/a/softwp/', 'https://s4.softaculous.com/a/softwp/', 'https://s5.softaculous.com/a/softwp/', 'https://s7.softaculous.com/a/softwp/', 'https://s8.softaculous.com/a/softwp/' ); $mirror = $r[array_rand($r)]; if(!empty($main_server) && $main_server < 0){ return $mirror; } // If the license is newly issued, we need to fetch from API only if(!empty($main_server) || empty($cookieadmin['license']['last_edit']) || (!empty($cookieadmin['license']['last_edit']) && (time() - 3600) < $cookieadmin['license']['last_edit']) ){ $mirror = COOKIEADMIN_API; } if(!empty($suffix)){ $mirror = str_replace('/softwp', '/'.$suffix, $mirror); } return $mirror; } function cookieadmin_pro_plugins_expired($plugins){ $plugins[] = 'CookieAdmin'; return $plugins; } function cookieadmin_pro_expiry_notice(){ global $cookieadmin; // The combined notice for all Softaculous plugin to show that the license has expired $dismissed_at = get_option('softaculous_expired_licenses', 0); $expired_plugins = apply_filters('softaculous_expired_licenses', []); if( !empty($expired_plugins) && is_array($expired_plugins) && !defined('SOFTACULOUS_EXPIRY_LICENSES') && (empty($dismissed_at) || ($dismissed_at + WEEK_IN_SECONDS) < time()) ){ define('SOFTACULOUS_EXPIRY_LICENSES', true); // To make sure other plugins don't return a Notice echo '<div class="notice notice-error is-dismissible" id="cookieadmin-pro-expiry-notice"> <p>'.sprintf(__('Your SoftWP license has %1$sexpired%2$s. Please renew it to continue receiving uninterrupted updates and support for %3$s.', 'cookieadmin-pro'), '<font style="color:red;"><b>', '</b></font>', esc_html(implode(', ', $expired_plugins)) ). '</p> </div>'; wp_register_script('cookieadmin-pro-expiry-notice', '', ['jquery'], COOKIEADMIN_PRO_VERSION, true); wp_enqueue_script('cookieadmin-pro-expiry-notice'); wp_add_inline_script('cookieadmin-pro-expiry-notice', ' jQuery(document).ready(function(){ jQuery("#cookieadmin-pro-expiry-notice").on("click", ".notice-dismiss", function(e){ e.preventDefault(); let target = jQuery(e.target); let jEle = target.closest("#cookieadmin-pro-expiry-notice"); jEle.slideUp(); jQuery.post("'.admin_url('admin-ajax.php').'", { cookieadmin_pro_security : "'.wp_create_nonce('cookieadmin_pro_admin_js_nonce').'", action: "cookieadmin_pro_ajax_handler", cookieadmin_act: "dismiss_expired_licenses", }, function(res){ if(!res["success"]){ alert(res["data"]); } }).fail(function(data){ alert("There seems to be some issue dismissing this alert"); }); }); })'); } } function cookieadmin_pro_human_readable_time($timestamp){ $now = time(); $today_start = strtotime('today'); $yesterday_start = strtotime('yesterday'); if ($timestamp >= $today_start) { return 'Today ' . wp_date('g:i A T', $timestamp); } elseif ($timestamp >= $yesterday_start) { return 'Yesterday ' . wp_date('g:i A T', $timestamp); } else { return wp_date('M j Y g:i A T', $timestamp); // e.g., Dec 6 2024 6:00 AM UTC } } license.php 0000644 00000010463 15100113026 0006670 0 ustar 00 <?php /* * CookieAdmin Pro * https://cookieadmin.net * (c) Softaculous Team */ namespace CookieAdminPro; if(!defined('ABSPATH')){ die('Hacking Attempt!'); } class License{ static function cookieadmin_pro_license(){ global $lic_resp, $cookieadmin_lang, $cookieadmin_error, $cookieadmin_msg; if(empty($_POST['cookieadmin_pro_license_nonce']) || !wp_verify_nonce($_POST['cookieadmin_pro_license_nonce'], 'cookieadmin_pro_license')){ $cookieadmin_error = __('Security Check Failed', 'cookieadmin-pro'); return; } $license = !empty($_POST['cookieadmin_pro_license']) ? sanitize_key(wp_unslash($_POST['cookieadmin_pro_license'])) : ''; if(empty($license)){ $cookieadmin_error = __('The license key was not submitted', 'cookieadmin-pro'); return; } cookieadmin_pro_load_license($license); if(!is_array($lic_resp)){ $cookieadmin_error = __('The response was malformed<br>'.var_export($lic_resp, true), 'cookieadmin-pro'); return; } $json = json_decode($lic_resp['body'], true); if(empty($json['license'])){ $cookieadmin_error = __('The license key is invalid', 'cookieadmin-pro'); return; } $cookieadmin_msg = __('Successfully updated the license key', 'cookieadmin-pro'); } static function cookieadmin_show_license(){ global $cookieadmin; if(isset($_REQUEST['save_cookieadmin_pro_license'])){ \CookieAdminPro\License::cookieadmin_pro_license(); } ?> <?php \CookieAdmin\Admin::header_theme(__('License', 'cookieadmin-pro')); ?> <div class="cookieadmin-pro-license-content wrap" > <div class="cookieadmin-pro-tab-group" style=" width:100% ;background:white; padding:20px;"> <table class="wp-list-table fixed striped users cookieadmin-pro-license-table" cellspacing="1" border="0" width="100%" cellpadding="10" align="center"> <tbody> <tr> <th align="left" width="25%"><?php esc_html_e('CookieAdmin Version', 'cookieadmin-pro'); ?></th> <td><?php echo COOKIEADMIN_PRO_VERSION.' ('.esc_html__('Pro Version', 'cookieadmin-pro').')'; ?> </td> </tr> <tr> <th align="left" valign="top"><?php esc_html_e('CookieAdmin License', 'cookieadmin-pro'); ?></th> <td align="left"> <form method="post" action=""> <?php echo (defined('COOKIEADMIN_PREMIUM') && empty($cookieadmin['license']['license']) ? '<span style="color:red">'.esc_html__('Unlicensed', 'cookieadmin-pro').'</span> ' : '')?> <input type="hidden" name="cookieadmin_pro_license_nonce" value="<?php echo wp_create_nonce('cookieadmin_pro_license');?>"/> <input type="text" name="cookieadmin_pro_license" value="<?php echo (empty($cookieadmin['license']['license']) ? '': esc_html($cookieadmin['license']['license']))?>" size="30" placeholder="e.g. COOKA-11111-22222-33333-44444" style="width:300px;"> <input name="save_cookieadmin_pro_license" class="cookieadmin-btn cookieadmin-btn-primary dosmtp-sumbit-licence" value="Update License" type="submit"> </form> <?php if(!empty($cookieadmin['license']['license'])){ $expires = $cookieadmin['license']['expires']; $expires = substr($expires, 0, 4).'/'.substr($expires, 4, 2).'/'.substr($expires, 6); echo '<div style="margin-top:10px;">'.esc_html__('License Status', 'cookieadmin-pro').' : '.(empty($cookieadmin['license']['status_txt']) ? 'N.A.' : wp_kses_post($cookieadmin['license']['status_txt'])).' '.($cookieadmin['license']['expires'] <= date('Ymd') ? esc_html__('License Expires', 'cookieadmin-pro').' : <span style="color:red;">'.esc_attr($expires).'</span>' : (empty($cookieadmin['license']['has_plid']) ? esc_html__('License Expires', 'cookieadmin-pro').' : '.esc_html($expires) : '')).' </div>'; }?> </td> </tr> <tr> <th align="left">URL</th> <td><?php echo esc_url(get_site_url()); ?></td> </tr> <tr> <th align="left">Path</th> <td><?php echo ABSPATH; ?></td> </tr> <tr> <th align="left"><?php esc_html_e('Server\'s IP Address', 'cookieadmin-pro') ?></th> <td><?php echo esc_attr($_SERVER['SERVER_ADDR']); ?></td> </tr> </tbody> </table> </div> </div> <?php \CookieAdmin\Admin::footer_theme(); } } plugin-update-checker.php 0000644 00000151325 15100113026 0011431 0 ustar 00 <?php /** * Plugin Update Checker Library 3.2 * http://w-shadow.com/ * * Copyright 2016 Janis Elsts * Released under the MIT license. See license.txt for details. */ if ( !class_exists('CookieAdminUpdateChecker_3_2', false) ): /** * A custom plugin update checker. * * @author Janis Elsts * @copyright 2016 * @version 3.2 * @access public */ class CookieAdminUpdateChecker_3_2 { public $metadataUrl = ''; //The URL of the plugin's metadata file. public $pluginAbsolutePath = ''; //Full path of the main plugin file. public $pluginFile = ''; //Plugin filename relative to the plugins directory. Many WP APIs use this to identify plugins. public $slug = ''; //Plugin slug. public $optionName = ''; //Where to store the update info. public $muPluginFile = ''; //For MU plugins, the plugin filename relative to the mu-plugins directory. public $debugMode = false; //Set to TRUE to enable error reporting. Errors are raised using trigger_error() //and should be logged to the standard PHP error log. public $scheduler; protected $upgraderStatus; private $debugBarPlugin = null; private $cachedInstalledVersion = null; private $metadataHost = ''; //The host component of $metadataUrl. /** * Class constructor. * * @param string $metadataUrl The URL of the plugin's metadata file. * @param string $pluginFile Fully qualified path to the main plugin file. * @param string $slug The plugin's 'slug'. If not specified, the filename part of $pluginFile sans '.php' will be used as the slug. * @param integer $checkPeriod How often to check for updates (in hours). Defaults to checking every 12 hours. Set to 0 to disable automatic update checks. * @param string $optionName Where to store book-keeping info about update checks. Defaults to 'external_updates-$slug'. * @param string $muPluginFile Optional. The plugin filename relative to the mu-plugins directory. */ public function __construct($metadataUrl, $pluginFile, $slug = '', $checkPeriod = 12, $optionName = '', $muPluginFile = ''){ $this->metadataUrl = $metadataUrl; $this->pluginAbsolutePath = $pluginFile; $this->pluginFile = plugin_basename($this->pluginAbsolutePath); $this->muPluginFile = $muPluginFile; $this->slug = $slug; $this->optionName = $optionName; $this->debugMode = (bool)(constant('WP_DEBUG')); //If no slug is specified, use the name of the main plugin file as the slug. //For example, 'my-cool-plugin/cool-plugin.php' becomes 'cool-plugin'. if ( empty($this->slug) ){ $this->slug = basename($this->pluginFile, '.php'); } //Plugin slugs must be unique. $slugCheckFilter = 'puc_is_slug_in_use-' . $this->slug; $slugUsedBy = apply_filters($slugCheckFilter, false); if ( $slugUsedBy ) { $this->triggerError(sprintf( 'Plugin slug "%s" is already in use by %s. Slugs must be unique.', htmlentities($this->slug), htmlentities($slugUsedBy) ), E_USER_ERROR); } add_filter($slugCheckFilter, array($this, 'getAbsolutePath')); if ( empty($this->optionName) ){ $this->optionName = 'external_updates-' . $this->slug; } //Backwards compatibility: If the plugin is a mu-plugin but no $muPluginFile is specified, assume //it's the same as $pluginFile given that it's not in a subdirectory (WP only looks in the base dir). if ( (strpbrk($this->pluginFile, '/\\') === false) && $this->isUnknownMuPlugin() ) { $this->muPluginFile = $this->pluginFile; } $this->scheduler = $this->createScheduler($checkPeriod); $this->upgraderStatus = new CookieAdmin_PucUpgraderStatus_3_2(); $this->installHooks(); } /** * Create an instance of the scheduler. * * This is implemented as a method to make it possible for plugins to subclass the update checker * and substitute their own scheduler. * * @param int $checkPeriod * @return CookieAdmin_PucScheduler_3_2 */ protected function createScheduler($checkPeriod) { return new CookieAdmin_PucScheduler_3_2($this, $checkPeriod); } /** * Install the hooks required to run periodic update checks and inject update info * into WP data structures. * * @return void */ protected function installHooks(){ //Override requests for plugin information add_filter('plugins_api', array($this, 'injectInfo'), 20, 3); //Insert our update info into the update array maintained by WP. add_filter('site_transient_update_plugins', array($this,'injectUpdate')); //WP 3.0+ add_filter('transient_update_plugins', array($this,'injectUpdate')); //WP 2.8+ add_filter('site_transient_update_plugins', array($this, 'injectTranslationUpdates')); add_filter('plugin_row_meta', array($this, 'addCheckForUpdatesLink'), 10, 2); add_action('admin_init', array($this, 'handleManualCheck')); add_action('all_admin_notices', array($this, 'displayManualCheckResult')); //Clear the version number cache when something - anything - is upgraded or WP clears the update cache. add_filter('upgrader_post_install', array($this, 'clearCachedVersion')); add_action('delete_site_transient_update_plugins', array($this, 'clearCachedVersion')); //Clear translation updates when WP clears the update cache. //This needs to be done directly because the library doesn't actually remove obsolete plugin updates, //it just hides them (see getUpdate()). We can't do that with translations - too much disk I/O. add_action('delete_site_transient_update_plugins', array($this, 'clearCachedTranslationUpdates')); if ( did_action('plugins_loaded') ) { $this->initDebugBarPanel(); } else { add_action('plugins_loaded', array($this, 'initDebugBarPanel')); } //Rename the update directory to be the same as the existing directory. add_filter('upgrader_source_selection', array($this, 'fixDirectoryName'), 10, 3); //Enable language support (i18n). load_plugin_textdomain('plugin-update-checker', false, plugin_basename(dirname(__FILE__)) . '/languages'); //Allow HTTP requests to the metadata URL even if it's on a local host. $this->metadataHost = @parse_url($this->metadataUrl, PHP_URL_HOST); add_filter('http_request_host_is_external', array($this, 'allowMetadataHost'), 10, 2); } /** * Explicitly allow HTTP requests to the metadata URL. * * WordPress has a security feature where the HTTP API will reject all requests that are sent to * another site hosted on the same server as the current site (IP match), a local host, or a local * IP, unless the host exactly matches the current site. * * This feature is opt-in (at least in WP 4.4). Apparently some people enable it. * * That can be a problem when you're developing your plugin and you decide to host the update information * on the same server as your test site. Update requests will mysteriously fail. * * We fix that by adding an exception for the metadata host. * * @param bool $allow * @param string $host * @return bool */ public function allowMetadataHost($allow, $host) { if ( strtolower($host) === strtolower($this->metadataHost) ) { return true; } return $allow; } /** * Retrieve plugin info from the configured API endpoint. * * @uses wp_remote_get() * * @param array $queryArgs Additional query arguments to append to the request. Optional. * @return CookieAdminInfo_3_2 */ public function requestInfo($queryArgs = array()){ //Query args to append to the URL. Plugins can add their own by using a filter callback (see addQueryArgFilter()). $installedVersion = $this->getInstalledVersion(); $queryArgs['installed_version'] = ($installedVersion !== null) ? $installedVersion : ''; $queryArgs = apply_filters('puc_request_info_query_args-'.$this->slug, $queryArgs); //Various options for the wp_remote_get() call. Plugins can filter these, too. $options = array( 'timeout' => 10, //seconds 'headers' => array( 'Accept' => 'application/json' ), ); $options = apply_filters('puc_request_info_options-'.$this->slug, $options); //The plugin info should be at 'http://your-api.com/url/here/$slug/info.json' $url = $this->metadataUrl; if ( !empty($queryArgs) ){ $url = add_query_arg($queryArgs, $url); } $result = wp_remote_get( $url, $options ); //Try to parse the response $status = $this->validateApiResponse($result); $pluginInfo = null; if ( !is_wp_error($status) ){ $pluginInfo = CookieAdminInfo_3_2::fromJson($result['body']); if ( $pluginInfo !== null ) { $pluginInfo->filename = $this->pluginFile; $pluginInfo->slug = $this->slug; } } else { $this->triggerError( sprintf('The URL %s does not point to a valid plugin metadata file. ', $url) . $status->get_error_message(), E_USER_WARNING ); } $pluginInfo = apply_filters('puc_request_info_result-'.$this->slug, $pluginInfo, $result); return $pluginInfo; } /** * Check if $result is a successful update API response. * * @param array|WP_Error $result * @return true|WP_Error */ private function validateApiResponse($result) { if ( is_wp_error($result) ) { /** @var WP_Error $result */ return new WP_Error($result->get_error_code(), 'WP HTTP Error: ' . $result->get_error_message()); } if ( !isset($result['response']['code']) ) { return new WP_Error('puc_no_response_code', 'wp_remote_get() returned an unexpected result.'); } if ( $result['response']['code'] !== 200 ) { return new WP_Error( 'puc_unexpected_response_code', 'HTTP response code is ' . $result['response']['code'] . ' (expected: 200)' ); } if ( empty($result['body']) ) { return new WP_Error('puc_empty_response', 'The metadata file appears to be empty.'); } return true; } /** * Retrieve the latest update (if any) from the configured API endpoint. * * @uses CookieAdminUpdateChecker::requestInfo() * * @return CookieAdminUpdate_3_2 An instance of CookieAdminUpdate, or NULL when no updates are available. */ public function requestUpdate(){ //For the sake of simplicity, this function just calls requestInfo() //and transforms the result accordingly. $pluginInfo = $this->requestInfo(array('checking_for_updates' => '1')); if ( $pluginInfo == null ){ return null; } $update = CookieAdminUpdate_3_2::fromCookieAdminInfo($pluginInfo); //Keep only those translation updates that apply to this site. $update->translations = $this->filterApplicableTranslations($update->translations); return $update; } /** * Filter a list of translation updates and return a new list that contains only updates * that apply to the current site. * * @param array $translations * @return array */ private function filterApplicableTranslations($translations) { $languages = array_flip(array_values(get_available_languages())); $installedTranslations = wp_get_installed_translations('plugins'); if ( isset($installedTranslations[$this->slug]) ) { $installedTranslations = $installedTranslations[$this->slug]; } else { $installedTranslations = array(); } $applicableTranslations = array(); foreach($translations as $translation) { //Does it match one of the available core languages? $isApplicable = array_key_exists($translation->language, $languages); //Is it more recent than an already-installed translation? if ( isset($installedTranslations[$translation->language]) ) { $updateTimestamp = strtotime($translation->updated); $installedTimestamp = strtotime($installedTranslations[$translation->language]['PO-Revision-Date']); $isApplicable = $updateTimestamp > $installedTimestamp; } if ( $isApplicable ) { $applicableTranslations[] = $translation; } } return $applicableTranslations; } /** * Get the currently installed version of the plugin. * * @return string Version number. */ public function getInstalledVersion(){ if ( isset($this->cachedInstalledVersion) ) { return $this->cachedInstalledVersion; } $pluginHeader = $this->getPluginHeader(); if ( isset($pluginHeader['Version']) ) { $this->cachedInstalledVersion = $pluginHeader['Version']; return $pluginHeader['Version']; } else { //This can happen if the filename points to something that is not a plugin. $this->triggerError( sprintf( "Can't to read the Version header for '%s'. The filename is incorrect or is not a plugin.", $this->pluginFile ), E_USER_WARNING ); return null; } } /** * Get plugin's metadata from its file header. * * @return array */ protected function getPluginHeader() { if ( !is_file($this->pluginAbsolutePath) ) { //This can happen if the plugin filename is wrong. $this->triggerError( sprintf( "Can't to read the plugin header for '%s'. The file does not exist.", $this->pluginFile ), E_USER_WARNING ); return array(); } if ( !function_exists('get_plugin_data') ){ /** @noinspection PhpIncludeInspection */ require_once( ABSPATH . '/wp-admin/includes/plugin.php' ); } return get_plugin_data($this->pluginAbsolutePath, false, false); } /** * Check for plugin updates. * The results are stored in the DB option specified in $optionName. * * @return CookieAdminUpdate_3_2|null */ public function checkForUpdates(){ $installedVersion = $this->getInstalledVersion(); //Fail silently if we can't find the plugin or read its header. if ( $installedVersion === null ) { $this->triggerError( sprintf('Skipping update check for %s - installed version unknown.', $this->pluginFile), E_USER_WARNING ); return null; } $state = $this->getUpdateState(); if ( empty($state) ){ $state = new stdClass; $state->lastCheck = 0; $state->checkedVersion = ''; $state->update = null; } $state->lastCheck = time(); $state->checkedVersion = $installedVersion; $this->setUpdateState($state); //Save before checking in case something goes wrong $state->update = $this->requestUpdate(); $this->setUpdateState($state); return $this->getUpdate(); } /** * Load the update checker state from the DB. * * @return stdClass|null */ public function getUpdateState() { $state = get_site_option($this->optionName, null); if ( empty($state) || !is_object($state)) { $state = null; } if ( isset($state, $state->update) && is_object($state->update) ) { $state->update = CookieAdminUpdate_3_2::fromObject($state->update); } return $state; } /** * Persist the update checker state to the DB. * * @param StdClass $state * @return void */ private function setUpdateState($state) { if ( isset($state->update) && is_object($state->update) && method_exists($state->update, 'toStdClass') ) { $update = $state->update; /** @var CookieAdminUpdate_3_2 $update */ $state->update = $update->toStdClass(); } update_site_option($this->optionName, $state); } /** * Reset update checker state - i.e. last check time, cached update data and so on. * * Call this when your plugin is being uninstalled, or if you want to * clear the update cache. */ public function resetUpdateState() { delete_site_option($this->optionName); } /** * Intercept plugins_api() calls that request information about our plugin and * use the configured API endpoint to satisfy them. * * @see plugins_api() * * @param mixed $result * @param string $action * @param array|object $args * @return mixed */ public function injectInfo($result, $action = null, $args = null){ $relevant = ($action == 'plugin_information') && isset($args->slug) && ( ($args->slug == $this->slug) || ($args->slug == dirname($this->pluginFile)) ); if ( !$relevant ) { return $result; } $pluginInfo = $this->requestInfo(); $pluginInfo = apply_filters('puc_pre_inject_info-' . $this->slug, $pluginInfo); if ( $pluginInfo ) { return $pluginInfo->toWpFormat(); } return $result; } /** * Insert the latest update (if any) into the update list maintained by WP. * * @param StdClass $updates Update list. * @return StdClass Modified update list. */ public function injectUpdate($updates){ //Is there an update to insert? $update = $this->getUpdate(); //No update notifications for mu-plugins unless explicitly enabled. The MU plugin file //is usually different from the main plugin file so the update wouldn't show up properly anyway. if ( $this->isUnknownMuPlugin() ) { $update = null; } if ( !empty($update) ) { //Let plugins filter the update info before it's passed on to WordPress. $update = apply_filters('puc_pre_inject_update-' . $this->slug, $update); $updates = $this->addUpdateToList($updates, $update); } else { //Clean up any stale update info. $updates = $this->removeUpdateFromList($updates); } return $updates; } /** * @param StdClass|null $updates * @param CookieAdminUpdate_3_2 $updateToAdd * @return StdClass */ private function addUpdateToList($updates, $updateToAdd) { if ( !is_object($updates) ) { $updates = new stdClass(); $updates->response = array(); } $wpUpdate = $updateToAdd->toWpFormat(); $pluginFile = $this->pluginFile; if ( $this->isMuPlugin() ) { //WP does not support automatic update installation for mu-plugins, but we can still display a notice. $wpUpdate->package = null; $pluginFile = $this->muPluginFile; } $updates->response[$pluginFile] = $wpUpdate; return $updates; } /** * @param stdClass|null $updates * @return stdClass|null */ private function removeUpdateFromList($updates) { if ( isset($updates, $updates->response) ) { unset($updates->response[$this->pluginFile]); if ( !empty($this->muPluginFile) ) { unset($updates->response[$this->muPluginFile]); } } return $updates; } /** * Insert translation updates into the list maintained by WordPress. * * @param stdClass $updates * @return stdClass */ public function injectTranslationUpdates($updates) { $translationUpdates = $this->getTranslationUpdates(); if ( empty($translationUpdates) ) { return $updates; } //Being defensive. if ( !is_object($updates) ) { $updates = new stdClass(); } if ( !isset($updates->translations) ) { $updates->translations = array(); } //In case there's a name collision with a plugin hosted on wordpress.org, //remove any preexisting updates that match our plugin. $translationType = 'plugin'; $filteredTranslations = array(); foreach($updates->translations as $translation) { if ( ($translation['type'] === $translationType) && ($translation['slug'] === $this->slug) ) { continue; } $filteredTranslations[] = $translation; } $updates->translations = $filteredTranslations; //Add our updates to the list. foreach($translationUpdates as $update) { $convertedUpdate = array_merge( array( 'type' => $translationType, 'slug' => $this->slug, 'autoupdate' => 0, //AFAICT, WordPress doesn't actually use the "version" field for anything. //But lets make sure it's there, just in case. 'version' => isset($update->version) ? $update->version : ('1.' . strtotime($update->updated)), ), (array)$update ); $updates->translations[] = $convertedUpdate; } return $updates; } /** * Rename the update directory to match the existing plugin directory. * * When WordPress installs a plugin or theme update, it assumes that the ZIP file will contain * exactly one directory, and that the directory name will be the same as the directory where * the plugin/theme is currently installed. * * GitHub and other repositories provide ZIP downloads, but they often use directory names like * "project-branch" or "project-tag-hash". We need to change the name to the actual plugin folder. * * This is a hook callback. Don't call it from a plugin. * * @param string $source The directory to copy to /wp-content/plugins. Usually a subdirectory of $remoteSource. * @param string $remoteSource WordPress has extracted the update to this directory. * @param WP_Upgrader $upgrader * @return string|WP_Error */ public function fixDirectoryName($source, $remoteSource, $upgrader) { global $wp_filesystem; /** @var WP_Filesystem_Base $wp_filesystem */ //Basic sanity checks. if ( !isset($source, $remoteSource, $upgrader, $upgrader->skin, $wp_filesystem) ) { return $source; } //If WordPress is upgrading anything other than our plugin, leave the directory name unchanged. if ( !$this->isPluginBeingUpgraded($upgrader) ) { return $source; } //Rename the source to match the existing plugin directory. $pluginDirectoryName = dirname($this->pluginFile); if ( $pluginDirectoryName === '.' ) { return $source; } $correctedSource = trailingslashit($remoteSource) . $pluginDirectoryName . '/'; if ( $source !== $correctedSource ) { //The update archive should contain a single directory that contains the rest of plugin files. Otherwise, //WordPress will try to copy the entire working directory ($source == $remoteSource). We can't rename //$remoteSource because that would break WordPress code that cleans up temporary files after update. if ( $this->isBadDirectoryStructure($remoteSource) ) { return new WP_Error( 'puc-incorrect-directory-structure', sprintf( 'The directory structure of the update is incorrect. All plugin files should be inside ' . 'a directory named <span class="code">%s</span>, not at the root of the ZIP file.', htmlentities($this->slug) ) ); } /** @var WP_Upgrader_Skin $upgrader->skin */ $upgrader->skin->feedback(sprintf( 'Renaming %s to %s…', '<span class="code">' . basename($source) . '</span>', '<span class="code">' . $pluginDirectoryName . '</span>' )); if ( $wp_filesystem->move($source, $correctedSource, true) ) { $upgrader->skin->feedback('Plugin directory successfully renamed.'); return $correctedSource; } else { return new WP_Error( 'puc-rename-failed', 'Unable to rename the update to match the existing plugin directory.' ); } } return $source; } /** * Check for incorrect update directory structure. An update must contain a single directory, * all other files should be inside that directory. * * @param string $remoteSource Directory path. * @return bool */ private function isBadDirectoryStructure($remoteSource) { global $wp_filesystem; /** @var WP_Filesystem_Base $wp_filesystem */ $sourceFiles = $wp_filesystem->dirlist($remoteSource); if ( is_array($sourceFiles) ) { $sourceFiles = array_keys($sourceFiles); $firstFilePath = trailingslashit($remoteSource) . $sourceFiles[0]; return (count($sourceFiles) > 1) || (!$wp_filesystem->is_dir($firstFilePath)); } //Assume it's fine. return false; } /** * Is there and update being installed RIGHT NOW, for this specific plugin? * * @param WP_Upgrader|null $upgrader The upgrader that's performing the current update. * @return bool */ public function isPluginBeingUpgraded($upgrader = null) { return $this->upgraderStatus->isPluginBeingUpgraded($this->pluginFile, $upgrader); } /** * Get the details of the currently available update, if any. * * If no updates are available, or if the last known update version is below or equal * to the currently installed version, this method will return NULL. * * Uses cached update data. To retrieve update information straight from * the metadata URL, call requestUpdate() instead. * * @return CookieAdminUpdate_3_2|null */ public function getUpdate() { $state = $this->getUpdateState(); /** @var StdClass $state */ //Is there an update available? if ( isset($state, $state->update) ) { $update = $state->update; //Check if the update is actually newer than the currently installed version. $installedVersion = $this->getInstalledVersion(); if ( ($installedVersion !== null) && version_compare($update->version, $installedVersion, '>') ){ $update->filename = $this->pluginFile; return $update; } } return null; } /** * Get a list of available translation updates. * * This method will return an empty array if there are no updates. * Uses cached update data. * * @return array */ public function getTranslationUpdates() { $state = $this->getUpdateState(); if ( isset($state, $state->update, $state->update->translations) ) { return $state->update->translations; } return array(); } /** * Remove all cached translation updates. * * @see wp_clean_update_cache */ public function clearCachedTranslationUpdates() { $state = $this->getUpdateState(); if ( isset($state, $state->update, $state->update->translations) ) { $state->update->translations = array(); $this->setUpdateState($state); } } /** * Add a "Check for updates" link to the plugin row in the "Plugins" page. By default, * the new link will appear after the "Visit plugin site" link. * * You can change the link text by using the "puc_manual_check_link-$slug" filter. * Returning an empty string from the filter will disable the link. * * @param array $pluginMeta Array of meta links. * @param string $pluginFile * @return array */ public function addCheckForUpdatesLink($pluginMeta, $pluginFile) { $isRelevant = ($pluginFile == $this->pluginFile) || (!empty($this->muPluginFile) && $pluginFile == $this->muPluginFile); if ( $isRelevant && current_user_can('update_plugins') ) { $linkUrl = wp_nonce_url( add_query_arg( array( 'puc_check_for_updates' => 1, 'puc_slug' => $this->slug, ), self_admin_url('plugins.php') ), 'puc_check_for_updates' ); $linkText = apply_filters('puc_manual_check_link-' . $this->slug, __('Check for updates', 'plugin-update-checker')); if ( !empty($linkText) ) { $final_link = sprintf('<a href="%s">%s</a>', esc_attr($linkUrl), $linkText); $pluginMeta[] = apply_filters('puc_manual_final_check_link-' . $this->slug, $final_link); } } return $pluginMeta; } /** * Check for updates when the user clicks the "Check for updates" link. * @see self::addCheckForUpdatesLink() * * @return void */ public function handleManualCheck() { $shouldCheck = isset($_GET['puc_check_for_updates'], $_GET['puc_slug']) && $_GET['puc_slug'] == $this->slug && current_user_can('update_plugins') && check_admin_referer('puc_check_for_updates'); if ( $shouldCheck ) { $update = $this->checkForUpdates(); $status = ($update === null) ? 'no_update' : 'update_available'; wp_redirect(add_query_arg( array( 'puc_update_check_result' => $status, 'puc_slug' => $this->slug, ), self_admin_url('plugins.php') )); } } /** * Display the results of a manual update check. * @see self::handleManualCheck() * * You can change the result message by using the "puc_manual_check_message-$slug" filter. */ public function displayManualCheckResult() { if ( isset($_GET['puc_update_check_result'], $_GET['puc_slug']) && ($_GET['puc_slug'] == $this->slug) ) { $status = strval($_GET['puc_update_check_result']); if ( $status == 'no_update' ) { $message = __('This plugin is up to date.', 'plugin-update-checker'); } else if ( $status == 'update_available' ) { $message = __('A new version of this plugin is available.', 'plugin-update-checker'); } else { $message = sprintf(__('Unknown update checker status "%s"', 'plugin-update-checker'), htmlentities($status)); } printf( '<div class="updated notice is-dismissible"><p>%s</p></div>', apply_filters('puc_manual_check_message-' . $this->slug, $message, $status) ); } } /** * Check if the plugin file is inside the mu-plugins directory. * * @return bool */ protected function isMuPlugin() { static $cachedResult = null; if ( $cachedResult === null ) { //Convert both paths to the canonical form before comparison. $muPluginDir = realpath(WPMU_PLUGIN_DIR); $pluginPath = realpath($this->pluginAbsolutePath); if(!empty($muPluginDir)){ $cachedResult = (strpos($pluginPath, $muPluginDir) === 0); }else{ $cachedResult = false; } } return $cachedResult; } /** * MU plugins are partially supported, but only when we know which file in mu-plugins * corresponds to this plugin. * * @return bool */ protected function isUnknownMuPlugin() { return empty($this->muPluginFile) && $this->isMuPlugin(); } /** * Clear the cached plugin version. This method can be set up as a filter (hook) and will * return the filter argument unmodified. * * @param mixed $filterArgument * @return mixed */ public function clearCachedVersion($filterArgument = null) { $this->cachedInstalledVersion = null; return $filterArgument; } /** * Get absolute path to the main plugin file. * * @return string */ public function getAbsolutePath() { return $this->pluginAbsolutePath; } /** * Register a callback for filtering query arguments. * * The callback function should take one argument - an associative array of query arguments. * It should return a modified array of query arguments. * * @uses add_filter() This method is a convenience wrapper for add_filter(). * * @param callable $callback * @return void */ public function addQueryArgFilter($callback){ add_filter('puc_request_info_query_args-'.$this->slug, $callback); } /** * Register a callback for filtering arguments passed to wp_remote_get(). * * The callback function should take one argument - an associative array of arguments - * and return a modified array or arguments. See the WP documentation on wp_remote_get() * for details on what arguments are available and how they work. * * @uses add_filter() This method is a convenience wrapper for add_filter(). * * @param callable $callback * @return void */ public function addHttpRequestArgFilter($callback){ add_filter('puc_request_info_options-'.$this->slug, $callback); } /** * Register a callback for filtering the plugin info retrieved from the external API. * * The callback function should take two arguments. If the plugin info was retrieved * successfully, the first argument passed will be an instance of CookieAdminInfo. Otherwise, * it will be NULL. The second argument will be the corresponding return value of * wp_remote_get (see WP docs for details). * * The callback function should return a new or modified instance of CookieAdminInfo or NULL. * * @uses add_filter() This method is a convenience wrapper for add_filter(). * * @param callable $callback * @return void */ public function addResultFilter($callback){ add_filter('puc_request_info_result-'.$this->slug, $callback, 10, 2); } /** * Register a callback for one of the update checker filters. * * Identical to add_filter(), except it automatically adds the "puc_" prefix * and the "-$plugin_slug" suffix to the filter name. For example, "request_info_result" * becomes "puc_request_info_result-your_plugin_slug". * * @param string $tag * @param callable $callback * @param int $priority * @param int $acceptedArgs */ public function addFilter($tag, $callback, $priority = 10, $acceptedArgs = 1) { add_filter('puc_' . $tag . '-' . $this->slug, $callback, $priority, $acceptedArgs); } /** * Initialize the update checker Debug Bar plugin/add-on thingy. */ public function initDebugBarPanel() { $debugBarPlugin = dirname(__FILE__) . '/debug-bar-plugin.php'; if ( class_exists('Debug_Bar', false) && file_exists($debugBarPlugin) ) { /** @noinspection PhpIncludeInspection */ require_once $debugBarPlugin; $this->debugBarPlugin = new CookieAdmin_PucDebugBarPlugin_3_2($this); } } /** * Trigger a PHP error, but only when $debugMode is enabled. * * @param string $message * @param int $errorType */ protected function triggerError($message, $errorType) { if ( $this->debugMode ) { trigger_error($message, $errorType); } } } endif; if ( !class_exists('CookieAdminInfo_3_2', false) ): /** * A container class for holding and transforming various plugin metadata. * * @author Janis Elsts * @copyright 2016 * @version 3.2 * @access public */ class CookieAdminInfo_3_2 { //Most fields map directly to the contents of the plugin's info.json file. //See the relevant docs for a description of their meaning. public $name; public $slug; public $version; public $homepage; public $sections = array(); public $banners; public $translations = array(); public $download_url; public $author; public $author_homepage; public $requires; public $tested; public $upgrade_notice; public $rating; public $num_ratings; public $downloaded; public $active_installs; public $last_updated; public $id = 0; //The native WP.org API returns numeric plugin IDs, but they're not used for anything. public $filename; //Plugin filename relative to the plugins directory. /** * Create a new instance of CookieAdminInfo from JSON-encoded plugin info * returned by an external update API. * * @param string $json Valid JSON string representing plugin info. * @return CookieAdminInfo_3_2|null New instance of CookieAdminInfo, or NULL on error. */ public static function fromJson($json){ /** @var StdClass $apiResponse */ $apiResponse = json_decode($json); if ( empty($apiResponse) || !is_object($apiResponse) ){ trigger_error( "Failed to parse plugin metadata. Try validating your .json file with http://jsonlint.com/", E_USER_NOTICE ); return null; } $valid = self::validateMetadata($apiResponse); if ( is_wp_error($valid) ){ trigger_error($valid->get_error_message(), E_USER_NOTICE); return null; } $info = new self(); foreach(get_object_vars($apiResponse) as $key => $value){ $info->$key = $value; } //json_decode decodes assoc. arrays as objects. We want it as an array. $info->sections = (array)$info->sections; return $info; } /** * Very, very basic validation. * * @param StdClass $apiResponse * @return bool|WP_Error */ protected static function validateMetadata($apiResponse) { if ( !isset($apiResponse->name, $apiResponse->version) || empty($apiResponse->name) || empty($apiResponse->version) ) { return new WP_Error( 'puc-invalid-metadata', "The plugin metadata file does not contain the required 'name' and/or 'version' keys." ); } return true; } /** * Transform plugin info into the format used by the native WordPress.org API * * @return object */ public function toWpFormat(){ $info = new stdClass; //The custom update API is built so that many fields have the same name and format //as those returned by the native WordPress.org API. These can be assigned directly. $sameFormat = array( 'name', 'slug', 'version', 'requires', 'tested', 'rating', 'upgrade_notice', 'num_ratings', 'downloaded', 'active_installs', 'homepage', 'last_updated', ); foreach($sameFormat as $field){ if ( isset($this->$field) ) { $info->$field = $this->$field; } else { $info->$field = null; } } //Other fields need to be renamed and/or transformed. $info->download_link = $this->download_url; $info->author = $this->getFormattedAuthor(); $info->sections = array_merge(array('description' => ''), $this->sections); if ( !empty($this->banners) ) { //WP expects an array with two keys: "high" and "low". Both are optional. //Docs: https://wordpress.org/plugins/about/faq/#banners $info->banners = is_object($this->banners) ? get_object_vars($this->banners) : $this->banners; $info->banners = array_intersect_key($info->banners, array('high' => true, 'low' => true)); } return $info; } protected function getFormattedAuthor() { if ( !empty($this->author_homepage) ){ return sprintf('<a href="%s">%s</a>', $this->author_homepage, $this->author); } return $this->author; } } endif; if ( !class_exists('CookieAdminUpdate_3_2', false) ): /** * A simple container class for holding information about an available update. * * @author Janis Elsts * @copyright 2016 * @version 3.2 * @access public */ class CookieAdminUpdate_3_2 { public $id = 0; public $slug; public $version; public $homepage; public $download_url; public $upgrade_notice; public $tested; public $translations = array(); public $filename; //Plugin filename relative to the plugins directory. private static $fields = array( 'id', 'slug', 'version', 'homepage', 'tested', 'download_url', 'upgrade_notice', 'filename', 'translations' ); /** * Create a new instance of CookieAdminUpdate from its JSON-encoded representation. * * @param string $json * @return CookieAdminUpdate_3_2|null */ public static function fromJson($json){ //Since update-related information is simply a subset of the full plugin info, //we can parse the update JSON as if it was a plugin info string, then copy over //the parts that we care about. $pluginInfo = CookieAdminInfo_3_2::fromJson($json); if ( $pluginInfo != null ) { return self::fromCookieAdminInfo($pluginInfo); } else { return null; } } /** * Create a new instance of CookieAdminUpdate based on an instance of CookieAdminInfo. * Basically, this just copies a subset of fields from one object to another. * * @param CookieAdminInfo_3_2 $info * @return CookieAdminUpdate_3_2 */ public static function fromCookieAdminInfo($info){ return self::fromObject($info); } /** * Create a new instance of CookieAdminUpdate by copying the necessary fields from * another object. * * @param StdClass|CookieAdminInfo_3_2|CookieAdminUpdate_3_2 $object The source object. * @return CookieAdminUpdate_3_2 The new copy. */ public static function fromObject($object) { $update = new self(); $fields = self::$fields; if ( !empty($object->slug) ) { $fields = apply_filters('puc_retain_fields-' . $object->slug, $fields); } foreach($fields as $field){ if (property_exists($object, $field)) { $update->$field = $object->$field; } } return $update; } /** * Create an instance of StdClass that can later be converted back to * a CookieAdminUpdate. Useful for serialization and caching, as it avoids * the "incomplete object" problem if the cached value is loaded before * this class. * * @return StdClass */ public function toStdClass() { $object = new stdClass(); $fields = self::$fields; if ( !empty($this->slug) ) { $fields = apply_filters('puc_retain_fields-' . $this->slug, $fields); } foreach($fields as $field){ if (property_exists($this, $field)) { $object->$field = $this->$field; } } return $object; } /** * Transform the update into the format used by WordPress native plugin API. * * @return object */ public function toWpFormat(){ $update = new stdClass; $update->id = $this->id; $update->slug = $this->slug; $update->new_version = $this->version; $update->url = $this->homepage; $update->package = $this->download_url; $update->tested = $this->tested; $update->plugin = $this->filename; if ( !empty($this->upgrade_notice) ){ $update->upgrade_notice = $this->upgrade_notice; } return $update; } } endif; if ( !class_exists('CookieAdmin_PucScheduler_3_2', false) ): /** * The scheduler decides when and how often to check for updates. * It calls @see CookieAdminUpdateChecker::checkForUpdates() to perform the actual checks. * * @version 3.2 */ class CookieAdmin_PucScheduler_3_2 { public $checkPeriod = 12; //How often to check for updates (in hours). public $throttleRedundantChecks = false; //Check less often if we already know that an update is available. public $throttledCheckPeriod = 72; /** * @var CookieAdminUpdateChecker_3_2 */ protected $updateChecker; private $cronHook = null; /** * Scheduler constructor. * * @param CookieAdminUpdateChecker_3_2 $updateChecker * @param int $checkPeriod How often to check for updates (in hours). */ public function __construct($updateChecker, $checkPeriod) { $this->updateChecker = $updateChecker; $this->checkPeriod = $checkPeriod; //Set up the periodic update checks $this->cronHook = 'check_plugin_updates-' . $this->updateChecker->slug; if ( $this->checkPeriod > 0 ){ //Trigger the check via Cron. //Try to use one of the default schedules if possible as it's less likely to conflict //with other plugins and their custom schedules. $defaultSchedules = array( 1 => 'hourly', 12 => 'twicedaily', 24 => 'daily', ); if ( array_key_exists($this->checkPeriod, $defaultSchedules) ) { $scheduleName = $defaultSchedules[$this->checkPeriod]; } else { //Use a custom cron schedule. $scheduleName = 'every' . $this->checkPeriod . 'hours'; add_filter('cron_schedules', array($this, '_addCustomSchedule')); } if ( !wp_next_scheduled($this->cronHook) && !defined('WP_INSTALLING') ) { wp_schedule_event(time(), $scheduleName, $this->cronHook); } add_action($this->cronHook, array($this, 'maybeCheckForUpdates')); register_deactivation_hook($this->updateChecker->pluginFile, array($this, '_removeUpdaterCron')); //In case Cron is disabled or unreliable, we also manually trigger //the periodic checks while the user is browsing the Dashboard. add_action( 'admin_init', array($this, 'maybeCheckForUpdates') ); //Like WordPress itself, we check more often on certain pages. /** @see wp_update_plugins */ add_action('load-update-core.php', array($this, 'maybeCheckForUpdates')); add_action('load-plugins.php', array($this, 'maybeCheckForUpdates')); add_action('load-update.php', array($this, 'maybeCheckForUpdates')); //This hook fires after a bulk update is complete. add_action('upgrader_process_complete', array($this, 'maybeCheckForUpdates'), 11, 0); } else { //Periodic checks are disabled. wp_clear_scheduled_hook($this->cronHook); } } /** * Check for updates if the configured check interval has already elapsed. * Will use a shorter check interval on certain admin pages like "Dashboard -> Updates" or when doing cron. * * You can override the default behaviour by using the "puc_check_now-$slug" filter. * The filter callback will be passed three parameters: * - Current decision. TRUE = check updates now, FALSE = don't check now. * - Last check time as a Unix timestamp. * - Configured check period in hours. * Return TRUE to check for updates immediately, or FALSE to cancel. * * This method is declared public because it's a hook callback. Calling it directly is not recommended. */ public function maybeCheckForUpdates(){ if ( empty($this->checkPeriod) ){ return; } $state = $this->updateChecker->getUpdateState(); $shouldCheck = empty($state) || !isset($state->lastCheck) || ( (time() - $state->lastCheck) >= $this->getEffectiveCheckPeriod() ); //Let plugin authors substitute their own algorithm. $shouldCheck = apply_filters( 'puc_check_now-' . $this->updateChecker->slug, $shouldCheck, (!empty($state) && isset($state->lastCheck)) ? $state->lastCheck : 0, $this->checkPeriod ); if ( $shouldCheck ) { $this->updateChecker->checkForUpdates(); } } /** * Calculate the actual check period based on the current status and environment. * * @return int Check period in seconds. */ protected function getEffectiveCheckPeriod() { $currentFilter = current_filter(); if ( in_array($currentFilter, array('load-update-core.php', 'upgrader_process_complete')) ) { //Check more often when the user visits "Dashboard -> Updates" or does a bulk update. $period = 60; } else if ( in_array($currentFilter, array('load-plugins.php', 'load-update.php')) ) { //Also check more often on the "Plugins" page and /wp-admin/update.php. $period = 3600; } else if ( $this->throttleRedundantChecks && ($this->updateChecker->getUpdate() !== null) ) { //Check less frequently if it's already known that an update is available. $period = $this->throttledCheckPeriod * 3600; } else if ( defined('DOING_CRON') && constant('DOING_CRON') ) { //WordPress cron schedules are not exact, so lets do an update check even //if slightly less than $checkPeriod hours have elapsed since the last check. $cronFuzziness = 20 * 60; $period = $this->checkPeriod * 3600 - $cronFuzziness; } else { $period = $this->checkPeriod * 3600; } return $period; } /** * Add our custom schedule to the array of Cron schedules used by WP. * * @param array $schedules * @return array */ public function _addCustomSchedule($schedules){ if ( $this->checkPeriod && ($this->checkPeriod > 0) ){ $scheduleName = 'every' . $this->checkPeriod . 'hours'; $schedules[$scheduleName] = array( 'interval' => $this->checkPeriod * 3600, 'display' => sprintf('Every %d hours', $this->checkPeriod), ); } return $schedules; } /** * Remove the scheduled cron event that the library uses to check for updates. * * @return void */ public function _removeUpdaterCron(){ wp_clear_scheduled_hook($this->cronHook); } /** * Get the name of the update checker's WP-cron hook. Mostly useful for debugging. * * @return string */ public function getCronHookName() { return $this->cronHook; } } endif; if ( !class_exists('CookieAdmin_PucUpgraderStatus_3_2', false) ): /** * A utility class that helps figure out which plugin WordPress is upgrading. * * It may seem strange to have an separate class just for that, but the task is surprisingly complicated. * Core classes like Plugin_Upgrader don't expose the plugin file name during an in-progress update (AFAICT). * This class uses a few workarounds and heuristics to get the file name. */ class CookieAdmin_PucUpgraderStatus_3_2 { private $upgradedPluginFile = null; //The plugin that is currently being upgraded by WordPress. public function __construct() { //Keep track of which plugin WordPress is currently upgrading. add_filter('upgrader_pre_install', array($this, 'setUpgradedPlugin'), 10, 2); add_filter('upgrader_package_options', array($this, 'setUpgradedPluginFromOptions'), 10, 1); add_filter('upgrader_post_install', array($this, 'clearUpgradedPlugin'), 10, 1); add_action('upgrader_process_complete', array($this, 'clearUpgradedPlugin'), 10, 1); } /** * Is there and update being installed RIGHT NOW, for a specific plugin? * * Caution: This method is unreliable. WordPress doesn't make it easy to figure out what it is upgrading, * and upgrader implementations are liable to change without notice. * * @param string $pluginFile The plugin to check. * @param WP_Upgrader|null $upgrader The upgrader that's performing the current update. * @return bool True if the plugin identified by $pluginFile is being upgraded. */ public function isPluginBeingUpgraded($pluginFile, $upgrader = null) { if ( isset($upgrader) ) { $upgradedPluginFile = $this->getPluginBeingUpgradedBy($upgrader); if ( !empty($upgradedPluginFile) ) { $this->upgradedPluginFile = $upgradedPluginFile; } } return ( !empty($this->upgradedPluginFile) && ($this->upgradedPluginFile === $pluginFile) ); } /** * Get the file name of the plugin that's currently being upgraded. * * @param Plugin_Upgrader|WP_Upgrader $upgrader * @return string|null */ private function getPluginBeingUpgradedBy($upgrader) { if ( !isset($upgrader, $upgrader->skin) ) { return null; } //Figure out which plugin is being upgraded. $pluginFile = null; $skin = $upgrader->skin; if ( $skin instanceof Plugin_Upgrader_Skin ) { if ( isset($skin->plugin) && is_string($skin->plugin) && ($skin->plugin !== '') ) { $pluginFile = $skin->plugin; } } elseif ( isset($skin->plugin_info) && is_array($skin->plugin_info) ) { //This case is tricky because Bulk_Plugin_Upgrader_Skin (etc) doesn't actually store the plugin //filename anywhere. Instead, it has the plugin headers in $plugin_info. So the best we can //do is compare those headers to the headers of installed plugins. $pluginFile = $this->identifyPluginByHeaders($skin->plugin_info); } return $pluginFile; } /** * Identify an installed plugin based on its headers. * * @param array $searchHeaders The plugin file header to look for. * @return string|null Plugin basename ("foo/bar.php"), or NULL if we can't identify the plugin. */ private function identifyPluginByHeaders($searchHeaders) { if ( !function_exists('get_plugins') ){ /** @noinspection PhpIncludeInspection */ require_once( ABSPATH . '/wp-admin/includes/plugin.php' ); } $installedPlugins = get_plugins(); $matches = array(); foreach($installedPlugins as $pluginBasename => $headers) { $diff1 = array_diff_assoc($headers, $searchHeaders); $diff2 = array_diff_assoc($searchHeaders, $headers); if ( empty($diff1) && empty($diff2) ) { $matches[] = $pluginBasename; } } //It's possible (though very unlikely) that there could be two plugins with identical //headers. In that case, we can't unambiguously identify the plugin that's being upgraded. if ( count($matches) !== 1 ) { return null; } return reset($matches); } /** * @access private * * @param mixed $input * @param array $hookExtra * @return mixed Returns $input unaltered. */ public function setUpgradedPlugin($input, $hookExtra) { if (!empty($hookExtra['plugin']) && is_string($hookExtra['plugin'])) { $this->upgradedPluginFile = $hookExtra['plugin']; } else { $this->upgradedPluginFile = null; } return $input; } /** * @access private * * @param array $options * @return array */ public function setUpgradedPluginFromOptions($options) { if (isset($options['hook_extra']['plugin']) && is_string($options['hook_extra']['plugin'])) { $this->upgradedPluginFile = $options['hook_extra']['plugin']; } else { $this->upgradedPluginFile = null; } return $options; } /** * @access private * * @param mixed $input * @return mixed Returns $input unaltered. */ public function clearUpgradedPlugin($input = null) { $this->upgradedPluginFile = null; return $input; } } endif; if ( !class_exists('CookieAdmin_PucFactory', false) ): /** * A factory that builds instances of other classes from this library. * * When multiple versions of the same class have been loaded (e.g. CookieAdminUpdateChecker 1.2 * and 1.3), this factory will always use the latest available version. Register class * versions by calling {@link CookieAdmin_PucFactory::addVersion()}. * * At the moment it can only build instances of the CookieAdminUpdateChecker class. Other classes * are intended mainly for internal use and refer directly to specific implementations. If you * want to instantiate one of them anyway, you can use {@link CookieAdmin_PucFactory::getLatestClassVersion()} * to get the class name and then create it with <code>new $class(...)</code>. */ class CookieAdmin_PucFactory { protected static $classVersions = array(); protected static $sorted = false; /** * Create a new instance of CookieAdminUpdateChecker. * * @see CookieAdminUpdateChecker::__construct() * * @param $metadataUrl * @param $pluginFile * @param string $slug * @param int $checkPeriod * @param string $optionName * @param string $muPluginFile * @return CookieAdminUpdateChecker_3_2 */ public static function buildUpdateChecker($metadataUrl, $pluginFile, $slug = '', $checkPeriod = 12, $optionName = '', $muPluginFile = '') { $class = self::getLatestClassVersion('CookieAdminUpdateChecker'); return new $class($metadataUrl, $pluginFile, $slug, $checkPeriod, $optionName, $muPluginFile); } /** * Get the specific class name for the latest available version of a class. * * @param string $class * @return string|null */ public static function getLatestClassVersion($class) { if ( !self::$sorted ) { self::sortVersions(); } if ( isset(self::$classVersions[$class]) ) { return reset(self::$classVersions[$class]); } else { return null; } } /** * Sort available class versions in descending order (i.e. newest first). */ protected static function sortVersions() { foreach ( self::$classVersions as $class => $versions ) { uksort($versions, array(__CLASS__, 'compareVersions')); self::$classVersions[$class] = $versions; } self::$sorted = true; } protected static function compareVersions($a, $b) { return -version_compare($a, $b); } /** * Register a version of a class. * * @access private This method is only for internal use by the library. * * @param string $generalClass Class name without version numbers, e.g. 'CookieAdminUpdateChecker'. * @param string $versionedClass Actual class name, e.g. 'CookieAdminUpdateChecker_1_2'. * @param string $version Version number, e.g. '1.2'. */ public static function addVersion($generalClass, $versionedClass, $version) { if ( !isset(self::$classVersions[$generalClass]) ) { self::$classVersions[$generalClass] = array(); } self::$classVersions[$generalClass][$version] = $versionedClass; self::$sorted = false; } } endif; //Register classes defined in this file with the factory. CookieAdmin_PucFactory::addVersion('CookieAdminUpdateChecker', 'CookieAdminUpdateChecker_3_2', '3.2'); CookieAdmin_PucFactory::addVersion('CookieAdminUpdate', 'CookieAdminUpdate_3_2', '3.2'); CookieAdmin_PucFactory::addVersion('CookieAdminInfo', 'CookieAdminInfo_3_2', '3.2'); CookieAdmin_PucFactory::addVersion('CookieAdmin_PucGitHubChecker', 'CookieAdmin_PucGitHubChecker_3_2', '3.2'); database.php 0000644 00000002453 15100113026 0007012 0 ustar 00 <?php namespace CookieAdminPro; if(!defined('COOKIEADMIN_PRO_VERSION') || !defined('ABSPATH')){ die('Hacking Attempt'); } class Database{ static $wpdb = ''; static $consent_table = ''; static function activate(){ global $wpdb; self::$wpdb = $wpdb; self::$consent_table = esc_sql(self::$wpdb->prefix . 'cookieadmin_consents'); self::cookieadmin_create_tables(); } static function cookieadmin_create_tables() { $charset_collate = self::$wpdb->get_charset_collate(); require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); //Create Consent table $sql = "CREATE TABLE IF NOT EXISTS ".self::$consent_table." ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, consent_id VARCHAR(128) NOT NULL UNIQUE, -- Designed to store up to 128 characters for future expansion user_ip VARBINARY(16) DEFAULT NULL, -- For storing anonymized IP (IPv4 or IPv6) consent_time INT NOT NULL, country VARCHAR(150) DEFAULT NULL, -- Full country name browser TEXT DEFAULT NULL, -- Browser User agent string domain VARCHAR(255) DEFAULT NULL, -- Domain from which consent was submitted consent_status VARCHAR(50) NOT NULL -- Stores 'accepted', 'rejected', 'partially accepted', etc. ) {$charset_collate};"; dbDelta($sql); } } enduser.php 0000644 00000012524 15100113026 0006713 0 ustar 00 <?php namespace CookieAdminPro; if(!defined('COOKIEADMIN_PRO_VERSION') || !defined('ABSPATH')){ die('Hacking Attempt'); } class Enduser{ static $http_cookies; static function enqueue_scripts(){ wp_enqueue_script('cookieadmin_pro_js', COOKIEADMIN_PRO_PLUGIN_URL . 'assets/js/consent.js', [], COOKIEADMIN_PRO_VERSION, 'async'); $vars['ajax_url'] = admin_url('admin-ajax.php'); $vars['nonce'] = wp_create_nonce('cookieadmin_pro_js_nonce'); $vars['home_url'] = home_url(); // cookieadmin_r_print($policy);die(); wp_localize_script('cookieadmin_pro_js', 'cookieadmin_pro_vars', $vars); } // TODO static function cookieadmin_check_rate_limit($ip) { global $wpdb; //First Fetch stored rate limit for this IP $table_name = esc_sql($wpdb->prefix . 'cookie_consent_logs'); $rate_limit_count = $wpdb->get_var($wpdb->prepare( "SELECT rate_limit_count FROM $table_name WHERE user_ip = %s", $ip )); if (!$rate_limit_count) { return true; // No rate limit set, allow request } $time_window = 10; // Time window in seconds as of now we are checking for 10 seconds, we can pass this value as function's paramater as well. $transient_key = 'rate_limit_' . md5($ip); $requests = get_transient($transient_key); if (!$requests) { $requests = []; } $current_time = time(); $requests = array_filter($requests, function($timestamp) use ($current_time, $time_window) { return ($current_time - $timestamp) < $time_window; }); if (count($requests) >= $rate_limit_count) { return false; //Too many requests } $requests[] = $current_time; set_transient($transient_key, $requests, $time_window); return true; //Request allowed } // TODO static function get_location_details($ip){ global $cookieadmin; $return = array(); $api_url = cookieadmin_pro_api_url(-1, 'softwp'); $url = $api_url.'ipinfo.php?ip='.rawurlencode($ip).'&license='.$cookieadmin['license']['license'].'&url='.rawurlencode(site_url()); $response = wp_remote_get($url); if(is_wp_error($response)){ return $return; } $body = wp_remote_retrieve_body($response); $data = json_decode($body, true); if(empty($data)){ return $return; } return $data; } static function consent_exists($consent_id){ global $wpdb; $table_name = esc_sql($wpdb->prefix . 'cookieadmin_consents'); $result = $wpdb->get_var( $wpdb->prepare("SELECT id FROM $table_name WHERE consent_id = %s", $consent_id) ); return !empty($result); } static function anonymize_ip($ip) { if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { // Replace last octet with 0 return preg_replace('/\.\d+$/', '.0', $ip); } elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { // Replace last segment with :: return preg_replace('/:[0-9a-fA-F]+$/', '::', $ip); } return $ip; // fallback if invalid IP } static function generate_consent_id() { return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x', wp_rand(0, 0xffff), wp_rand(0, 0xffff), wp_rand(0, 0xffff), wp_rand(0, 0x0fff) | 0x4000, // version 4 wp_rand(0, 0x3fff) | 0x8000, // variant wp_rand(0, 0xffff), wp_rand(0, 0xffff), wp_rand(0, 0xffff) ); } static function save_consent(){ global $wpdb; if(empty($_POST['cookieadmin_preference'])){ exit(1); } $default_prefrencs = array('accept', 'reject', 'functional', 'analytics', 'marketing'); $prefrnc = json_decode(sanitize_text_field(wp_unslash($_POST['cookieadmin_preference']))); foreach($prefrnc as $k => $preff){ if(!in_array($preff, $default_prefrencs)){ array_splice($prefrnc, $k, 1); } } $prefrnc = json_encode($prefrnc, true); $user_ip = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : ''; $location = \CookieAdminPro\Enduser::get_location_details($user_ip); $masked_user_ip = \CookieAdminPro\Enduser::anonymize_ip($user_ip); $country = !empty($location['country']) ? sanitize_text_field($location['country']) : ''; $browser = isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])) : ''; $domain = wp_parse_url(home_url())['host']; $table_name = esc_sql($wpdb->prefix . 'cookieadmin_consents'); $consent_id = !empty($_POST['cookieadmin_consent_id']) ? sanitize_text_field(wp_unslash($_POST['cookieadmin_consent_id'])) : ''; $data = array( 'user_ip' => inet_pton($masked_user_ip), 'consent_time' => time(), 'country' => $country, 'browser' => $browser, 'domain' => $domain, 'consent_status' => $prefrnc ); //Save consent in DB if(!empty($consent_id) && \CookieAdminPro\Enduser::consent_exists($consent_id)){ $format = array('%s', '%d', '%s', '%s', '%s', '%s'); $where = array('consent_id' => $consent_id); $where_format = array('%s'); $inserted = $wpdb->update($table_name, $data, $where, $format, $where_format); }else{ $consent_id = \CookieAdminPro\Enduser::generate_consent_id(); $data['consent_id'] = $consent_id; $format = array('%s', '%d', '%s', '%s', '%s', '%s', '%s'); $inserted = $wpdb->insert($table_name, $data, $format); } if (false === $inserted) { wp_send_json_error(array('response' => 'Error saving consent data.')); } else { wp_send_json_success(array('response' => $consent_id)); } } } admin.php 0000644 00000027514 15100113026 0006343 0 ustar 00 <?php namespace CookieAdminPro; if(!defined('COOKIEADMIN_PRO_VERSION') || !defined('ABSPATH')){ die('Hacking Attempt'); } class Admin{ static function enqueue_scripts(){ $request_uri = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : ''; $is_admin_page = basename(parse_url($request_uri, PHP_URL_PATH)); if(!is_admin() || empty($_GET['page']) || !in_array($_GET['page'], array('cookieadmin-consent-logs')) || $is_admin_page != 'admin.php'){ return false; } // Add condition to load only on our settings page //Consent Page Css wp_enqueue_style('cookieadmin-pro-style', COOKIEADMIN_PRO_PLUGIN_URL . 'assets/css/cookie.css', [], COOKIEADMIN_PRO_VERSION); wp_enqueue_script('cookieadmin_pro_js', COOKIEADMIN_PRO_PLUGIN_URL . 'assets/js/cookie.js', [], COOKIEADMIN_PRO_VERSION); $policy['admin_url'] = admin_url('admin-ajax.php'); $policy['cookieadmin_nonce'] = wp_create_nonce('cookieadmin_pro_admin_js_nonce'); //cookieadmin_r_print($policy);die(); wp_localize_script('cookieadmin_pro_js', 'cookieadmin_pro_policy', $policy); } //Add Main Menu static function plugin_menu(){ } static function show_settings($title = 'CookieAdmin Pro'){ } static function cookieadmin_pro_table_exists($table_name) { global $wpdb; $query = $wpdb->prepare("SHOW TABLES LIKE %s", $table_name); return $wpdb->get_var($query) === $table_name; } static function show_consent_logs(){ global $cookieadmin_lang, $cookieadmin_error, $cookieadmin_msg; \CookieAdmin\Admin::header_theme(__('Consent Logs', 'cookieadmin-pro')); $log_data = \CookieAdminPro\Admin::get_consent_logs(); $consent_logs = (!empty($log_data['logs']) ? $log_data['logs'] : array()); echo ' <div class="cookieadmin_pro_consent-wrap" style="max-width: 85vw;"> <form action="" method="post"> <div class="cookieadmin_consent-contents"> <div class="cookieadmin_consent"> <div class="contents cookieadmin_manager"> <div class="cookieadmin-setting cookieadmin-manager-consent-logs"> <label class="cookieadmin-title"></label> <div class="cookieadmin-setting-contents cookieadmin-consent-logs"> <input type="button" class="cookieadmin-btn cookieadmin-btn-primary cookieadmin-consent-logs-export" value="Export CSV"> </div> <div class="cookieadmin-manager-scan-result"> <table class="cookieadmin-table cookieadmin-consent-logs-result"> <thead> <tr> <th width="30%">'.esc_html__('Consent Id', 'cookieadmin-pro').'</th> <th width="20%">'.esc_html__('Status', 'cookieadmin-pro').'</th> <th>'.esc_html__('Country', 'cookieadmin-pro').'</th> <th>'.esc_html__('User IP (Anonymized)', 'cookieadmin-pro').'</th> <th>'.esc_html__('Time', 'cookieadmin-pro').'</th> </tr> </thead> <tbody>'; if(!empty($consent_logs)){ foreach ($consent_logs as $log){ $status_badge = 'warning'; if(strtolower($log['consent_status_raw']) == 'accept'){ $status_badge = 'success'; }elseif(strtolower($log['consent_status_raw']) == 'reject'){ $status_badge = 'danger'; } echo ' <tr> <td>'.esc_html($log['consent_id']).'</td> <td><span class="cookieadmin-badge cookieadmin-'.$status_badge.'">'.esc_html($log['consent_status']).'</span></td> <td>'.(!empty($log['country']) ? esc_html($log['country']) : '—').'</td> <td>'.esc_html($log['user_ip']).'</td> <td>'.esc_html($log['consent_time']).'</td> </tr>'; } }else{ echo ' <tr> <td colspan="4">'.esc_html__('No consent logs recorded yet!', 'cookieadmin-pro').'</td> </tr>'; } echo ' </tbody> </table> </div>'; if(!empty($consent_logs)){ echo ' <div class="cookieadmin-consent-logs-pagination" style="text-align:right;"> '.esc_html__('Displaying', 'cookieadmin-pro').' <span class="displaying-num">'.esc_html($log_data['min_items'].' - '.$log_data['max_items']).'</span> '.esc_html__('of', 'cookieadmin-pro').' <span class="max-num">'.esc_html($log_data['total_logs']).'</span> '.esc_html__('item(s)', 'cookieadmin-pro').' <!-- First Page Consent logs --> <a class="first-page cookieadmin-logs-paginate" id="cookieadmin-first-consent-logs" href="javascript:void(0)"> <span aria-hidden="true">«</span> </a> <!-- Previous Page Consent logs --> <a class="prev-page cookieadmin-logs-paginate" id="cookieadmin-previous-consent-logs" href="javascript:void(0)"> <span aria-hidden="true">‹</span> </a> <!-- Current Page logs --> <span class="paging-input"> <label for="current-page-selector" class="screen-reader-text">Current Page</label> <input class="current-page" id="current-page-selector" name="current-page-selector" value="'.(!empty($log_data['current_page']) ? esc_attr($log_data['current_page']) : '').'" size="3" aria-describedby="table-paging" type="text" style="text-align: center;"> <span class="tablenav-paging-text"> of <span class="total-pages">'.esc_html($log_data['total_pages']).'</span> </span> </span> <!-- Next Page Consent Logs --> <a class="next-page cookieadmin-logs-paginate" id="cookieadmin-next-consent-logs" href="javascript:void(0)"> <span aria-hidden="true">›</span> </a> <!-- Last Page Consent logs --> <a class="last-page cookieadmin-logs-paginate" id="cookieadmin-last-consent-logs" href="javascript:void(0)"> <span aria-hidden="true">»</span> </a> </div>'; } echo ' </div> </div> </div>'; wp_nonce_field('cookieadmin_pro_admin_nonce', 'cookieadmin_pro_security'); echo '<br/> <br/> </div> </form> </div>'; \CookieAdmin\Admin::footer_theme(); } //Load Consent logs data from the database static function get_consent_logs(){ global $wpdb; if($_POST && count($_POST) > 0){ $nonce_slug = (wp_doing_ajax() ? 'cookieadmin_pro_admin_js_nonce' : 'cookieadmin_pro_admin_nonce'); check_admin_referer($nonce_slug, 'cookieadmin_pro_security'); } if(!current_user_can('administrator')){ wp_send_json_error(array('message' => 'Sorry, but you do not have permissions to perform this action')); } $num_items = 0; $table_name = esc_sql($wpdb->prefix . 'cookieadmin_consents'); $current_page = isset($_POST['current_page']) ? intval($_POST['current_page']) : 1; if (!\CookieAdminPro\Admin::cookieadmin_pro_table_exists($table_name)) { // wp_send_json_error(['message' => 'Table does not exist']); return array(); } // Get total number of logs $total_consent_logs = (int) $wpdb->get_var("SELECT COUNT(*) FROM $table_name"); $logs_per_page = 25; // Calculate max pages $max_page = ceil($total_consent_logs / $logs_per_page); // Ensure current page is within valid range if ($current_page > $max_page) { $current_page = $max_page; } elseif ($current_page < 1) { $current_page = 1; } // Calculate pagination offset $offset = ($current_page - 1) * $logs_per_page; // Fetch paginated logs $consent_logs = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $table_name ORDER BY id DESC LIMIT %d OFFSET %d", $logs_per_page, $offset ), ARRAY_A ); if(!empty($consent_logs)){ foreach($consent_logs as $lk => $log){ if(!empty($log['consent_status'])){ $_consent_status = json_decode($log['consent_status'], true)[0]; if($_consent_status == 'accept'){ $consent_logs[$lk]['consent_status_raw'] = 'accept'; $consent_logs[$lk]['consent_status'] = __('Accepted', 'cookieadmin-pro'); }elseif($_consent_status == 'reject'){ $consent_logs[$lk]['consent_status_raw'] = 'reject'; $consent_logs[$lk]['consent_status'] = __('Rejected', 'cookieadmin-pro'); }else{ $consent_logs[$lk]['consent_status_raw'] = 'partially_accepted'; $consent_logs[$lk]['consent_status'] = __('Partially Accepted', 'cookieadmin-pro'); } } if(!empty($log['consent_time'])){ $consent_logs[$lk]['consent_time'] = cookieadmin_pro_human_readable_time($log['consent_time']); } if(!empty($log['user_ip'])){ $consent_logs[$lk]['user_ip'] = inet_ntop($log['user_ip']); } } $num_items = count($consent_logs); } $min_items = $offset + 1; $max_items = $min_items + ($num_items - 1); $return = [ 'logs' => $consent_logs, 'total_logs' => $total_consent_logs, 'logs_per_page' => $logs_per_page, 'current_page' => $current_page, 'total_pages' => $max_page, 'min_items' => $min_items, 'max_items' => $max_items ]; // Return logs as JSON response if (defined('DOING_AJAX') && DOING_AJAX) { wp_send_json_success($return); } // Return paginated data return $return; } // Export Consent Logs from the Database static function export_logs() { global $wpdb; $cookieadmin_export_type = !empty($_REQUEST['cookieadmin_export_type']) ? sanitize_text_field(wp_unslash($_REQUEST['cookieadmin_export_type'])) : ''; if(!empty($cookieadmin_export_type)){ if($cookieadmin_export_type == 'consent_logs'){ $table_name = esc_sql($wpdb->prefix . 'cookieadmin_consents'); //First will check if the table in the database exists or not? if(!self::cookieadmin_pro_table_exists($table_name)){ wp_send_json_error(['message' => 'Table does not exists']); } $logs = $wpdb->get_results("SELECT * FROM $table_name ORDER BY id DESC", ARRAY_A); $filename = 'cookieadmin-consent-logs'; } } if(empty($logs)){ echo -1; echo __('No data to export', 'cookieadmin-pro'); wp_die(); } header('Content-Type: text/csv; charset=utf-8'); header('Content-Disposition: attachment; filename='.$filename.'.csv'); $allowed_fields = array('consent_id' => 'Consent Id', 'consent_status' => 'Consent Status', 'country' => 'Country', 'user_ip' => 'User IP (Anonymized)', 'consent_time' => 'Consent Time'); $file = fopen("php://output","w"); fputcsv($file, array_values($allowed_fields)); foreach($logs as $ik => $log){ if(!empty($log['consent_status'])){ $_consent_status = json_decode($log['consent_status'], true)[0]; if($_consent_status == 'accept'){ $log['consent_status'] = __('Accepted', 'cookieadmin-pro'); }elseif($_consent_status == 'reject'){ $log['consent_status'] = __('Rejected', 'cookieadmin-pro'); }else{ $log['consent_status'] = __('Partially Accepted', 'cookieadmin-pro'); } } if(!empty($log['consent_time'])){ $log['consent_time'] = wp_date('M j Y g:i A T', $log['consent_time']); } if(!empty($log['user_ip'])){ $log['user_ip'] = inet_ntop($log['user_ip']); } $log['country'] = (!empty($log['country']) ? $log['country'] : '—'); $row = array(); foreach($allowed_fields as $ak => $av){ $row[$ak] = $log[$ak]; } fputcsv($file, $row); } fclose($file); wp_die(); } function version_notice(){ $type = ''; if(!empty($_REQUEST['type'])){ $type = sanitize_text_field(wp_unslash($_REQUEST['type'])); } if(empty($type)){ wp_send_json_error(__('Unknow version difference type', 'cookieadmin-pro')); } update_option('cookieadmin_version_'. $type .'_nag', time() + WEEK_IN_SECONDS); wp_send_json_success(); } function dismiss_expired_licenses(){ update_option('softaculous_expired_licenses', time()); wp_send_json_success(); } } short-cirtuit.php 0000644 00000012472 15100113026 0010070 0 ustar 00 <?php /* * CookieAdmin * https://cookieadmin.net * (c) Softaculous Team */ // Are we being accessed directly ? if(!defined('COOKIEADMIN_PRO_VERSION')) { exit('Hacking Attempt !'); } // Prevent update of cookieadmin free // This also work for auto update add_filter('site_transient_update_plugins', 'cookieadmin_pro_disable_manual_update_for_plugin'); add_filter('pre_site_transient_update_plugins', 'cookieadmin_pro_disable_manual_update_for_plugin'); // Auto update free version after update pro version add_action('upgrader_process_complete', 'cookieadmin_pro_update_free_after_pro', 10, 2); add_action('plugins_loaded', 'cookieadmin_pro_load_plugin'); function cookieadmin_pro_load_plugin(){ global $cookieadmin; // Load license cookieadmin_pro_load_license(); cookieadmin_pro_update_checker(); // Check for updates include_once(COOKIEADMIN_PRO_DIR.'/includes/plugin-update-checker.php'); $cookieadmin_updater = CookieAdmin_PucFactory::buildUpdateChecker(cookieadmin_pro_api_url().'updates.php?version='.COOKIEADMIN_PRO_VERSION, COOKIEADMIN_PRO_FILE); // Add the license key to query arguments $cookieadmin_updater->addQueryArgFilter('cookieadmin_pro_updater_filter_args'); // Show the text to install the license key add_filter('puc_manual_final_check_link-cookieadmin-pro', 'cookieadmin_pro_updater_check_link', 10, 1); // Nag informing the user to install the free version. if(current_user_can('activate_plugins')){ add_action('admin_notices', 'cookieadmin_pro_free_version_nag', 9); add_action('admin_menu', 'cookieadmin_pro_add_menu', 9); } $is_network_wide = cookieadmin_pro_is_network_active('cookieadmin-pro'); $_do_version = get_option('cookieadmin_version'); $req_free_update = !empty($_do_version) && version_compare($_do_version, COOKIEADMIN_PRO_VERSION, '<'); if($is_network_wide){ $free_installed = get_site_option('cookieadmin_free_installed'); }else{ $free_installed = get_option('cookieadmin_free_installed'); } if(!empty($free_installed)){ return; } // Include the necessary stuff include_once(ABSPATH . 'wp-admin/includes/plugin-install.php'); include_once(ABSPATH . 'wp-admin/includes/plugin.php'); include_once(ABSPATH . 'wp-admin/includes/file.php'); if(file_exists(WP_PLUGIN_DIR . '/cookieadmin/cookieadmin.php') && is_plugin_inactive('/cookieadmin/cookieadmin.php') && empty($req_free_update)) { if($is_network_wide){ update_site_option('cookieadmin_free_installed', time()); }else{ update_option('cookieadmin_free_installed', time()); } activate_plugin('/cookieadmin/cookieadmin.php', '', $is_network_wide); remove_action('admin_notices', 'cookieadmin_pro_free_version_nag', 9); remove_action('admin_menu', 'cookieadmin_pro_add_menu', 9); return; } // Includes necessary for Plugin_Upgrader and Plugin_Installer_Skin include_once(ABSPATH . 'wp-admin/includes/misc.php'); include_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'); // Filter to prevent the activate text add_filter('install_plugin_complete_actions', 'cookieadmin_pro_prevent_activation_text', 10, 3); $upgrader = new Plugin_Upgrader(new WP_Ajax_Upgrader_Skin()); // Upgrade the plugin to the latest version of free already installed. if(!empty($req_free_update)){ $installed = $upgrader->upgrade('cookieadmin/cookieadmin.php'); }else{ $installed = $upgrader->install('https://downloads.wordpress.org/plugin/cookieadmin.zip'); } if(!is_wp_error($installed) && $installed){ if($is_network_wide){ update_site_option('cookieadmin_free_installed', time()); }else{ update_option('cookieadmin_free_installed', time()); } activate_plugin('cookieadmin/cookieadmin.php', '', $is_network_wide); remove_action('admin_notices', 'cookieadmin_pro_free_version_nag', 9); remove_action('admin_menu', 'cookieadmin_pro_add_menu', 9); } } // Do not shows the activation text if function cookieadmin_pro_prevent_activation_text($install_actions, $api, $plugin_file){ if($plugin_file == 'cookieadmin/cookieadmin.php'){ return array(); } return $install_actions; } function cookieadmin_pro_free_version_nag(){ $cookieadmin_version = get_option('cookieadmin_version'); $lower_version = __('You have not installed the free version of CookieAdmin. CookieAdmin Pro depends on the free version, so you must install it first in order to use CookieAdmin Pro.', 'cookieadmin-pro'); echo '<div class="notice notice-error"> <p style="font-size:16px;">'.esc_html($lower_version).' <a href="'.admin_url('plugin-install.php?s=cookieadmin&tab=search').'" class="button button-primary">Install/Update Now</a></p> </div>'; } function cookieadmin_pro_add_menu(){ add_menu_page('CookieAdmin Settings', 'CookieAdmin', 'activate_plugins', 'cookieadmin', 'cookieadmin_pro_menu_page'); } function cookieadmin_pro_menu_page(){ echo '<div style="color: #333;padding: 50px;text-align: center;"> <h1 style="font-size: 2em;margin-bottom: 10px;">CookieAdmin Free version is not installed / outdated!</h> <p style=" font-size: 16px;margin-bottom: 20px; font-weight:400;">'.esc_html__('CookieAdmin Pro depends on the free version of CookieAdmin, so you need to install / update the free version first.', 'cookieadmin-pro').'</p> <a href="'.admin_url('plugin-install.php?s=cookieadmin&tab=search').'" style="text-decoration: none;font-size:16px;">'.esc_html__('Install/Update Now', 'cookieadmin-pro').'</a> </div>'; } image-templates.php 0000644 00000011625 15100113040 0010321 0 ustar 00 <?php /** * Shortcode Markup * * TMPL - Single Demo Preview * TMPL - No more demos * TMPL - Filters * TMPL - List * * @package Astra Sites * @since 2.0.0 */ if ( ! defined( 'ABSPATH' ) ) { exit; } ?> <script type="text/template" id="tmpl-ast-image-skeleton"> <div class="ast-image__skeleton-wrap"> <div class="ast-image__skeleton-inner-wrap"> <div class="ast-image__skeleton"> </div> <div class="ast-image__preview-skeleton"> </div> </div> </div> <div class="ast-image__loader-wrap"> <div class="ast-image__loader-1"></div> <div class="ast-image__loader-2"></div> <div class="ast-image__loader-3"></div> </div> </script> <script type="text/template" id="tmpl-ast-image-list"> <# var count = 0; #> <# for ( key in data ) { count++; #> <# var is_imported = _.includes( astraImages.saved_images, data[key]['id'] ); #> <# var imported_class = ( is_imported ) ? 'imported' : ''; #> <div class="ast-image__list-wrap loading" data-id="{{data[key]['id']}}" data-url="{{data[key]['pageURL']}}"> <div class="ast-image__list-inner-wrap {{imported_class}}"> <div class="ast-image__list-img-wrap"> <img src="{{data[key]['webformatURL']}}" alt="{{data[key]['tags']}}" /> <div class="ast-image__list-img-overlay" data-img-url={{data[key]['largeImageURL']}} data-img-id={{data[key]['id']}}> <span>{{data[key]['tags']}}</span> <# if ( '' === imported_class ) { #> <span class="ast-image__download-icon dashicons-arrow-down-alt dashicons" data-import-status={{is_imported}}></span> <# } #> </div> </div> </div> </div> <# } #> <# if ( 0 === count ) { #> <div class="astra-sites-no-sites"> <h3><?php esc_html_e( 'Sorry No Results Found.', 'astra-sites' ); ?></h3> </div> <# } #> </script> <script type="text/template" id="tmpl-ast-image-filters"> <div class="ast-image__filter-wrap"> <ul class="ast-image__filter"> <li class="ast-image__filter-category"> <select> <# for ( key in astraImages.pixabay_category ) { #> <option value="{{key}}">{{astraImages.pixabay_category[key]}}</option> <# } #> </select> </li> <li class="ast-image__filter-orientation"> <select> <# for ( key in astraImages.pixabay_orientation ) { #> <option value="{{key}}">{{astraImages.pixabay_orientation[key]}}</option> <# } #> </select> </li> <li class="ast-image__filter-order"> <select> <# for ( key in astraImages.pixabay_order ) { #> <option value="{{key}}">{{astraImages.pixabay_order[key]}}</option> <# } #> </select> </li> <li class="ast-image__filter-safesearch"> <label><input type="checkbox" checked value="1" /><?php esc_html_e( 'SafeSearch', 'astra-sites' ); ?></label> </li> </ul> </div> <div class="ast-powered-by-pixabay-wrap"><span><?php esc_html_e( 'Powered by', 'astra-sites' ); ?></span><img src="<?php echo esc_url( ASTRA_SITES_URI . 'inc/assets/images/pixabay-logo.png' ); ?>"> </div> </script> <script type="text/template" id="tmpl-ast-image-no-result"> <div class="astra-sites-no-sites"> <h3><?php esc_html_e( 'Sorry No Results Found.', 'astra-sites' ); ?></h3> <p class="description"> <?php /* translators: %1$s External Link */ printf( esc_html__( 'Don\'t see a template you would like to import?<br><a target="_blank" href="%1$s">Make a Template Suggestion!</a>', 'astra-sites' ), esc_url( 'https://wpastra.com/sites-suggestions/?utm_source=demo-import-panel&utm_campaign=astra-sites&utm_medium=suggestions' ) ); ?> </p> </div> </script> <script type="text/template" id="tmpl-ast-image-single"> <# var is_imported = _.includes( astraImages.saved_images, data.id.toString() ); #> <# var disable_class = ( is_imported ) ? 'disabled': ''; #> <# var image_type = data.largeImageURL.substring( data.largeImageURL.lastIndexOf( "." ) + 1 ); #> <div class="single-site-wrap"> <div class="single-site"> <div class="single-site-preview-wrap"> <div class="single-site-preview"> <img class="theme-screenshot" src="{{data.largeImageURL}}"> </div> </div> </div> </div> </script> <script type="text/template" id="tmpl-ast-image-go-back"> <div class="ast-image__go-back"> <i class="ast-icon-chevron-left"></i> <span class="ast-image__go-back-text"><?php esc_html_e( 'Back to Images', 'astra-sites' ); ?></span> </div> </script> <script type="text/template" id="tmpl-ast-image-save"> <# var is_imported = _.includes( astraImages.saved_images, data.id.toString() ); #> <# var disable_class = ( is_imported ) ? 'disabled': ''; #> <div class="ast-image__save-wrap"> <button type="button" class="ast-image__save button media-button button-primary button-large media-button-select {{disable_class}}" data-import-status={{is_imported}}> <# if ( is_imported ) { #> <?php esc_html_e( 'Already Saved', 'astra-sites' ); ?> <# } else { #> <?php esc_html_e( 'Save & Insert', 'astra-sites' ); ?> <# } #> </button> </div> </script> <?php white-label.php 0000644 00000003232 15100113040 0007433 0 ustar 00 <?php /** * White Label Form * * @package Astra Sites */ ?> <?php // Bail from displaying settings screen if Astra Pro is older version. if ( ! is_callable( 'Astra_Ext_White_Label_Markup::branding_key_to_constant' ) ) { return; } ?> <li> <div class="branding-form postbox"> <button type="button" class="handlediv button-link" aria-expanded="true"> <span class="screen-reader-text"><?php echo esc_html( $plugin_name ); ?></span> <span class="toggle-indicator" aria-hidden="true"></span> </button> <h2 class="hndle ui-sortable-handle"> <span><?php echo esc_html( $plugin_name ); ?></span> </h2> <div class="inside"> <div class="form-wrap"> <div class="form-field"> <label><?php esc_html_e( 'Plugin Name:', 'astra-sites' ); ?> <input type="text" name="ast_white_label[astra-sites][name]" class="placeholder placeholder-active" <?php disabled( defined( Astra_Ext_White_Label_Markup::branding_key_to_constant( 'astra-sites', 'name' ) ), true, true ); ?> value="<?php echo esc_attr( Astra_Ext_White_Label_Markup::get_whitelabel_string( 'astra-sites', 'name' ) ); ?>"> </label> </div> <div class="form-field"> <label><?php esc_html_e( 'Plugin Description:', 'astra-sites' ); ?> <textarea name="ast_white_label[astra-sites][description]" class="placeholder placeholder-active" <?php disabled( defined( Astra_Ext_White_Label_Markup::branding_key_to_constant( 'astra-sites', 'description' ) ), true, true ); ?> rows="2"><?php echo esc_html( Astra_Ext_White_Label_Markup::get_whitelabel_string( 'astra-sites', 'description' ) ); ?></textarea> </label> </div> <div class="clear"></div> </div> </div> </div> </li> templates.php 0000644 00000056204 15100113040 0007243 0 ustar 00 <?php /** * Shortcode Markup * * TMPL - Single Demo Preview * TMPL - No more demos * TMPL - Filters * TMPL - List * * @package Astra Sites * @since 1.0.0 */ if ( ! defined( 'ABSPATH' ) ) { exit; } $suggestion_link = astra_sites_get_suggestion_link(); ?> <script type="text/template" id="tmpl-ast-template-base-skeleton"> <div class="dialog-widget dialog-lightbox-widget dialog-type-buttons dialog-type-lightbox" id="ast-sites-modal"> <div class="dialog-widget-content dialog-lightbox-widget-content"> <div class="astra-sites-content-wrap" data-page="1"> <div class="ast-template-library-toolbar"> <div class="elementor-template-library-filter-toolbar"> <div class="elementor-template-library-order"> <select class="elementor-template-library-order-input elementor-template-library-filter-select elementor-select2"> <option value=""><?php esc_html_e( 'All', 'astra-sites' ); ?></option> <option value="free"><?php esc_html_e( 'Free', 'astra-sites' ); ?></option> <option value="agency"><?php esc_html_e( 'Premium', 'astra-sites' ); ?></option> </select> </div> <div class="astra-blocks-category-inner-wrap"> <select id="elementor-template-library-filter" class="astra-blocks-category elementor-template-library-filter-select elementor-select2"> <option value=""><?php esc_html_e( 'All', 'astra-sites' ); ?></option> <# for ( key in astraElementorSites.astra_block_categories ) { #> <option value="{{astraElementorSites.astra_block_categories[key].id}}">{{astraElementorSites.astra_block_categories[key].name}}</option> <# } #> </select> </div> <div class="astra-blocks-filter-inner-wrap" id="elementor-template-block-color-filter" style="display: none;"></div> </div> <div class="ast-sites-template-library-filter-text-wrapper"> <label for="elementor-template-library-filter-text" class="elementor-screen-only"><?php esc_html_e( 'Search...', 'astra-sites' ); ?></label> <input id="wp-filter-search-input" placeholder="<?php esc_attr_e( 'SEARCH', 'astra-sites' ); ?>" class=""> <i class="eicon-search"></i> </div> </div> <?php // Check flexbox container, If inactive then activate it. $flexbox_container = get_option( 'elementor_experiment-container' ); // Check if the value is 'inactive'. if ( 'inactive' === $flexbox_container ) { ?> <div class="ast-sites-container-notice-wrap"> <div class="ast-sites-container-notice-content"> <p><?php esc_html_e( "We've observed that the 'Flexbox Container' setting in your Elementor configuration is currently inactive. To ensure a seamless import, please active this option.", 'astra-sites' ); ?></p> <div class="ast-sites-container-notice-actions"> <a href="<?php echo esc_url( home_url( '/wp-admin/admin.php?page=elementor#tab-experiments' ) ); ?>" class="ast-sites-container-notice-button" > <span><?php esc_html_e( 'Activate it!', 'astra-sites' ); ?></span> </a> </div> </div> </div> <?php } ?> <div id="ast-sites-floating-notice-wrap-id" class="ast-sites-floating-notice-wrap"><div class="ast-sites-floating-notice"></div></div> <?php $manual_sync = get_site_option( 'astra-sites-manual-sync-complete', 'no' ); if ( 'yes' === $manual_sync ) { $batch_status = get_site_option( 'astra-sites-batch-is-complete', 'no' ); if ( 'yes' === $batch_status ) { ?> <div class="ast-sites-floating-notice-wrap refreshed-notice slide-in"> <div class="ast-sites-floating-notice"> <div class="astra-sites-sync-library-message success astra-sites-notice notice notice-success is-dismissible"> <?php Astra_Sites::get_instance()->get_sync_complete_message( true ); ?> <button type="button" class="notice-dismiss"><span class="screen-reader-text"><?php esc_html_e( 'Dismiss', 'astra-sites' ); ?></span></button> </div> </div> </div> <?php } } ?> <div class="dialog-message dialog-lightbox-message" data-type="pages"> <div class="dialog-content dialog-lightbox-content theme-browser"></div> <div class="theme-preview"></div> </div> <div class="dialog-message dialog-lightbox-message-block" data-type="blocks"> <div class="dialog-content dialog-lightbox-content-block theme-browser" data-block-page="1"></div> <div class="theme-preview-block"></div> </div> <div class="astra-loading-wrap"><div class="astra-loading-icon"></div></div> </div> <div class="dialog-buttons-wrapper dialog-lightbox-buttons-wrapper"></div> </div> <div class="dialog-background-lightbox"></div> </div> </script> <script type="text/template" id="tmpl-ast-template-block-color-filters"> <select class="astra-blocks-filter elementor-template-library-filter-select elementor-select2"> <option value=""><?php esc_html_e( 'Filter by Color', 'astra-sites' ); ?></option> <# for ( key in data ) { #> <option value="{{data[key]}}">{{data[key]}}</option> <# } #> </select> </script> <script type="text/template" id="tmpl-ast-template-modal__header-back"> <div class="dialog-lightbox-back"><span class="dialog-lightbox-back-text"><?php esc_html_e( 'Back to Pages', 'astra-sites' ); ?></span></div> </script> <script type="text/template" id="tmpl-ast-template-modal__header"> <div class="dialog-header dialog-lightbox-header"> <div class="ast-sites-modal__header"> <div class="ast-sites-modal__header__logo-area"> <?php if ( ! Astra_Sites_White_Label::get_instance()->is_white_labeled() ) { ?> <div class="ast-sites-modal__header__logo"> <span class="ast-sites-modal__header__logo__icon-wrapper"></span> </div> <?php } else { ?> <div class="ast-sites-modal__header__logo"> <span class="ast-sites-modal__header__logo__text-wrapper"><?php echo esc_html( Astra_Sites_White_Label::get_instance()->get_white_label_name() ); ?></span> </div> <?php } ?> <div class="back-to-layout" title="<?php esc_attr_e( 'Back to Layout', 'astra-sites' ); ?>" data-step="1"><i class="ast-icon-chevron-left"></i></div> </div> <div class="elementor-templates-modal__header__menu-area astra-sites-step-1-wrap ast-sites-modal__options"> <div class="elementor-template-library-header-menu"> <div class="elementor-template-library-menu-item elementor-active" data-template-source="remote" data-template-type="pages"><span class="ast-icon-file"></span><?php esc_html_e( 'Pages', 'astra-sites' ); ?></div> <div class="elementor-template-library-menu-item" data-template-source="remote" data-template-type="blocks"><span class="ast-icon-layers"></span><?php esc_html_e( 'Blocks', 'astra-sites' ); ?></div> </div> </div> <div class="elementor-templates-modal__header__items-area"> <div class="ast-sites-modal__header__close ast-sites-modal__header__close--normal ast-sites-modal__header__item"> <i class="dashicons close dashicons-no-alt" aria-hidden="true" title="<?php esc_attr_e( 'Close', 'astra-sites' ); ?>"></i> <span class="elementor-screen-only"><?php esc_html_e( 'Close', 'astra-sites' ); ?></span> </div> <div class="astra-sites__sync-wrap"> <div class="astra-sites-sync-library-button"> <span class="ast-icon-refresh" aria-hidden="true" title="<?php esc_attr_e( 'Sync Library', 'astra-sites' ); ?>"></span> </div> </div> </div> </div> </div> </script> <script type="text/template" id="tmpl-astra-sites-list"> <# var count = 0; for ( key in data ) { var page_data = data[ key ][ 'pages' ]; var site_type = data[ key ][ 'astra-sites-type' ] || ''; if ( 0 == Object.keys( page_data ).length ) { continue; } if ( undefined == site_type ) { continue; } if ( '' !== AstraElementorSitesAdmin.siteType ) { if ( 'free' == AstraElementorSitesAdmin.siteType && site_type != 'free' ) { continue; } if ( 'free' != AstraElementorSitesAdmin.siteType && site_type == 'free' ) { continue; } } var type_class = ' site-type-' + data[ key ]['astra-sites-type']; var site_title = data[ key ]['title'].slice( 0, 25 ); if ( data[ key ]['title'].length > 25 ) { site_title += '...'; } count++; #> <div class="theme astra-theme site-single publish page-builder-elementor {{type_class}}" data-site-id={{key}} data-template-id=""> <div class="inner"> <span class="site-preview" data-href="" data-title={{site_title}}> <div class="theme-screenshot one loading" data-step="1" data-src={{data[ key ]['thumbnail-image-url']}} data-featured-src={{data[ key ]['featured-image-url']}}> <div class="elementor-template-library-template-preview"> <i class="eicon-zoom-in" aria-hidden="true"></i> </div> </div> </span> <div class="theme-id-container"> <h3 class="theme-name">{{site_title}}</h3> </div> <# if ( site_type && 'free' !== site_type ) { #> <?php /* translators: %1$s are white label strings. */ ?> <div class="agency-ribbons" title="<?php printf( esc_attr__( 'This premium template is accessible with %1$s "Premium" Package.', 'astra-sites' ), esc_html( Astra_Sites_White_Label::get_instance()->get_white_label_name() ) ); ?>"><img class="premium-crown-icon" src="<?php echo esc_url( ASTRA_SITES_URI . 'inc/assets/images/premium-crown.svg' ); ?>" alt="premium-crown"><?php esc_html_e( 'Premium', 'astra-sites' ); ?></div> <# } #> </div> </div> <# } #> </script> <script type="text/template" id="tmpl-astra-blocks-list"> <# var count = 0; let upper_window = ( AstraElementorSitesAdmin.per_page * ( AstraElementorSitesAdmin.page - 1 ) ); let lower_window = ( upper_window + AstraElementorSitesAdmin.per_page ); for ( key in data ) { var site_title = ( undefined == data[ key ]['category'] || 0 == data[ key ]['category'].length ) ? data[ key ]['title'] : astraElementorSites.astra_block_categories[data[ key ]['category']].name; if ( '' !== AstraElementorSitesAdmin.blockCategory ) { if ( AstraElementorSitesAdmin.blockCategory != data[ key ]['category'] ) { continue; } } if ( '' !== AstraElementorSitesAdmin.blockColor ) { if ( undefined !== data[ key ]['filter'] && AstraElementorSitesAdmin.blockColor != data[ key ]['filter'] ) { continue; } } count++; #> <div class="astra-sites-library-template astra-theme" data-block-id={{key}}> <div class="astra-sites-library-template-inner" > <div class="elementor-template-library-template-body theme-screenshot" data-step="1"> <img src="{{data[ key ]['thumbnail-image-url']}}"> <div class="elementor-template-library-template-preview"> <i class="eicon-zoom-in" aria-hidden="true"></i> </div> </div> <div class="elementor-template-library-template-footer"> <a class="elementor-template-library-template-action elementor-template-library-template-insert ast-block-insert"> <i class="eicon-file-download" aria-hidden="true"></i> <span class="elementor-button-title"><?php esc_html_e( 'INSERT', 'astra-sites' ); ?></span> </a> </div> </div> </div> <# } if ( count == 0 ) { #> <div class="astra-sites-no-sites"> <div class="inner"> <h3><?php esc_html_e( 'Sorry No Results Found.', 'astra-sites' ); ?></h3> <div class="content" style="text-align: center"> <div class="description"> <p> <?php /* translators: %1$s External Link */ printf( esc_html__( "Don't see a template you would like to import? %s", 'astra-sites' ), nl2br( '<br><a target="_blank" href="' . esc_url( $suggestion_link ) . '">Make a Template Suggestion!</a>' ) ); ?> </p> <div class="back-to-layout-button"><span class="button astra-sites-back"><?php esc_html_e( 'Back to Templates', 'astra-sites' ); ?></span></div> </div> </div> </div> </div> <# } #> </script> <script type="text/template" id="tmpl-astra-sites-list-search"> <# var count = 0; for ( ind in data ) { var site_type = data[ ind ]['site-pages-type']; var type_class = ' site-type-' + site_type; var site_id = ( undefined == data.site_id ) ? data[ind].site_id : data.site_id; if ( undefined == site_type ) { continue; } if ( 'gutenberg' == data[ind]['site-pages-page-builder'] ) { continue; } var site_title = data[ ind ]['title'].slice( 0, 25 ); if ( data[ ind ]['title'].length > 25 ) { site_title += '...'; } count++; #> <div class="theme astra-theme site-single publish page-builder-elementor {{type_class}}" data-template-id={{ind}} data-site-id={{site_id}}> <div class="inner"> <span class="site-preview" data-href="" data-title={{site_title}}> <div class="theme-screenshot one loading" data-step="2" data-src={{data[ ind ]['thumbnail-image-url']}} data-featured-src={{data[ ind ]['featured-image-url']}}> <div class="elementor-template-library-template-preview"> <i class="eicon-zoom-in" aria-hidden="true"></i> </div> </div> </span> <div class="theme-id-container"> <h3 class="theme-name">{{site_title}}</h3> <# var is_free = true; if ( 'pages' == AstraElementorSitesAdmin.type ) { if( 'free' !== data[ ind ]['site-pages-type'] && ! astraElementorSites.license_status ) { is_free = false; } } if( is_free ) { #> <a class="elementor-template-library-template-action elementor-template-library-template-insert ast-block-insert"> <i class="eicon-file-download" aria-hidden="true"></i> <span class="elementor-button-title"><?php esc_html_e( 'INSERT', 'astra-sites' ); ?></span> </a> <# } else { #> <a class="elementor-template-library-template-action elementor-template-library-template-go-pro" href="{{astraElementorSites.getProURL}}" target="_blank"> <i class="eicon-external-link-square" aria-hidden="true"></i> <span class="elementor-button-title"><?php esc_html_e( 'Get Access!', 'astra-sites' ); ?></span> </a> <# } #> </div> <# if ( site_type && 'free' !== site_type ) { #> <?php /* translators: %1$s are white label strings. */ ?> <div class="agency-ribbons" title="<?php printf( esc_attr__( 'This premium template is accessible with %1$s "Premium" Package.', 'astra-sites' ), esc_html( Astra_Sites_White_Label::get_instance()->get_white_label_name() ) ); ?>"><?php esc_html_e( 'Premium', 'astra-sites' ); ?></div> <# } #> </div> </div> <# } if ( count == 0 ) { #> <div class="astra-sites-no-sites"> <div class="inner"> <h3><?php esc_html_e( 'Sorry No Results Found.', 'astra-sites' ); ?></h3> <div class="content"> <div class="description"> <p> <?php /* translators: %1$s External Link */ printf( esc_attr__( 'Don\'t see a template you would like to import?<br><a target="_blank" href="%1$s">Make a Template Suggestion!</a>', 'astra-sites' ), esc_url( $suggestion_link ) ); ?> </p> <div class="back-to-layout-button"><span class="button astra-sites-back"><?php esc_html_e( 'Back to Templates', 'astra-sites' ); ?></span></div> </div> </div> </div> </div> <# } #> </script> <script type="text/template" id="tmpl-astra-sites-search"> <# var count = 0; for ( ind in data ) { if ( 'gutenberg' == data[ind]['site-pages-page-builder'] ) { continue; } var site_id = ( undefined == data.site_id ) ? data[ind].site_id : data.site_id; var site_type = data[ ind ]['site-pages-type']; if ( 'site' == data[ind]['type'] ) { site_type = data[ ind ]['astra-sites-type']; } if ( undefined == site_type ) { continue; } var parent_name = ''; if ( undefined != data[ind]['parent-site-name'] ) { var parent_name = jQuery( "<textarea/>") .html( data[ind]['parent-site-name'] ).text(); } var complete_title = parent_name + ' - ' + data[ ind ]['title']; var site_title = complete_title.slice( 0, 25 ); if ( complete_title.length > 25 ) { site_title += '...'; } var tmp = site_title.split(' - '); var title1 = site_title; var title2 = ''; if ( undefined !== tmp && undefined !== tmp[1] ) { title1 = tmp[0]; title2 = ' - ' + tmp[1]; } else { title1 = tmp[0]; title2 = ''; } var type_class = ' site-type-' + site_type; count++; #> <div class="theme astra-theme site-single publish page-builder-elementor {{type_class}}" data-template-id={{ind}} data-site-id={{site_id}}> <div class="inner"> <span class="site-preview" data-href="" data-title={{title2}}> <div class="theme-screenshot one loading" data-type={{data[ind]['type']}} data-step={{data[ind]['step']}} data-show="search" data-src={{data[ ind ]['thumbnail-image-url']}} data-featured-src={{data[ ind ]['featured-image-url']}}></div> </span> <div class="theme-id-container"> <h3 class="theme-name"><strong>{{title1}}</strong>{{title2}}</h3> </div> <# if ( site_type && 'free' !== site_type ) { #> <div class="agency-ribbons" title=" <?php /* translators: %1$s are white label strings. */ printf( esc_attr__( 'This premium template is accessible with %1$s "Premium" Package.', 'astra-sites' ), esc_html( Astra_Sites_White_Label::get_instance()->get_white_label_name() ) ); ?> " > <?php esc_html_e( 'Premium', 'astra-sites' ); ?> </div> <# } #> </div> </div> <# } if ( count == 0 ) { #> <div class="astra-sites-no-sites"> <div class="inner"> <h3><?php esc_html_e( 'Sorry No Results Found.', 'astra-sites' ); ?></h3> <div class="content" style="text-align: center"> <div class="description"> <p> <?php /* translators: %1$s External Link */ printf( esc_html__( "Don't see a template you would like to import? %s", 'astra-sites' ), nl2br( '<br><a target="_blank" href="' . esc_url( $suggestion_link ) . '">Make a Template Suggestion!</a>' ) ); ?> </p> <div class="back-to-layout-button"><span class="button astra-sites-back"><?php esc_html_e( 'Back to Templates', 'astra-sites' ); ?></span></div> </div> </div> </div> </div> <# } #> </script> <script type="text/template" id="tmpl-astra-sites-insert-button"> <div id="elementor-template-library-header-preview-insert-wrapper" class="elementor-templates-modal__header__item" data-template-id={{data.template_id}} data-site-id={{data.site_id}}> <a class="elementor-template-library-template-action elementor-template-library-template-insert elementor-button"> <i class="eicon-file-download" aria-hidden="true"></i> <span class="elementor-button-title"><?php esc_html_e( 'Insert', 'astra-sites' ); ?></span> </a> </div> </script> <?php /** * TMPL - Third Party Required Plugins */ ?> <script type="text/template" id="tmpl-astra-sites-third-party-required-plugins"> <div class="skip-and-import"> <div class="heading"> <h3><?php esc_html_e( 'Required Plugins Missing', 'astra-sites' ); ?></h3> <span class="dashicons close dashicons-no-alt"></span> </div> <div class="astra-sites-import-content"> <p><?php esc_html_e( 'This starter site requires premium plugins. As these are third party premium plugins, you\'ll need to purchase, install and activate them first.', 'astra-sites' ); ?></p> <ul class="astra-sites-third-party-required-plugins"> <# for ( key in data ) { #> <li class="plugin-card plugin-card-{{data[ key ].slug}}'" data-slug="{{data[ key ].slug }}" data-init="{{data[ key ].init}}" data-name="{{data[ key ].name}}"><a href="{{data[ key ].link}}" target="_blank">{{data[ key ].name}}</a></li> <# } #> </ul> </div> <div class="ast-actioms-wrap"> <a href="#" class="button button-hero button-primary astra-sites-skip-and-import-step"><?php esc_html_e( 'Skip & Import', 'astra-sites' ); ?></a> <div class="button button-hero site-import-cancel"><?php esc_html_e( 'Cancel', 'astra-sites' ); ?></div> </div> </div> </script> <script type="text/template" id="tmpl-astra-sites-no-sites"> <div class="astra-sites-no-sites"> <div class="inner"> <h3><?php esc_html_e( 'Sorry No Results Found.', 'astra-sites' ); ?></h3> <div class="content"> <div class="empty-item"> <img class="empty-collection-part" src="<?php echo esc_url( ASTRA_SITES_URI . 'inc/assets/images/empty-collection.svg' ); ?>" alt="empty-collection"> </div> <div class="description"> <p> <?php /* translators: %1$s External Link */ printf( esc_html__( 'Don\'t see a template you would like to import?<br><a target="_blank" href="%1$s">Make a Template Suggestion!</a>', 'astra-sites' ), esc_url( $suggestion_link ) ); ?> </p> <div class="back-to-layout-button"><span class="button astra-sites-back"><?php esc_html_e( 'Back to Templates', 'astra-sites' ); ?></span></div> </div> </div> </div> </div> <# </script> <script type="text/template" id="tmpl-astra-sites-elementor-preview"> <# let wrap_height = $elscope.find( '.astra-sites-content-wrap' ).height(); wrap_height = ( wrap_height - 55 ); wrap_height = wrap_height + 'px'; #> <div id="astra-blocks" class="themes wp-clearfix" data-site-id="{{data.id}}" style="display: block;"> <div class="single-site-wrap"> <div class="single-site"> <div class="single-site-preview-wrap"> <div class="single-site-preview" style="max-height: {{wrap_height}};"> <img class="theme-screenshot" data-src="" src="{{data['featured-image-url']}}"> </div> </div> </div> </div> </div> </script> <script type="text/template" id="tmpl-astra-sites-elementor-preview-actions"> <# var demo_link = ''; var action_str = ''; if ( 'blocks' == AstraElementorSitesAdmin.type ) { demo_link = astraElementorSites.astra_blocks[AstraElementorSitesAdmin.block_id]['url']; action_str = 'Block'; } else { demo_link = data['astra-page-url']; action_str = 'Template'; } #> <div class="astra-preview-actions-wrap"> <div class="astra-preview-actions-inner-wrap"> <div class="astra-preview-actions"> <div class="site-action-buttons-wrap"> <div class="astra-sites-import-template-action site-action-buttons-right"> <div class="astra-sites-tooltip"><span class="astra-sites-tooltip-icon" data-tip-id="astra-sites-tooltip-plugins-settings"><span class="dashicons dashicons-editor-help"></span></span></div> <# var is_free = true; if ( 'pages' == AstraElementorSitesAdmin.type ) { if( 'free' !== data['site-pages-type'] && ! astraElementorSites.license_status ) { is_free = false; } } if( ! is_free ) { #> <a class="button button-hero button-primary" href="{{astraElementorSites.getProURL}}" target="_blank">{{astraElementorSites.getProText}}<i class="dashicons dashicons-external"></i></a> <# } else { #> <div type="button" class="button button-hero button-primary ast-library-template-insert disabled"><?php esc_html_e( 'Import ', 'astra-sites' ); ?>{{action_str}}</div> <div type="button" class="button button-hero button-primary ast-import-elementor-template disabled"><?php esc_html_e( 'Save ', 'astra-sites' ); ?>{{action_str}}</div> <# } #> </div> </div> </div> <div class="ast-tooltip-wrap"> <div> <div class="ast-tooltip-inner-wrap" id="astra-sites-tooltip-plugins-settings"> <ul class="required-plugins-list"><span class="spinner is-active"></span></ul> </div> </div> </div> </div> </div> </script> <?php class-astra-theme-builder-free.php 0000644 00000015417 15104072660 0013146 0 ustar 00 <?php /** * Site Builder Free Version Preview. * * @package Astra */ if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } if ( ! class_exists( 'Astra_Theme_Builder_Free' ) ) { define( 'ASTRA_THEME_BUILDER_FREE_DIR', ASTRA_THEME_DIR . 'admin/assets/theme-builder/' ); define( 'ASTRA_THEME_BUILDER_FREE_URI', ASTRA_THEME_URI . 'admin/assets/theme-builder/' ); /** * Site Builder initial setup. * * @since 4.5.0 */ class Astra_Theme_Builder_Free { /** * Member Variable * * @var null $instance */ private static $instance; /** * Initiator * * @since 4.5.0 */ public static function get_instance() { if ( ! isset( self::$instance ) ) { /** @psalm-suppress InvalidPropertyAssignmentValue */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort self::$instance = new self(); /** @psalm-suppress InvalidPropertyAssignmentValue */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort } return self::$instance; } /** * Constructor * * @since 4.5.0 * @return void */ public function __construct() { $is_astra_addon_active = defined( 'ASTRA_EXT_VER' ); if ( ! $is_astra_addon_active ) { add_action( 'admin_enqueue_scripts', array( $this, 'theme_builder_admin_enqueue_scripts' ) ); add_action( 'admin_body_class', array( $this, 'admin_body_class' ) ); add_action( 'admin_menu', array( $this, 'setup_menu' ) ); add_action( 'admin_init', array( $this, 'astra_theme_builder_disable_notices' ) ); } add_action( 'admin_page_access_denied', array( $this, 'astra_theme_builder_access_denied_redirect' ) ); } /** * Enqueue scripts and styles. * * @since 4.5.0 * @return void */ public function theme_builder_admin_enqueue_scripts() { $file_prefix = ''; if ( is_rtl() ) { $file_prefix .= '.rtl'; } wp_enqueue_style( 'astra-theme-builder-style', ASTRA_THEME_BUILDER_FREE_URI . 'build/index' . $file_prefix . '.css', array(), ASTRA_THEME_VERSION ); wp_enqueue_script( 'astra-theme-builder-script', ASTRA_THEME_BUILDER_FREE_URI . 'build/index.js', array( 'wp-element' ), ASTRA_THEME_VERSION, true ); wp_enqueue_style( 'dashicons' ); $astra_addon_locale = ASTRA_THEME_ORG_VERSION ? 'astra-addon/astra-addon.php' : 'astra-pro/astra-pro.php'; $localized_data = array( 'title' => esc_html__( 'Site Builder', 'astra' ), 'rest_url' => '/wp-json/astra-addon/v1/custom-layouts/', 'new_custom_layout_base_url' => admin_url( 'post-new.php?post_type=astra-advanced-hook' ), 'astra_pricing_page_url' => astra_get_pro_url( '/pricing/', 'free-theme', 'site-builder', 'upgrade' ), 'astra_docs_page_url' => astra_get_pro_url( '/docs/custom-layouts-pro/', 'free-theme', 'site-builder', 'documentation' ), 'astra_base_url' => admin_url( 'admin.php?page=' . Astra_Menu::get_theme_page_slug() ), ); wp_localize_script( 'astra-theme-builder-script', 'astra_theme_builder', $localized_data ); wp_set_script_translations( 'astra-theme-builder-script', 'astra' ); $localize = array( 'pro_installed_status' => 'installed' === Astra_Menu::get_plugin_status( $astra_addon_locale ) ? true : false, 'ajax_url' => admin_url( 'admin-ajax.php' ), 'upgrade_url' => astra_get_upgrade_url( 'dashboard' ), 'astra_base_url' => admin_url( 'admin.php?page=' . Astra_Menu::get_theme_page_slug() ), 'update_nonce' => wp_create_nonce( 'astra_update_admin_setting' ), 'plugin_manager_nonce' => wp_create_nonce( 'astra_plugin_manager_nonce' ), 'plugin_installer_nonce' => wp_create_nonce( 'updates' ), 'plugin_installing_text' => esc_html__( 'Installing', 'astra' ), 'plugin_installed_text' => esc_html__( 'Installed', 'astra' ), 'plugin_activating_text' => esc_html__( 'Activating', 'astra' ), 'plugin_activated_text' => esc_html__( 'Activated', 'astra' ), 'plugin_activate_text' => esc_html__( 'Activate', 'astra' ), ); wp_localize_script( 'astra-theme-builder-script', 'astra_admin', $localize ); } /** * Admin Body Classes * * @since 4.5.0 * @param string $classes Space separated class string. */ public function admin_body_class( $classes = '' ) { $theme_builder_class = isset( $_GET['page'] ) && 'theme-builder-free' === $_GET['page'] ? 'ast-theme-builder' : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Fetching a $_GET value, no nonce available to validate. $classes .= ' ' . $theme_builder_class . ' '; return $classes; } /** * Renders the admin settings. * * @since 4.5.0 * @return void */ public function render_theme_builder() { ?> <div class="ast-tb-menu-page-wrapper"> <div id="ast-tb-menu-page"> <div class="ast-tb-menu-page-content"> <div id="ast-tb-app-root" class="ast-tb-app-root"></div> </div> </div> </div> <?php } /** * Setup menu. * * @since 4.5.0 * @return void */ public function setup_menu() { add_submenu_page( // phpcs:ignore WPThemeReview.PluginTerritory.NoAddAdminPages.add_menu_pages_add_submenu_page -- Taken the menu on top level 'astra', __( 'Site Builder', 'astra' ), __( 'Site Builder', 'astra' ), 'manage_options', 'theme-builder-free', array( $this, 'render_theme_builder' ), 2 ); } /** * Disable notices for Site Builder page. * * @since 4.5.0 * @return void */ public function astra_theme_builder_disable_notices() { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Fetching a $_GET value, no nonce available to validate. if ( isset( $_GET['page'] ) && 'theme-builder-free' === $_GET['page'] ) { remove_all_actions( 'admin_notices' ); remove_all_actions( 'all_admin_notices' ); // For older versions of WordPress } } /** * Redirect to Site Builder pro from free preview if pro module is active. * * @since 4.5.0 * @return void */ public function astra_theme_builder_access_denied_redirect() { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Fetching a $_GET value, no nonce available to validate. if ( isset( $_GET['page'] ) && 'theme-builder-free' === $_GET['page'] ) { /** @psalm-suppress UndefinedClass */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $is_astra_addon_active = ( defined( 'ASTRA_EXT_VER' ) && Astra_Ext_Extension::is_active( 'advanced-hooks' ) ); /** @psalm-suppress UndefinedClass */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort if ( $is_astra_addon_active ) { wp_safe_redirect( admin_url( 'admin.php?page=theme-builder' ) ); exit; } } } } /** * Kicking this off by calling 'get_instance()' method */ Astra_Theme_Builder_Free::get_instance(); } class-astra-admin-ajax.php 0000644 00000035002 15104072660 0011502 0 ustar 00 <?php /** * Astra Admin Ajax Base. * * @package Astra * @since 4.0.0 */ if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } /** * Class Astra_Admin_Ajax. * * @since 4.0.0 */ class Astra_Admin_Ajax { /** * Ajax action prefix. * * @var string * @since 4.0.0 */ private $prefix = 'astra'; /** * Instance * * @var null $instance * @since 4.0.0 */ private static $instance; /** * Initiator * * @since 4.0.0 * @return object initialized object of class. */ public static function get_instance() { if ( ! isset( self::$instance ) ) { /** @psalm-suppress InvalidPropertyAssignmentValue */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort self::$instance = new self(); /** @psalm-suppress InvalidPropertyAssignmentValue */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort } return self::$instance; } /** * Errors class instance. * * @var array * @since 4.0.0 */ private $errors = array(); /** * Constructor * * @since 4.0.0 */ public function __construct() { add_action( 'init', function() { $this->errors = array( 'permission' => esc_html__( 'Sorry, you are not allowed to do this operation.', 'astra' ), 'nonce' => esc_html__( 'Nonce validation failed', 'astra' ), 'default' => esc_html__( 'Sorry, something went wrong.', 'astra' ), 'invalid' => esc_html__( 'No post data found!', 'astra' ), ); } ); add_action( 'wp_ajax_ast_disable_pro_notices', array( $this, 'disable_astra_pro_notices' ) ); add_action( 'wp_ajax_astra_recommended_plugin_install', array( $this, 'required_plugin_install' ) ); add_action( 'wp_ajax_ast_migrate_to_builder', array( $this, 'migrate_to_builder' ) ); add_action( 'wp_ajax_astra_update_admin_setting', array( $this, 'astra_update_admin_setting' ) ); add_action( 'wp_ajax_astra_analytics_optin_status', array( $this, 'astra_analytics_optin_status' ) ); add_action( 'wp_ajax_astra_recommended_plugin_activate', array( $this, 'required_plugin_activate' ) ); add_action( 'wp_ajax_astra_recommended_plugin_deactivate', array( $this, 'required_plugin_deactivate' ) ); } /** * Return boolean settings for admin dashboard app. * * @return array * @since 4.0.0 */ public function astra_admin_settings_typewise() { return apply_filters( 'astra_admin_settings_datatypes', array( 'self_hosted_gfonts' => 'bool', 'preload_local_fonts' => 'bool', 'use_old_header_footer' => 'bool', ) ); } /** * Disable pro upgrade notice from all over in Astra. * * @since 4.0.0 */ public function disable_astra_pro_notices() { $response_data = array( 'message' => $this->get_error_msg( 'permission' ) ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( $response_data ); } if ( empty( $_POST ) ) { $response_data = array( 'message' => $this->get_error_msg( 'invalid' ) ); wp_send_json_error( $response_data ); } /** * Nonce verification. */ if ( ! check_ajax_referer( 'astra_update_admin_setting', 'security', false ) ) { $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) ); wp_send_json_error( $response_data ); } if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( esc_html__( 'You don\'t have the access', 'astra' ) ); } /** @psalm-suppress PossiblyInvalidArgument */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $migrate = isset( $_POST['status'] ) ? sanitize_key( $_POST['status'] ) : ''; /** @psalm-suppress PossiblyInvalidArgument */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $migrate = 'true' === $migrate ? true : false; astra_update_option( 'ast-disable-upgrade-notices', $migrate ); wp_send_json_success(); } /** * Migrate to New Header Builder * * @since 4.0.0 */ public function migrate_to_builder() { $response_data = array( 'message' => $this->get_error_msg( 'permission' ) ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( $response_data ); } if ( empty( $_POST ) ) { $response_data = array( 'message' => $this->get_error_msg( 'invalid' ) ); wp_send_json_error( $response_data ); } /** * Nonce verification. */ if ( ! check_ajax_referer( 'astra_update_admin_setting', 'security', false ) ) { $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) ); wp_send_json_error( $response_data ); } /** @psalm-suppress PossiblyInvalidArgument */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $migrate = isset( $_POST['status'] ) ? sanitize_key( $_POST['status'] ) : ''; /** @psalm-suppress PossiblyInvalidArgument */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $migrate = 'true' === $migrate ? true : false; /** @psalm-suppress InvalidArgument */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $migration_flag = astra_get_option( 'v3-option-migration', false ); astra_update_option( 'is-header-footer-builder', $migrate ); if ( $migrate && false === $migration_flag ) { require_once ASTRA_THEME_DIR . 'inc/theme-update/astra-builder-migration-updater.php'; // phpcs:ignore WPThemeReview.CoreFunctionality.FileInclude.FileIncludeFound astra_header_builder_migration(); } wp_send_json_success(); } /** * Save settings. * * @return void * @since 4.0.0 */ public function astra_update_admin_setting() { $response_data = array( 'message' => $this->get_error_msg( 'permission' ) ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( $response_data ); } if ( empty( $_POST ) ) { $response_data = array( 'message' => $this->get_error_msg( 'invalid' ) ); wp_send_json_error( $response_data ); } /** * Nonce verification. */ if ( ! check_ajax_referer( 'astra_update_admin_setting', 'security', false ) ) { $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) ); wp_send_json_error( $response_data ); } $get_bool_settings = $this->astra_admin_settings_typewise(); /** @psalm-suppress PossiblyInvalidArgument */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $sub_option_key = isset( $_POST['key'] ) ? sanitize_text_field( wp_unslash( $_POST['key'] ) ) : ''; /** @psalm-suppress PossiblyInvalidArgument */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $sub_option_value = ''; // @codingStandardsIgnoreStart if ( isset( $get_bool_settings[ $sub_option_key ] ) ) { if ( 'bool' === $get_bool_settings[ $sub_option_key ] ) { /** @psalm-suppress PossiblyInvalidArgument */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $val = isset( $_POST['value'] ) && 'true' === sanitize_text_field( $_POST['value'] ) ? true : false; /** @psalm-suppress PossiblyInvalidArgument */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $sub_option_value = $val; } else { /** @psalm-suppress PossiblyInvalidArgument */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $val = isset( $_POST['value'] ) ? sanitize_text_field( wp_unslash( $_POST['value'] ) ) : ''; /** @psalm-suppress PossiblyInvalidArgument */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $sub_option_value = $val; } } // @codingStandardsIgnoreEnd Astra_API_Init::update_admin_settings_option( $sub_option_key, $sub_option_value ); $response_data = array( 'message' => esc_html__( 'Successfully saved data!', 'astra' ), ); wp_send_json_success( $response_data ); } /** * Astra Analytics Opt-in. * * @return void * @since 4.10.0 */ public function astra_analytics_optin_status() { $response_data = array( 'message' => $this->get_error_msg( 'permission' ) ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( $response_data ); } if ( empty( $_POST ) ) { $response_data = array( 'message' => $this->get_error_msg( 'invalid' ) ); wp_send_json_error( $response_data ); } /* Nonce verification */ if ( ! check_ajax_referer( 'astra_update_admin_setting', 'security', false ) ) { $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) ); wp_send_json_error( $response_data ); } $opt_in = filter_input( INPUT_POST, 'value', FILTER_VALIDATE_BOOLEAN ) ? 'yes' : 'no'; update_site_option( 'astra_analytics_optin', $opt_in ); $response_data = array( 'message' => esc_html__( 'Successfully saved data!', 'astra' ), ); wp_send_json_success( $response_data ); } /** * Get ajax error message. * * @param string $type Message type. * @return string * @since 4.0.0 */ public function get_error_msg( $type ) { if ( ! isset( $this->errors[ $type ] ) ) { $type = 'default'; } return $this->errors[ $type ]; } /** * Handles the installation and saving of required plugins. * * This function is responsible for installing and saving required plugins for the Astra theme. * It checks for the plugin slug in the AJAX request, verifies the nonce, and initiates the plugin installation process. * If the plugin is successfully installed, it schedules a database update to map the plugin slug to a custom key for analytics tracking. * * @since 4.8.12 */ public function required_plugin_install() { check_ajax_referer( 'updates', '_ajax_nonce' ); // Fetching the plugin slug from the AJAX request. // @psalm-suppress PossiblyInvalidArgument $plugin_slug = isset( $_POST['slug'] ) && is_string( $_POST['slug'] ) ? sanitize_text_field( wp_unslash( $_POST['slug'] ) ) : ''; if ( empty( $plugin_slug ) ) { wp_send_json_error( array( 'message' => __( 'Plugin slug is missing.', 'astra' ) ) ); } // Schedule the database update if the plugin is installed successfully. add_action( 'shutdown', static function () use ( $plugin_slug ) { // Iterate through all plugins to check if the installed plugin matches the current plugin slug. $all_plugins = get_plugins(); foreach ( $all_plugins as $plugin_file => $_ ) { if ( is_callable( 'BSF_UTM_Analytics::update_referer' ) && strpos( $plugin_file, $plugin_slug . '/' ) === 0 ) { // If the plugin is found and the update_referer function is callable, update the referer with the corresponding product slug. BSF_UTM_Analytics::update_referer( 'astra', $plugin_slug ); return; } } } ); if ( function_exists( 'wp_ajax_install_plugin' ) ) { // @psalm-suppress NoValue wp_ajax_install_plugin(); } else { wp_send_json_error( array( 'message' => __( 'Plugin installation function not found.', 'astra' ) ) ); } } /** * Required Plugin Activate * * @since 1.2.4 */ public function required_plugin_activate() { $response_data = array( 'message' => $this->get_error_msg( 'permission' ) ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( $response_data ); } if ( empty( $_POST ) ) { $response_data = array( 'message' => $this->get_error_msg( 'invalid' ) ); wp_send_json_error( $response_data ); } /** * Nonce verification. */ if ( ! check_ajax_referer( 'astra_plugin_manager_nonce', 'security', false ) ) { $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) ); wp_send_json_error( $response_data ); } /** @psalm-suppress PossiblyInvalidArgument */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort if ( ! current_user_can( 'install_plugins' ) || ! isset( $_POST['init'] ) || ! sanitize_text_field( wp_unslash( $_POST['init'] ) ) ) { /** @psalm-suppress PossiblyInvalidArgument */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort wp_send_json_error( array( 'success' => false, 'message' => esc_html__( 'No plugin specified', 'astra' ), ) ); } /** @psalm-suppress PossiblyInvalidArgument */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $plugin_init = isset( $_POST['init'] ) ? sanitize_text_field( wp_unslash( $_POST['init'] ) ) : ''; /** @psalm-suppress PossiblyInvalidArgument */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $activate = activate_plugin( $plugin_init ); if ( is_wp_error( $activate ) ) { /** @psalm-suppress PossiblyNullReference */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort wp_send_json_error( array( 'success' => false, 'message' => $activate->get_error_message(), ) ); /** @psalm-suppress PossiblyNullReference */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort } /** * Added this flag as tracker to track onboarding and funnel stats for SureCart owners. * * @since 4.7.0 */ if ( 'surecart/surecart.php' === $plugin_init ) { update_option( 'surecart_source', 'astra', false ); } wp_send_json_success( array( 'success' => true, 'message' => esc_html__( 'Plugin Successfully Activated', 'astra' ), ) ); } /** * Required Plugin Activate * * @since 1.2.4 */ public function required_plugin_deactivate() { $response_data = array( 'message' => $this->get_error_msg( 'permission' ) ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( $response_data ); } if ( empty( $_POST ) ) { $response_data = array( 'message' => $this->get_error_msg( 'invalid' ) ); wp_send_json_error( $response_data ); } /** * Nonce verification. */ if ( ! check_ajax_referer( 'astra_plugin_manager_nonce', 'security', false ) ) { $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) ); wp_send_json_error( $response_data ); } /** @psalm-suppress PossiblyInvalidArgument */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort if ( ! current_user_can( 'install_plugins' ) || ! isset( $_POST['init'] ) || ! sanitize_text_field( wp_unslash( $_POST['init'] ) ) ) { /** @psalm-suppress PossiblyInvalidArgument */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort wp_send_json_error( array( 'success' => false, 'message' => esc_html__( 'No plugin specified', 'astra' ), ) ); } /** @psalm-suppress PossiblyInvalidArgument */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $plugin_init = isset( $_POST['init'] ) ? sanitize_text_field( wp_unslash( $_POST['init'] ) ) : ''; /** @psalm-suppress PossiblyInvalidArgument */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $deactivate = deactivate_plugins( $plugin_init ); if ( is_wp_error( $deactivate ) ) { wp_send_json_error( array( 'success' => false, 'message' => $deactivate->get_error_message(), ) ); } wp_send_json_success( array( 'success' => true, 'message' => esc_html__( 'Plugin Successfully Deactivated', 'astra' ), ) ); } } Astra_Admin_Ajax::get_instance(); class-astra-api-init.php 0000644 00000010471 15104072660 0011206 0 ustar 00 <?php /** * Class Astra_API_Init. * * @package Astra * @since 4.0.0 */ if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } // Bail if WP_REST_Controller class does not exist. if ( ! class_exists( 'WP_REST_Controller' ) ) { return; } /** * Astra_API_Init. * * @since 4.1.0 */ class Astra_API_Init extends WP_REST_Controller { /** * Instance * * @var null $instance * @since 4.0.0 */ private static $instance; /** * Initiator * * @since 4.0.0 * @return object initialized object of class. */ public static function get_instance() { if ( ! isset( self::$instance ) ) { self::$instance = new self(); } return self::$instance; } /** * Namespace. * * @var string */ protected $namespace = 'astra/v1'; /** * Route base. * * @var string */ protected $rest_base = '/admin/settings/'; /** * Option name * * @var string $option_name DB option name. * @since 4.0.0 */ private static $option_name = 'astra_admin_settings'; /** * Admin settings dataset * * @var array $astra_admin_settings Settings array. * @since 4.0.0 */ private static $astra_admin_settings = array(); /** * Constructor * * @since 4.0.0 */ public function __construct() { self::$astra_admin_settings = get_option( self::$option_name, array() ); // REST API extensions init. add_action( 'rest_api_init', array( $this, 'register_routes' ) ); } /** * Register API routes. * * @since 4.0.0 */ public function register_routes() { register_rest_route( $this->namespace, $this->rest_base, array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'get_admin_settings' ), 'permission_callback' => array( $this, 'get_permissions_check' ), 'args' => array(), ), 'schema' => array( $this, 'get_public_item_schema' ), ) ); } /** * Get common settings. * * @param WP_REST_Request $request Full details about the request. * @return array $updated_option defaults + set DB option data. * * @since 4.0.0 */ public function get_admin_settings( $request ) { $db_option = get_option( 'astra_admin_settings', array() ); $defaults = apply_filters( 'astra_dashboard_rest_options', array( 'self_hosted_gfonts' => self::get_admin_settings_option( 'self_hosted_gfonts', false ), 'preload_local_fonts' => self::get_admin_settings_option( 'preload_local_fonts', false ), 'use_old_header_footer' => astra_get_option( 'is-header-footer-builder', false ), 'use_upgrade_notices' => astra_showcase_upgrade_notices(), 'analytics_enabled' => get_option( 'astra_analytics_optin', 'no' ) === 'yes', ) ); return wp_parse_args( $db_option, $defaults ); } /** * Check whether a given request has permission to read notes. * * @param WP_REST_Request $request Full details about the request. * @return WP_Error|bool * @since 4.0.0 */ public function get_permissions_check( $request ) { if ( ! current_user_can( 'edit_theme_options' ) ) { return new WP_Error( 'astra_rest_cannot_view', esc_html__( 'Sorry, you cannot list resources.', 'astra' ), array( 'status' => rest_authorization_required_code() ) ); } return true; } /** * Returns an value, * based on the settings database option for the admin settings page. * * @param string $key The sub-option key. * @param mixed $default Option default value if option is not available. * @return mixed Return the option value based on provided key * @since 4.0.0 */ public static function get_admin_settings_option( $key, $default = false ) { return isset( self::$astra_admin_settings[ $key ] ) ? self::$astra_admin_settings[ $key ] : $default; } /** * Update an value of a key, * from the settings database option for the admin settings page. * * @param string $key The option key. * @param mixed $value The value to update. * @return mixed Return the option value based on provided key * @since 4.0.0 */ public static function update_admin_settings_option( $key, $value ) { $astra_admin_updated_settings = get_option( self::$option_name, array() ); $astra_admin_updated_settings[ $key ] = $value; update_option( self::$option_name, $astra_admin_updated_settings ); } } Astra_API_Init::get_instance(); class-astra-menu.php 0000644 00000132463 15104072660 0010446 0 ustar 00 <?php /** * Class Astra_Menu. * * @package Astra * @since 4.0.0 */ if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } /** * Astra_Menu. * * @since 4.1.0 */ class Astra_Menu { /** * Instance * * @var null $instance * @since 4.0.0 */ private static $instance; /** * Initiator * * @since 4.0.0 * @return object initialized object of class. */ public static function get_instance() { if ( ! isset( self::$instance ) ) { /** @psalm-suppress InvalidPropertyAssignmentValue */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort self::$instance = new self(); /** @psalm-suppress InvalidPropertyAssignmentValue */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort } return self::$instance; } /** * Page title * * @since 4.0.0 * @var string $page_title */ public static $page_title = 'Astra'; /** * Plugin slug * * @since 4.0.0 * @var string $plugin_slug */ public static $plugin_slug = 'astra'; /** * Constructor * * @since 4.0.0 */ public function __construct() { $this->initialize_hooks(); } /** * Init Hooks. * * @since 4.0.0 * @return void */ public function initialize_hooks() { self::$plugin_slug = self::get_theme_page_slug(); add_action( 'admin_menu', array( $this, 'setup_menu' ) ); add_action( 'admin_init', array( $this, 'settings_admin_scripts' ) ); add_filter( 'install_plugins_tabs', array( $this, 'add_astra_woo_suggestions_link' ), 1 ); add_action( 'install_plugins_pre_astra-woo', array( $this, 'update_plugin_suggestions_tab_link' ) ); } /** * Add Astra~Woo Suggestions plugin tab link. * * @param array $tabs Plugin tabs. * @since 4.7.3 * @return array */ public function add_astra_woo_suggestions_link( $tabs ) { if ( class_exists( 'WooCommerce' ) ) { $tabs['astra-woo'] = esc_html__( 'For ', 'astra' ) . self::$page_title . '~Woo'; } return $tabs; } /** * Update plugin suggestions tab link. * * @since 4.7.3 * @return void */ public function update_plugin_suggestions_tab_link() { // phpcs:disable WordPress.Security.NonceVerification.Recommended if ( ! isset( $_GET['tab'] ) || 'astra-woo' !== $_GET['tab'] ) { return; } // phpcs:enable WordPress.Security.NonceVerification.Recommended $extensions_url = add_query_arg( array( 'page' => self::$plugin_slug, 'path' => 'woocommerce', 'ref' => 'plugins', ), admin_url( 'admin.php' ) ); wp_safe_redirect( $extensions_url ); exit; } /** * Theme options page Slug getter including White Label string. * * @since 4.0.0 * @return string Theme Options Page Slug. */ public static function get_theme_page_slug() { return apply_filters( 'astra_theme_page_slug', self::$plugin_slug ); } /** * Initialize after Astra gets loaded. * * @since 4.0.0 */ public function settings_admin_scripts() { // Enqueue admin scripts. /** @psalm-suppress PossiblyInvalidArgument */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort if ( ! empty( $_GET['page'] ) && ( self::$plugin_slug === $_GET['page'] || false !== strpos( $_GET['page'], self::$plugin_slug . '_' ) ) ) { //phpcs:ignore /** @psalm-suppress PossiblyInvalidArgument */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort add_action( 'admin_enqueue_scripts', array( $this, 'styles_scripts' ) ); add_filter( 'admin_footer_text', array( $this, 'astra_admin_footer_link' ), 99 ); } } /** * Add submenu to admin menu. * * @since 4.0.0 */ public function setup_menu() { global $submenu; $capability = 'manage_options'; if ( ! current_user_can( $capability ) ) { return; } self::$page_title = apply_filters( 'astra_page_title', esc_html__( 'Astra', 'astra' ) ); $astra_icon = apply_filters( 'astra_menu_icon', 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNzcyIiBoZWlnaHQ9Ijc3MiIgdmlld0JveD0iMCAwIDc3MiA3NzIiIGZpbGw9IiNhN2FhYWQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+DQo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTM4NiA3NzJDNTk5LjE4MiA3NzIgNzcyIDU5OS4xODIgNzcyIDM4NkM3NzIgMTcyLjgxOCA1OTkuMTgyIDAgMzg2IDBDMTcyLjgxOCAwIDAgMTcyLjgxOCAwIDM4NkMwIDU5OS4xODIgMTcyLjgxOCA3NzIgMzg2IDc3MlpNMjYxLjcxMyAzNDMuODg2TDI2MS42NzUgMzQzLjk2OEMyMjIuNDE3IDQyNi45OTQgMTgzLjE1OSA1MTAuMDE5IDE0My45MDIgNTkyLjk1MkgyNDQuODQ3QzI3Ni42MjcgNTI4LjczOSAzMDguNDA3IDQ2NC40MzQgMzQwLjE4NyA0MDAuMTI4QzM3MS45NjUgMzM1LjgyNyA0MDMuNzQyIDI3MS41MjcgNDM1LjUyIDIwNy4zMkwzNzkuNDQgOTVDMzQwLjE5NyAxNzcuOSAzMDAuOTU1IDI2MC44OTMgMjYxLjcxMyAzNDMuODg2Wk00MzYuNjczIDQwNC4wNzVDNDUyLjkwNiAzNzAuNzQ1IDQ2OS4xMzkgMzM3LjQxNSA0ODUuNDY3IDMwNC4wODVDNTA5LjMwMSAzNTIuMjI5IDUzMy4wNDIgNDAwLjM3NCA1NTYuNzgyIDQ0OC41MThDNTgwLjUyMyA0OTYuNjYzIDYwNC4yNjQgNTQ0LjgwNyA2MjguMDk4IDU5Mi45NTJINTE5LjI0OEM1MTMuMDU0IDU3OC42OTMgNTA2Ljc2NyA1NjQuNTI3IDUwMC40OCA1NTAuMzYyQzQ5NC4xOTMgNTM2LjE5NiA0ODcuOTA2IDUyMi4wMzEgNDgxLjcxMyA1MDcuNzczSDM4NkwzODcuODc3IDUwNC4wNjlDNDA0LjIwNSA0NzAuNzM4IDQyMC40MzkgNDM3LjQwNiA0MzYuNjczIDQwNC4wNzVaIiBmaWxsPSIjYTdhYWFkIi8+DQo8L3N2Zz4=' ); $priority = apply_filters( 'astra_menu_priority', 59 ); add_menu_page( // phpcs:ignore WPThemeReview.PluginTerritory.NoAddAdminPages.add_menu_pages_add_menu_page -- Taken the menu on top level self::$page_title, self::$page_title, $capability, self::$plugin_slug, array( $this, 'render_admin_dashboard' ), $astra_icon, $priority ); // Add Customize submenu. add_submenu_page( // phpcs:ignore WPThemeReview.PluginTerritory.NoAddAdminPages.add_menu_pages_add_submenu_page -- Taken the menu on top level self::$plugin_slug, __( 'Customize', 'astra' ), __( 'Customize', 'astra' ), $capability, 'customize.php' ); // Add Custom Layout submenu. /** @psalm-suppress UndefinedClass */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $show_custom_layout_submenu = defined( 'ASTRA_EXT_VER' ) && ! Astra_Ext_Extension::is_active( 'advanced-hooks' ) ? false : true; /** @psalm-suppress UndefinedClass */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort if ( $show_custom_layout_submenu && defined( 'ASTRA_EXT_VER' ) && version_compare( ASTRA_EXT_VER, '4.5.0', '<' ) ) { add_submenu_page( // phpcs:ignore WPThemeReview.PluginTerritory.NoAddAdminPages.add_menu_pages_add_submenu_page -- Taken the menu on top level self::$plugin_slug, __( 'Custom Layouts', 'astra' ), __( 'Custom Layouts', 'astra' ), $capability, /* @psalm-suppress UndefinedClass */ defined( 'ASTRA_EXT_VER' ) && Astra_Ext_Extension::is_active( 'advanced-hooks' ) ? 'edit.php?post_type=astra-advanced-hook' : 'admin.php?page=' . self::$plugin_slug . '&path=custom-layouts' ); } if ( ! astra_is_white_labelled() ) { // Add Astra~Woo Extensions page or Spectra submenu. /** @psalm-suppress TypeDoesNotContainType */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort if ( ASTRA_THEME_ORG_VERSION && class_exists( 'WooCommerce' ) ) { /** @psalm-suppress TypeDoesNotContainType */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort add_submenu_page( // phpcs:ignore WPThemeReview.PluginTerritory.NoAddAdminPages.add_menu_pages_add_submenu_page -- Taken the menu on top level self::$plugin_slug, 'WooCommerce', 'WooCommerce', $capability, 'admin.php?page=' . self::$plugin_slug . '&path=woocommerce' ); } elseif ( ASTRA_THEME_ORG_VERSION && ! $this->spectra_has_top_level_menu() ) { add_submenu_page( // phpcs:ignore WPThemeReview.PluginTerritory.NoAddAdminPages.add_menu_pages_add_submenu_page -- Taken the menu on top level self::$plugin_slug, 'Spectra', 'Spectra', $capability, $this->get_spectra_page_admin_link() ); } } // Rename to Home menu. $submenu[ self::$plugin_slug ][0][0] = esc_html__( 'Dashboard', 'astra' ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Required to rename the home menu. } /** * In version 2.4.1 Spectra introduces top level admin menu so there is no meaning to show Spectra submenu from Astra menu. * * @since 4.1.4 * @return bool true|false. */ public function spectra_has_top_level_menu() { return defined( 'UAGB_VER' ) && version_compare( UAGB_VER, '2.4.1', '>=' ) ? true : false; } /** * Provide the Spectra admin page URL. * * @since 4.1.1 * @return string url. */ public function get_spectra_page_admin_link() { $spectra_admin_url = defined( 'UAGB_VER' ) ? ( $this->spectra_has_top_level_menu() ? admin_url( 'admin.php?page=' . UAGB_SLUG ) : admin_url( 'options-general.php?page=' . UAGB_SLUG ) ) : 'admin.php?page=' . self::$plugin_slug . '&path=spectra'; return apply_filters( 'astra_dashboard_spectra_admin_link', $spectra_admin_url ); } /** * Renders the admin settings. * * @since 4.0.0 * @return void */ public function render_admin_dashboard() { $page_action = ''; if ( isset( $_GET['action'] ) ) { //phpcs:ignore /** @psalm-suppress PossiblyInvalidArgument */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $page_action = sanitize_text_field( wp_unslash( $_GET['action'] ) ); //phpcs:ignore /** @psalm-suppress PossiblyInvalidArgument */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $page_action = str_replace( '_', '-', $page_action ); } ?> <div class="ast-menu-page-wrapper"> <div id="ast-menu-page"> <div class="ast-menu-page-content"> <div id="astra-dashboard-app" class="astra-dashboard-app"> </div> </div> </div> </div> <?php } /** * Enqueues the needed CSS/JS for the builder's admin settings page. * * @since 4.0.0 */ public function styles_scripts() { if ( is_customize_preview() ) { return; } wp_enqueue_style( 'astra-admin-font', 'https://fonts.googleapis.com/css2?family=Inter:wght@200;400;500&display=swap', array(), ASTRA_THEME_VERSION ); // Styles. wp_enqueue_style( 'wp-components' ); /** @psalm-suppress UndefinedClass */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $show_self_branding = defined( 'ASTRA_EXT_VER' ) && is_callable( 'Astra_Ext_White_Label_Markup::show_branding' ) ? Astra_Ext_White_Label_Markup::show_branding() : true; /** @psalm-suppress UndefinedClass */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $user_firstname = wp_get_current_user()->user_firstname; /** @psalm-suppress TypeDoesNotContainType */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $astra_addon_locale = ASTRA_THEME_ORG_VERSION ? 'astra-addon/astra-addon.php' : 'astra-pro/astra-pro.php'; /** @psalm-suppress TypeDoesNotContainType */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $localize = array( 'current_user' => ! empty( $user_firstname ) ? ucfirst( $user_firstname ) : ucfirst( wp_get_current_user()->display_name ), 'admin_base_url' => admin_url(), 'plugin_dir' => ASTRA_THEME_URI, 'plugin_ver' => defined( 'ASTRA_EXT_VER' ) ? ASTRA_EXT_VER : '', 'version' => ASTRA_THEME_VERSION, 'pro_available' => defined( 'ASTRA_EXT_VER' ) ? true : false, 'pro_installed_status' => 'installed' === self::get_plugin_status( $astra_addon_locale ) ? true : false, 'astra_addon_locale' => $astra_addon_locale, /** @psalm-suppress TypeDoesNotContainType */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort 'astra_rating_url' => ASTRA_THEME_ORG_VERSION ? 'https://wordpress.org/support/theme/astra/reviews/?rate=5#new-post' : 'https://woo.com/products/astra/#reviews', /** @psalm-suppress TypeDoesNotContainType */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort 'spectra_plugin_status' => self::get_plugin_status( 'ultimate-addons-for-gutenberg/ultimate-addons-for-gutenberg.php' ), 'theme_name' => astra_get_theme_name(), 'plugin_name' => astra_get_addon_name(), 'quick_settings' => self::astra_get_quick_links(), 'ajax_url' => admin_url( 'admin-ajax.php' ), 'is_whitelabel' => astra_is_white_labelled(), 'show_self_branding' => $show_self_branding, 'admin_url' => admin_url( 'admin.php' ), 'home_slug' => self::$plugin_slug, 'upgrade_url' => astra_get_upgrade_url( 'dashboard' ), 'customize_url' => admin_url( 'customize.php' ), 'astra_base_url' => admin_url( 'admin.php?page=' . self::$plugin_slug ), 'logo_url' => apply_filters( 'astra_admin_menu_icon', ASTRA_THEME_URI . 'inc/assets/images/astra-logo.svg' ), 'update_nonce' => wp_create_nonce( 'astra_update_admin_setting' ), /** @psalm-suppress TypeDoesNotContainType */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort 'show_plugins' => apply_filters( 'astra_show_free_extend_plugins', true ) && ASTRA_THEME_ORG_VERSION ? true : false, // Legacy filter support. /** @psalm-suppress TypeDoesNotContainType */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort 'useful_plugins' => self::astra_get_useful_plugins(), 'extensions' => self::astra_get_pro_extensions(), 'plugin_manager_nonce' => wp_create_nonce( 'astra_plugin_manager_nonce' ), 'plugin_installer_nonce' => wp_create_nonce( 'updates' ), 'free_vs_pro_link' => admin_url( 'admin.php?page=' . self::$plugin_slug . '&path=free-vs-pro' ), 'show_builder_migration' => Astra_Builder_Helper::is_header_footer_builder_active(), 'plugin_installing_text' => esc_html__( 'Installing', 'astra' ), 'plugin_installed_text' => esc_html__( 'Installed', 'astra' ), 'plugin_activating_text' => esc_html__( 'Activating', 'astra' ), 'plugin_activated_text' => esc_html__( 'Activated', 'astra' ), 'plugin_activate_text' => esc_html__( 'Activate', 'astra' ), 'starter_templates_data' => self::get_starter_template_plugin_data(), 'astra_docs_data' => astra_remote_docs_data(), 'upgrade_notice' => astra_showcase_upgrade_notices(), 'show_banner_video' => apply_filters( 'astra_show_banner_video', true ), 'is_woo_active' => class_exists( 'WooCommerce' ) ? true : false, 'woo_extensions' => self::astra_get_woo_extensions( false ), 'astraWebsite' => array( 'baseUrl' => ASTRA_WEBSITE_BASE_URL, 'docsUrl' => astra_get_pro_url( '/docs/', 'free-theme', 'dashboard', 'documentation' ), 'docsCategoryDynamicUrl' => astra_get_pro_url( '/docs-category/{{category}}', 'free-theme', 'dashboard', 'documentation' ), 'vipPrioritySupportUrl' => astra_get_pro_url( '/vip-priority-support/', 'free-theme', 'dashboard', 'vip-priority-support' ), 'templatesUrl' => astra_get_pro_url( '/website-templates/', 'free-theme', 'dashboard', 'starter-templates' ), 'whatsNewFeedUrl' => esc_url( ASTRA_WEBSITE_BASE_URL . '/whats-new/feed/' ), ), /** @psalm-suppress TypeDoesNotContainType */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort 'astra_cta_btn_url' => ASTRA_THEME_ORG_VERSION ? astra_get_pro_url( '/pricing/', 'free-theme', 'dashboard', 'unlock-pro-features-CTA' ) : 'https://woocommerce.com/products/astra-pro/', /** @psalm-suppress TypeDoesNotContainType */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort 'plugin_configuring_text' => esc_html__( 'Configuring', 'astra' ), 'bsfUsageTrackingUrl' => 'https://store.brainstormforce.com/usage-tracking/?utm_source=astra&utm_medium=dashboard&utm_campaign=usage_tracking', ); $this->settings_app_scripts( apply_filters( 'astra_react_admin_localize', $localize ) ); } /** * Get customizer quick links for easy navigation. * * @return array * @since 4.0.0 */ public static function astra_get_quick_links() { return apply_filters( 'astra_quick_settings', array( 'logo-favicon' => array( 'title' => __( 'Site Identity', 'astra' ), 'quick_url' => admin_url( 'customize.php?autofocus[control]=site_icon' ), ), 'header' => array( 'title' => __( 'Header Settings', 'astra' ), 'quick_url' => admin_url( 'customize.php?autofocus[panel]=panel-header-group' ), ), 'footer' => array( 'title' => __( 'Footer Settings', 'astra' ), 'quick_url' => admin_url( 'customize.php?autofocus[section]=section-footer-group' ), ), 'colors' => array( 'title' => __( 'Color', 'astra' ), 'quick_url' => admin_url( 'customize.php?autofocus[section]=section-colors-background' ), ), 'typography' => array( 'title' => __( 'Typography', 'astra' ), 'quick_url' => admin_url( 'customize.php?autofocus[section]=section-typography' ), ), 'button' => array( 'title' => __( 'Button', 'astra' ), 'quick_url' => admin_url( 'customize.php?autofocus[section]=section-buttons' ), ), 'blog-options' => array( 'title' => __( 'Blog Options', 'astra' ), 'quick_url' => admin_url( 'customize.php?autofocus[section]=section-blog-group' ), ), 'layout' => array( 'title' => __( 'Layout', 'astra' ), 'quick_url' => admin_url( 'customize.php?autofocus[section]=section-container-layout' ), ), ) ); } /** * Check if Starter Templates promotions is being disabled. * * @return bool * @since 4.8.9 */ public static function is_promoting_starter_templates() { /** * Filter to disable Starter Templates promotions. * Used in the Website Learners platform: A popular YouTube channel that has been our partner since 2017. * * @param bool $disable_starter_templates_promotions Whether to disable Starter Templates promotions. * * @since 4.8.9 */ return ! apply_filters( 'astra_disable_starter_templates_promotions', false ); } /** * Get Starter Templates plugin data. * * @return array * @since 4.0.0 */ public static function get_starter_template_plugin_data() { /** @psalm-suppress UndefinedClass */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $st_data = array( 'title' => is_callable( 'Astra_Ext_White_Label_Markup::get_whitelabel_string' ) ? Astra_Ext_White_Label_Markup::get_whitelabel_string( 'astra-sites', 'name', __( 'Starter Templates', 'astra' ) ) : __( 'Starter Templates', 'astra' ), 'description' => is_callable( 'Astra_Ext_White_Label_Markup::get_whitelabel_string' ) ? Astra_Ext_White_Label_Markup::get_whitelabel_string( 'astra-sites', 'description', __( 'Create professional designed pixel perfect websites in minutes. Get access to 300+ pre-made full website templates for your favorite page builder.', 'astra' ) ) : __( 'Create professional designed pixel perfect websites in minutes. Get access to 300+ pre-made full website templates for your favorite page builder.', 'astra' ), 'is_available' => defined( 'ASTRA_PRO_SITES_VER' ) || defined( 'ASTRA_SITES_VER' ) ? true : false, 'redirection' => admin_url( 'themes.php?page=starter-templates' ), 'icon_path' => 'https://ps.w.org/astra-sites/assets/icon-256x256.gif', 'is_promoting' => self::is_promoting_starter_templates(), ); /** @psalm-suppress UndefinedClass */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $skip_free_version = false; $pro_plugin_status = self::get_plugin_status( 'astra-pro-sites/astra-pro-sites.php' ); if ( 'installed' === $pro_plugin_status || 'activated' === $pro_plugin_status ) { $skip_free_version = true; $st_data['slug'] = 'astra-pro-sites'; $st_data['status'] = $pro_plugin_status; $st_data['path'] = 'astra-pro-sites/astra-pro-sites.php'; } $free_plugin_status = self::get_plugin_status( 'astra-sites/astra-sites.php' ); if ( ! $skip_free_version ) { $st_data['slug'] = 'astra-sites'; $st_data['status'] = $free_plugin_status; $st_data['path'] = 'astra-sites/astra-sites.php'; } return $st_data; } /** * Method to check plugin configuration status. * * @since 4.8.2 * * @param string $plugin_init_file Plugin init file. * * @return bool Returns true if plugin is configured, false otherwise. */ public static function is_plugin_configured( $plugin_init_file ) { switch ( $plugin_init_file ) { case 'surecart/surecart.php': /** @psalm-suppress UndefinedClass */ return class_exists( '\SureCart\Models\ApiToken' ) && \SureCart\Models\ApiToken::get(); case 'suretriggers/suretriggers.php': if ( class_exists( '\SureTriggers\Controllers\OptionController' ) ) { /** @psalm-suppress UndefinedClass */ $st_key = \SureTriggers\Controllers\OptionController::get_option( 'secret_key' ); return $st_key && $st_key !== 'connection-denied'; } // Fall through: Intentional fall-through without returning. return false; case 'checkout-plugins-stripe-woo/checkout-plugins-stripe-woo.php': // If the setup is not skipped and connected to the Stripe. /** @psalm-suppress UndefinedClass */ return 'skipped' !== get_option( 'cpsw_setup_status', false ) && class_exists( '\CPSW\Admin\Admin_Controller' ) && \CPSW\Admin\Admin_Controller::get_instance()->is_stripe_connected(); case 'checkout-paypal-woo/checkout-paypal-woo.php': if ( ! class_exists( '\CPPW\Gateway\Paypal\Api\Client' ) ) { return false; } $remote_url = 'v1/identity/oauth2/userinfo?schema=paypalv1.1'; try { /** @psalm-suppress UndefinedClass */ $response = \CPPW\Gateway\Paypal\Api\Client::request( $remote_url, array(), 'get' ); if ( ! is_array( $response ) || empty( $response['user_id'] ) ) { return false; } return true; } catch ( \Exception $e ) { // Handle exception silently. return false; } // Fall through: This catch block will always return false if an exception is caught. return false; } return true; } /** * Get plugin status * * @since 4.0.0 * * @param string $plugin_init_file Plugin init file. * @return mixed */ public static function get_plugin_status( $plugin_init_file ) { $installed_plugins = get_plugins(); if ( ! isset( $installed_plugins[ $plugin_init_file ] ) ) { return 'install'; } if ( is_plugin_active( $plugin_init_file ) ) { if ( ! self::is_plugin_configured( $plugin_init_file ) ) { return 'configure'; } return 'activated'; } return 'installed'; } /** * Get Astra's pro extension list. * * @since 4.0.0 * @return array */ public static function astra_get_pro_extensions() { return apply_filters( 'astra_addon_list', array( 'colors-and-background' => array( 'title' => __( 'Colors & Background', 'astra' ), 'class' => 'ast-addon', 'title_url' => astra_get_pro_url( '/docs/colors-background-module/', 'free-theme', 'dashboard', 'documentation' ), 'links' => array( array( 'link_class' => 'ast-learn-more', 'link_url' => astra_get_pro_url( '/docs/colors-background-module/', 'free-theme', 'dashboard', 'documentation' ), 'link_text' => __( 'Documentation', 'astra' ), 'target_blank' => true, ), ), ), 'typography' => array( 'title' => __( 'Typography', 'astra' ), 'class' => 'ast-addon', 'title_url' => astra_get_pro_url( '/docs/typography-module/', 'free-theme', 'dashboard', 'documentation' ), 'links' => array( array( 'link_class' => 'ast-learn-more', 'link_url' => astra_get_pro_url( '/docs/typography-module/', 'free-theme', 'dashboard', 'documentation' ), 'link_text' => __( 'Documentation', 'astra' ), 'target_blank' => true, ), ), ), 'spacing' => array( 'title' => __( 'Spacing', 'astra' ), 'class' => 'ast-addon', 'title_url' => astra_get_pro_url( '/docs/spacing-addon-overview/', 'free-theme', 'dashboard', 'documentation' ), 'links' => array( array( 'link_class' => 'ast-learn-more', 'link_url' => astra_get_pro_url( '/docs/spacing-addon-overview/', 'free-theme', 'dashboard', 'documentation' ), 'link_text' => __( 'Documentation', 'astra' ), 'target_blank' => true, ), ), ), 'blog-pro' => array( 'title' => __( 'Blog Pro', 'astra' ), 'class' => 'ast-addon', 'title_url' => astra_get_pro_url( '/docs/blog-pro-overview/', 'free-theme', 'dashboard', 'documentation' ), 'links' => array( array( 'link_class' => 'ast-learn-more', 'link_url' => astra_get_pro_url( '/docs/blog-pro-overview/', 'free-theme', 'dashboard', 'documentation' ), 'link_text' => __( 'Documentation', 'astra' ), 'target_blank' => true, ), ), ), 'mobile-header' => array( 'title' => __( 'Mobile Header', 'astra' ), 'class' => 'ast-addon', 'title_url' => astra_get_pro_url( '/docs/mobile-header-with-astra/', 'free-theme', 'dashboard', 'documentation' ), 'links' => array( array( 'link_class' => 'ast-learn-more', 'link_url' => astra_get_pro_url( '/docs/mobile-header-with-astra/', 'free-theme', 'dashboard', 'documentation' ), 'link_text' => __( 'Documentation', 'astra' ), 'target_blank' => true, ), ), ), 'header-sections' => array( 'title' => __( 'Header Sections', 'astra' ), 'class' => 'ast-addon', 'title_url' => astra_get_pro_url( '/docs/header-sections-pro/', 'free-theme', 'dashboard', 'documentation' ), 'links' => array( array( 'link_class' => 'ast-learn-more', 'link_url' => astra_get_pro_url( '/docs/header-sections-pro/', 'free-theme', 'dashboard', 'documentation' ), 'link_text' => __( 'Documentation', 'astra' ), 'target_blank' => true, ), ), ), 'sticky-header' => array( 'title' => __( 'Sticky Header', 'astra' ), 'class' => 'ast-addon', 'title_url' => astra_get_pro_url( '/docs/sticky-header-pro/', 'free-theme', 'dashboard', 'documentation' ), 'links' => array( array( 'link_class' => 'ast-learn-more', 'link_url' => astra_get_pro_url( '/docs/sticky-header-pro/', 'free-theme', 'dashboard', 'documentation' ), 'link_text' => __( 'Documentation', 'astra' ), 'target_blank' => true, ), ), ), 'site-layouts' => array( 'title' => __( 'Site Layouts', 'astra' ), 'class' => 'ast-addon', 'title_url' => astra_get_pro_url( '/docs/site-layout-overview/', 'free-theme', 'dashboard', 'documentation' ), 'links' => array( array( 'link_class' => 'ast-learn-more', 'link_url' => astra_get_pro_url( '/docs/site-layout-overview/', 'free-theme', 'dashboard', 'documentation' ), 'link_text' => __( 'Documentation', 'astra' ), 'target_blank' => true, ), ), ), 'advanced-footer' => array( 'title' => __( 'Footer Widgets', 'astra' ), 'class' => 'ast-addon', 'title_url' => astra_get_pro_url( '/docs/footer-widgets-astra-pro/', 'free-theme', 'dashboard', 'documentation' ), 'links' => array( array( 'link_class' => 'ast-learn-more', 'link_url' => astra_get_pro_url( '/docs/footer-widgets-astra-pro/', 'free-theme', 'dashboard', 'documentation' ), 'link_text' => __( 'Documentation', 'astra' ), 'target_blank' => true, ), ), ), 'nav-menu' => array( 'title' => __( 'Nav Menu', 'astra' ), 'class' => 'ast-addon', 'title_url' => astra_get_pro_url( '/docs/nav-menu-addon/', 'free-theme', 'dashboard', 'documentation' ), 'links' => array( array( 'link_class' => 'ast-learn-more', 'link_url' => astra_get_pro_url( '/docs/nav-menu-addon/', 'free-theme', 'dashboard', 'documentation' ), 'link_text' => __( 'Documentation', 'astra' ), 'target_blank' => true, ), ), ), 'advanced-hooks' => array( 'title' => defined( 'ASTRA_EXT_VER' ) && version_compare( ASTRA_EXT_VER, '4.5.0', '<' ) ? __( 'Custom Layouts', 'astra' ) : __( 'Site Builder', 'astra' ), 'description' => __( 'Add content conditionally in the various hook areas of the theme.', 'astra' ), 'manage_settings' => true, 'class' => 'ast-addon', 'title_url' => astra_get_pro_url( '/docs/custom-layouts-pro/', 'free-theme', 'dashboard', 'documentation' ), 'links' => array( array( 'link_class' => 'ast-learn-more', 'link_url' => astra_get_pro_url( '/docs/custom-layouts-pro/', 'free-theme', 'dashboard', 'documentation' ), 'link_text' => __( 'Documentation', 'astra' ), 'target_blank' => true, ), ), ), 'advanced-headers' => array( 'title' => __( 'Page Headers', 'astra' ), 'description' => __( 'Make your header layouts look more appealing and sexy!', 'astra' ), 'manage_settings' => true, 'class' => 'ast-addon', 'title_url' => astra_get_pro_url( '/docs/page-headers-overview/', 'free-theme', 'dashboard', 'documentation' ), 'links' => array( array( 'link_class' => 'ast-learn-more', 'link_url' => astra_get_pro_url( '/docs/page-headers-overview/', 'free-theme', 'dashboard', 'documentation' ), 'link_text' => __( 'Documentation', 'astra' ), 'target_blank' => true, ), ), ), 'woocommerce' => array( 'title' => 'WooCommerce', 'class' => 'ast-addon', 'isActive' => defined( 'ASTRA_EXT_VER' ) && class_exists( 'WooCommerce' ) ? true : false, 'title_url' => astra_get_pro_url( '/docs/woocommerce-module-overview/', 'free-theme', 'dashboard', 'documentation' ), 'links' => array( array( 'link_class' => 'ast-learn-more', 'link_url' => astra_get_pro_url( '/docs/woocommerce-module-overview/', 'free-theme', 'dashboard', 'documentation' ), 'link_text' => __( 'Documentation', 'astra' ), 'target_blank' => true, ), ), ), 'edd' => array( 'title' => 'Easy Digital Downloads', 'class' => 'ast-addon', 'isActive' => defined( 'ASTRA_EXT_VER' ) && class_exists( 'Easy_Digital_Downloads' ) ? true : false, 'title_url' => astra_get_pro_url( '/docs/easy-digital-downloads-module-overview/', 'free-theme', 'dashboard', 'documentation' ), 'links' => array( array( 'link_class' => 'ast-learn-more', 'link_url' => astra_get_pro_url( '/docs/easy-digital-downloads-module-overview/', 'free-theme', 'dashboard', 'documentation' ), 'link_text' => __( 'Documentation', 'astra' ), 'target_blank' => true, ), ), ), 'learndash' => array( 'title' => 'LearnDash', 'isActive' => defined( 'ASTRA_EXT_VER' ) && class_exists( 'SFWD_LMS' ) ? true : false, 'description' => __( 'Supercharge your LearnDash website with amazing design features.', 'astra' ), 'class' => 'ast-addon', 'title_url' => astra_get_pro_url( '/docs/learndash-integration-in-astra-pro/', 'free-theme', 'dashboard', 'documentation' ), 'links' => array( array( 'link_class' => 'ast-learn-more', 'link_url' => astra_get_pro_url( '/docs/learndash-integration-in-astra-pro/', 'free-theme', 'dashboard', 'documentation' ), 'link_text' => __( 'Documentation', 'astra' ), 'target_blank' => true, ), ), ), 'lifterlms' => array( 'title' => 'LifterLMS', 'class' => 'ast-addon', 'isActive' => defined( 'ASTRA_EXT_VER' ) && class_exists( 'LifterLMS' ) ? true : false, 'title_url' => astra_get_pro_url( '/docs/lifterlms-module-pro/', 'free-theme', 'dashboard', 'documentation' ), 'links' => array( array( 'link_class' => 'ast-learn-more', 'link_url' => astra_get_pro_url( '/docs/lifterlms-module-pro/', 'free-theme', 'dashboard', 'documentation' ), 'link_text' => __( 'Documentation', 'astra' ), 'target_blank' => true, ), ), ), 'white-label' => array( 'title' => __( 'White Label', 'astra' ), 'class' => 'ast-addon', 'title_url' => astra_get_pro_url( '/docs/how-to-white-label-astra/', 'free-theme', 'dashboard', 'documentation' ), 'links' => array( array( 'link_class' => 'ast-learn-more', 'link_url' => astra_get_pro_url( '/docs/how-to-white-label-astra/', 'free-theme', 'dashboard', 'documentation' ), 'link_text' => __( 'Documentation', 'astra' ), 'target_blank' => true, ), ), ), ) ); } /** * Get Astra's recommended WooCommerce extensions. * * @param bool $under_useful_plugins Add under useful plugins or not. * * @since 4.7.3 * @return array */ public static function astra_get_woo_extensions( $under_useful_plugins = true ) { $extensions = array( array( 'title' => 'CartFlows: Create Sales Funnel', 'subtitle' => $under_useful_plugins ? __( '#1 Sales Funnel WordPress Builder.', 'astra' ) : __( 'Build high-converting E-Commerce stores with CartFlows, the ultimate checkout and funnel builder.', 'astra' ), 'status' => self::get_plugin_status( 'cartflows/cartflows.php' ), 'slug' => 'cartflows', 'path' => 'cartflows/cartflows.php', 'redirection' => false === get_option( 'wcf_setup_complete', false ) && ! get_option( 'wcf_setup_skipped', false ) ? admin_url( 'index.php?page=cartflow-setup' ) : admin_url( 'admin.php?page=cartflows' ), 'ratings' => '(400+)', 'activations' => '200,000 +', 'logoPath' => array( 'internal_icon' => false, 'icon_path' => 'https://ps.w.org/cartflows/assets/icon-256x256.gif', ), ), ); if ( ! $under_useful_plugins ) { $extensions[] = array( 'title' => 'OttoKit: WordPress Automation', 'subtitle' => __( 'Connect your WordPress plugins, WooCommerce sites, apps, and websites for powerful automations.', 'astra' ), 'status' => self::get_plugin_status( 'suretriggers/suretriggers.php' ), 'slug' => 'suretriggers', 'path' => 'suretriggers/suretriggers.php', 'redirection' => admin_url( 'admin.php?page=suretriggers' ), 'ratings' => '(60+)', 'activations' => '1,00,000 +', 'logoPath' => array( 'internal_icon' => true, 'icon_path' => 'ottokit', ), ); } $extensions[] = array( 'title' => 'Spectra: Blocks Builder', 'subtitle' => $under_useful_plugins ? __( 'Free WordPress Page Builder.', 'astra' ) : __( 'Power-up block editor with advanced blocks for faster and effortlessly website creation.', 'astra' ), 'status' => self::get_plugin_status( 'ultimate-addons-for-gutenberg/ultimate-addons-for-gutenberg.php' ), 'slug' => 'ultimate-addons-for-gutenberg', 'path' => 'ultimate-addons-for-gutenberg/ultimate-addons-for-gutenberg.php', 'redirection' => admin_url( 'options-general.php?page=spectra' ), 'ratings' => '(1500+)', 'activations' => '1,000,000 +', 'logoPath' => array( 'internal_icon' => false, 'icon_path' => 'https://ps.w.org/ultimate-addons-for-gutenberg/assets/icon-256x256.gif', ), ); $extensions[] = array( 'title' => 'Modern Cart for WooCommerce', 'subtitle' => $under_useful_plugins ? __( 'Modern Cart: A smarter way to sell', 'astra' ) : __( 'Say goodbye to slow checkouts – boost sales with a smooth, hassle-free experience.', 'astra' ), 'status' => 'visit', 'slug' => '', 'path' => '', 'redirection' => esc_url( 'https://cartflows.com/modern-cart-for-woocommerce/?utm_source=cross_promotions&utm_medium=referral&utm_campaign=astra_dashboard' ), 'ratings' => '(25+)', 'activations' => '100 +', 'logoPath' => array( 'internal_icon' => true, 'icon_path' => 'moderncart', ), ); if ( ! $under_useful_plugins ) { $extensions[] = array( 'title' => 'PayPal Payments For WooCommerce', 'subtitle' => __( 'PayPal Payments For WooCommerce simplifies and secures PayPal transactions on your store.', 'astra' ), 'status' => self::get_plugin_status( 'checkout-paypal-woo/checkout-paypal-woo.php' ), 'slug' => 'checkout-paypal-woo', 'path' => 'checkout-paypal-woo/checkout-paypal-woo.php', 'redirection' => admin_url( 'admin.php?page=wc-settings&tab=cppw_api_settings' ), 'ratings' => '(2)', 'activations' => '6,000 +', 'logoPath' => array( 'internal_icon' => false, 'icon_path' => 'https://ps.w.org/checkout-paypal-woo/assets/icon-128x128.jpg', ), ); } $extensions[] = array( 'title' => 'Cart Abandonment Recovery', 'subtitle' => $under_useful_plugins ? __( 'Recover lost revenue automatically.', 'astra' ) : __( 'Capture emails at checkout and send follow-up emails to recover lost revenue.', 'astra' ), 'status' => self::get_plugin_status( 'woo-cart-abandonment-recovery/woo-cart-abandonment-recovery.php' ), 'slug' => 'woo-cart-abandonment-recovery', 'path' => 'woo-cart-abandonment-recovery/woo-cart-abandonment-recovery.php', 'redirection' => admin_url( 'admin.php?page=woo-cart-abandonment-recovery' ), 'ratings' => '(490+)', 'activations' => '300,000 +', 'logoPath' => array( 'internal_icon' => false, 'icon_path' => 'https://ps.w.org/woo-cart-abandonment-recovery/assets/icon-128x128.png', ), ); if ( ! $under_useful_plugins ) { $extensions[] = array( 'title' => 'Variations Swatches by CartFlows', 'subtitle' => __( 'Convert WooCommerce variation dropdown attributes into attractive swatches instantly.', 'astra' ), 'status' => self::get_plugin_status( 'variation-swatches-woo/variation-swatches-woo.php' ), 'slug' => 'variation-swatches-woo', 'path' => 'variation-swatches-woo/variation-swatches-woo.php', 'redirection' => admin_url( 'admin.php?page=cfvsw_settings' ), 'ratings' => '(30+)', 'activations' => '200,000 +', 'logoPath' => array( 'internal_icon' => false, 'icon_path' => 'https://ps.w.org/variation-swatches-woo/assets/icon.svg', ), ); } return $extensions; } /** * Get Astra's useful plugins. * Extend this in following way - * * // array( * // 'title' => "Plugin Name", * // 'subtitle' => "Plugin description goes here.", * // 'path' => 'plugin-slug/plugin-slug.php', * // 'redirection' => admin_url( 'admin.php?page=sc-dashboard' ), * // 'status' => self::get_plugin_status( 'plugin-slug/plugin-slug.php' ), * // 'logoPath' => array( * // 'internal_icon' => true, // true = will take internal Astra's any icon. false = provide next custom icon link. * // 'icon_path' => "spectra", // If internal_icon false then - example custom SVG URL: ASTRA_THEME_URI . 'inc/assets/images/astra.svg'. * // ), * // ), * * @since 4.0.0 * @return array */ public static function astra_get_useful_plugins() { // Making useful plugin section dynamic. if ( class_exists( 'WooCommerce' ) ) { $useful_plugins = self::astra_get_woo_extensions(); } else { $surecart_status = self::get_plugin_status( 'surecart/surecart.php' ); $surecart_redirection = 'activated' === $surecart_status ? 'sc-dashboard' : 'sc-getting-started'; $plugins = array( 'surecart' => array( 'title' => 'SureCart', 'subtitle' => __( 'Sell products, services, subscriptions & more.', 'astra' ), 'status' => $surecart_status, 'slug' => 'surecart', 'path' => 'surecart/surecart.php', 'redirection' => admin_url( 'admin.php?page=' . esc_attr( $surecart_redirection ) ), 'logoPath' => array( 'internal_icon' => true, 'icon_path' => 'surecart_logo', ), ), 'spectra' => array( 'title' => 'Spectra', 'subtitle' => __( 'Free WordPress Page Builder.', 'astra' ), 'status' => self::get_plugin_status( 'ultimate-addons-for-gutenberg/ultimate-addons-for-gutenberg.php' ), 'slug' => 'ultimate-addons-for-gutenberg', 'path' => 'ultimate-addons-for-gutenberg/ultimate-addons-for-gutenberg.php', 'redirection' => admin_url( 'options-general.php?page=spectra' ), 'logoPath' => array( 'internal_icon' => false, 'icon_path' => 'https://ps.w.org/ultimate-addons-for-gutenberg/assets/icon-256x256.gif', ), ), 'suretriggers' => array( 'title' => 'OttoKit', 'subtitle' => __( 'Automate your WordPress setup.', 'astra' ), 'isPro' => false, 'status' => self::get_plugin_status( 'suretriggers/suretriggers.php' ), 'slug' => 'suretriggers', 'path' => 'suretriggers/suretriggers.php', 'redirection' => admin_url( 'admin.php?page=suretriggers' ), 'logoPath' => array( 'internal_icon' => true, 'icon_path' => 'ottokit', ), ), 'sureforms' => array( 'title' => 'SureForms', 'subtitle' => __( 'A versatile form builder plugin.', 'astra' ), 'status' => self::get_plugin_status( 'sureforms/sureforms.php' ), 'slug' => 'sureforms', 'path' => 'sureforms/sureforms.php', 'redirection' => admin_url( 'admin.php?page=sureforms_menu' ), 'logoPath' => array( 'internal_icon' => true, 'icon_path' => 'sureforms', ), ), 'presto-player' => array( 'title' => 'Presto Player', 'subtitle' => __( 'Ultimate Video Player For WordPress.', 'astra' ), 'status' => self::get_plugin_status( 'presto-player/presto-player.php' ), 'slug' => 'presto-player', 'path' => 'presto-player/presto-player.php', 'redirection' => admin_url( 'edit.php?post_type=pp_video_block' ), 'logoPath' => array( 'internal_icon' => false, 'icon_path' => 'https://ps.w.org/presto-player/assets/icon-128x128.png', ), ), 'uael' => array( 'title' => 'Ultimate Addons for Elementor', 'subtitle' => __( 'Extend Elementor with premium widgets.', 'astra' ), 'status' => self::get_plugin_status( 'header-footer-elementor/header-footer-elementor.php' ), 'slug' => 'header-footer-elementor', 'path' => 'header-footer-elementor/header-footer-elementor.php', 'redirection' => admin_url( 'admin.php?page=hfe#onboarding' ), 'logoPath' => array( 'internal_icon' => false, 'icon_path' => 'https://ps.w.org/header-footer-elementor/assets/icon-256x256.gif', ), ), ); // Pick useful plugins depending on Elementor status. $useful_plugins_keys = defined( 'ELEMENTOR_VERSION' ) ? array( 'uael', 'sureforms', 'spectra', 'suretriggers', 'presto-player' ) : array( 'sureforms', 'spectra', 'suretriggers', 'surecart', 'presto-player' ); $useful_plugins = array_map( static fn( $key ) => $plugins[ $key ], $useful_plugins_keys ); } return apply_filters( 'astra_useful_plugins', $useful_plugins ); } /** * Settings app scripts * * @since 4.0.0 * @param array $localize Variable names. */ public function settings_app_scripts( $localize ) { $handle = 'astra-admin-dashboard-app'; $build_path = ASTRA_THEME_ADMIN_DIR . 'assets/build/'; $build_url = ASTRA_THEME_ADMIN_URL . 'assets/build/'; $script_asset_path = $build_path . 'dashboard-app.asset.php'; /** @psalm-suppress MissingFile */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $script_info = file_exists( $script_asset_path ) ? include $script_asset_path : array( // phpcs:ignore WPThemeReview.CoreFunctionality.FileInclude.FileIncludeFound -- Not a template file so loading in a normal way. 'dependencies' => array(), 'version' => ASTRA_THEME_VERSION, ); /** @psalm-suppress MissingFile */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $script_dep = array_merge( $script_info['dependencies'], array( 'updates', 'wp-hooks' ) ); wp_register_script( $handle, $build_url . 'dashboard-app.js', $script_dep, $script_info['version'], true ); wp_register_style( $handle, $build_url . 'dashboard-app.css', array(), ASTRA_THEME_VERSION ); wp_enqueue_script( $handle ); wp_set_script_translations( $handle, 'astra' ); wp_enqueue_style( $handle ); wp_style_add_data( $handle, 'rtl', 'replace' ); wp_localize_script( $handle, 'astra_admin', $localize ); } /** * Add footer link. * * @since 4.0.0 */ public function astra_admin_footer_link() { $theme_name = astra_get_theme_name(); /** @psalm-suppress TypeDoesNotContainType */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort $rating_url = ASTRA_THEME_ORG_VERSION ? 'https://wordpress.org/support/theme/astra/reviews/?rate=5#new-post' : 'https://woo.com/products/astra/#reviews'; /** @psalm-suppress TypeDoesNotContainType */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort if ( astra_is_white_labelled() ) { $footer_text = '<span id="footer-thankyou">' . __( 'Thank you for using', 'astra' ) . '<span class="focus:text-astra-hover active:text-astra-hover hover:text-astra-hover"> ' . esc_html( $theme_name ) . '.</span></span>'; } else { $footer_text = sprintf( /* translators: 1: Astra, 2: Theme rating link */ __( 'Enjoyed %1$s? Please leave us a %2$s rating. We really appreciate your support!', 'astra' ), '<span class="ast-footer-thankyou"><strong>' . esc_html( $theme_name ) . '</strong>', '<a href="' . esc_url( $rating_url ) . '" target="_blank">★★★★★</a></span>' ); } return $footer_text; } } Astra_Menu::get_instance(); blocks/safe-svg/block.json 0000644 00000002033 15106016203 0011511 0 ustar 00 { "$schema": "https://schemas.wp.org/trunk/block.json", "apiVersion": 3, "title": "Safe SVG", "description": "Display the SVG icon", "textdomain": "safe-svg", "name": "safe-svg/svg-icon", "category": "design", "attributes": { "svgURL": { "type": "string", "default": "" }, "type": { "type": "string", "default": "full" }, "alignment": { "type": "string" }, "imageID": { "type": "number", "default": 0 }, "imageWidth": { "type": "number" }, "imageHeight": { "type": "number" }, "dimensionWidth": { "type": "number" }, "dimensionHeight": { "type": "number" }, "imageSizes": { "type": "object" } }, "supports": { "html": false, "color": { "text": true, "background": true }, "spacing": { "margin": true, "padding": true } }, "editorScript": "file:../../../dist/safe-svg-block.js", "style": "file:../../../dist/safe-svg-block-frontend.css" } blocks/safe-svg/frontend.js 0000644 00000000143 15106016203 0011701 0 ustar 00 /* global safe-svg_personalizer_params */ /* eslint-disable camelcase */ import './frontend.scss'; blocks/safe-svg/save.js 0000644 00000000176 15106016203 0011026 0 ustar 00
| ver. 1.4 |
Github
|
.
| PHP 8.1.33 | Generation time: 0.02 |
proxy
|
phpinfo
|
Settings