first commit

This commit is contained in:
User A0264400
2026-04-01 23:20:16 +03:00
commit a766acdc90
23071 changed files with 4933189 additions and 0 deletions

View File

@@ -0,0 +1,52 @@
<?php
use WBCR\Factory_Adverts_159\Base;
/**
* Factory Adverts
*
* @author Alexander Vitkalov <nechin.va@gmail.com>
* @author Alexander Kovalev <alex.kovalevv@gmail.com>, Github: https://github.com/alexkovalevv
* @since 1.0.0
*
* @package factory-ad-inserter
* @copyright (c) 2019, Webcraftic Ltd
*
* @version 1.3.9
*/
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( defined( 'FACTORY_ADVERTS_159_LOADED' ) || ( defined( 'FACTORY_ADVERTS_BLOCK' ) && FACTORY_ADVERTS_BLOCK ) ) {
return;
}
# Устанавливаем константу, что модуль уже загружен
define( 'FACTORY_ADVERTS_159_LOADED', true );
# Устанавливаем версию модуля
define( 'FACTORY_ADVERTS_159_VERSION', '1.6.2' );
add_action( 'init', function () {
# Регистрируем тектовый домен, для интернализации интерфейса модуля
load_plugin_textdomain( 'wbcr_factory_adverts_159', false, dirname( plugin_basename( __FILE__ ) ) . '/langs' );
} );
# Устанавливаем директорию модуля
define( 'FACTORY_ADVERTS_159_DIR', dirname( __FILE__ ) );
# Устанавливаем url модуля
define( 'FACTORY_ADVERTS_159_URL', plugins_url( '', __FILE__ ) );
require_once( FACTORY_ADVERTS_159_DIR . '/includes/class-rest-request.php' );
require_once( FACTORY_ADVERTS_159_DIR . '/includes/class-base.php' );
/**
* @param Wbcr_Factory480_Plugin $plugin
*/
add_action( 'wbcr_factory_adverts_159_plugin_created', function ( $plugin ) {
$plugin->set_adverts_manager( "WBCR\Factory_Adverts_159\Base" );
} );

View File

@@ -0,0 +1,319 @@
<?php
namespace WBCR\Factory_Adverts_159;
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Base class for adverts module.
*
* Contains methods for retrieving banner data for a specific position.
* With this class user cat get advert content for a specific position.
* This class use functional design pattern.
*
* @author Alexander Vitkalov <nechin.va@gmail.com>
* @author Alexander Kovalev <alex.kovalevv@gmail.com>, Github: https://github.com/alexkovalevv
*
* @since 1.0.0 Added
* @package factory-adverts
* @copyright (c) 2019 Webcraftic Ltd
*/
class Base {
/**
* Экзепляр плагина с которым взаимодействует этот модуль
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 1.0.1
* @var \Wbcr_Factory480_Plugin
*/
private $plugin;
/*
* Contain array data with the plugin information and the module settings.
* Mainly used to get the name of the plugin and how to get the adverts blocks.
*
* @since 1.0.0 Added
*
* @var array Example: array(
* 'dashboard_widget' => true,
* 'right_sidebar' => true,
* 'notice' => true,
* ...
* )
*
*/
private $settings = [];
/**
* Экземпляр класса для работы API CreativeMotion
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 1.0.1
* @var \WBCR\Factory_Adverts_159\Creative_Motion_API
*/
private $api;
/**
* Сохраняем уже полученные данные, для объектного кеширования
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 1.0.1
* @var array
*/
private $placements = [];
/**
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 1.0.1
* @var array
*/
private $errors = [];
/**
* Wbcr_Factory_Adinserter constructor.
*
* - Store plugin information and settings.
* - Add filter and actions.
* - Include dashboard widget.
*
* @since 1.0.0 Added
*
* @param \Wbcr_Factory480_Plugin $plugin
*/
public function __construct( \Wbcr_Factory480_Plugin $plugin, $settings ) {
$this->plugin = $plugin;
$this->settings = wp_parse_args( $settings, [
'dashboard_widget' => false, // show dashboard widget (default: false)
'right_sidebar' => false, // show adverts sidebar (default: false)
'notice' => false, // show notice message (default: false),
'business_suggetion' => false,
'support' => false
] );
$this->api = new Creative_Motion_API( $this->plugin );
add_filter( 'wbcr/factory/pages/impressive/widgets', [ $this, 'register_plugin_widgets' ], 10, 3 );
add_action( 'wbcr/factory/admin_notices', [ $this, 'register_plugin_notice' ], 10, 2 );
add_action( 'current_screen', [ $this, 'register_dashboard_widget' ], 10, 2 );
}
/**
* Directly get advert content for selected position.
*
* @since 1.0.1 Rename method. Content should now be printed.
* @since 1.0.0 Added
*
* @param string $position Custom position name
*
* @return void
*/
public function render_placement( $position = 'right_sidebar' ) {
$content = '';
if ( $position ) {
$content = $this->get_content( $position );
}
echo $content;
}
/**
* Register widgets.
*
* Depending on the settings, register new widgets.
*
* @since 1.0.0 Added
*
* @param array $widgets Already existing registered widgets
* @param string $position Position for the widget
* @param string $plugin Plugin object for which the hook is run
*
* @return array array(
* 'adverts_widget' => '<p></p>',
* 'business_suggetion' => '<p></p>',
* 'support' => '<p></p>',
* ...
* )
*/
public function register_plugin_widgets( $widgets, $position, $plugin ) {
if ( $plugin->getPluginName() == $this->plugin->getPluginName() && 'right' == $position ) {
if ( $this->settings['right_sidebar'] ) {
$content = $this->get_content( 'right_sidebar' );
$widgets['adverts_widget'] = $content;
if ( empty( $widgets['adverts_widget'] ) ) {
if ( defined( 'FACTORY_ADVERTS_DEBUG' ) && FACTORY_ADVERTS_DEBUG ) {
$debug_message = '<div style="background: #fff4f1;padding: 10px;color: #a58074;">';
$debug_message .= $this->get_debug_message( 'right_sidebar' );
$debug_message .= '</div>';
$widgets['adverts_widget'] = $debug_message;
} else {
unset( $widgets['adverts_widget'] );
}
}
}
if ( $this->settings['business_suggetion'] ) {
$content = $this->get_content( 'business_suggetion' );
if ( ! empty( $content ) ) {
$widgets['business_suggetion'] = $content;
}
}
if ( $this->settings['support'] ) {
$content = $this->get_content( 'support' );
if ( ! empty( $content ) ) {
$widgets['support'] = $content;
}
}
}
return $widgets;
}
/**
* Регистрирует уведомление для текущего плагина
*
* Мы добавляем уведомления в массив всех уведомлений плагина с ключем 'adverts_notice',
* то есть если другие плагины, тоже добавят свои рекламные уведомления, они просто
* будут перезаписывать друг друга, в итоге будет отображено только одно рекламное
* уведомеление. Это нужно для того, чтобы ограничить пользователя от спама.
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
*
* @since 1.0.1 Переделан полностью под интферфейс фреймворка. Используем встроенную систему уведомлений.
* @since 1.0.0 Added
*
* @param array $notices Массив со списком всех уведомлений, которые будут напечатыны в админ панели
* @param string $plugin_name Имя плагина, передано для того, чтобы выводить уведомления условно, только для конкретного плагина
*/
public function register_plugin_notice( $notices, $plugin_name ) {
if ( $plugin_name !== $this->plugin->getPluginName() ) {
return $notices;
}
if ( $this->settings['notice'] ) {
$notice_content = $this->get_content( 'notice' );
if ( empty( $notice_content ) ) {
# Информация для отладки
if ( defined( 'FACTORY_ADVERTS_DEBUG' ) && FACTORY_ADVERTS_DEBUG ) {
$debug_message = $this->get_debug_message( 'notice' );
$notices['adverts_notice'] = [
'id' => 'adverts_debug',
'type' => 'error',
'dismissible' => false,
'dismiss_expires' => 0,
'text' => '<p><b>' . $this->plugin->getPluginTitle() . '</b>:<br>' . $debug_message . '</p>'
];
}
return $notices;
}
$hash = md5( $notice_content );
$notices['adverts_notice'] = [
'id' => 'adverts_' . $hash,
'type' => 'success',
'dismissible' => true,
'dismiss_expires' => 0,
'text' => '<p><b>' . $this->plugin->getPluginTitle() . '</b>:<br>' . $notice_content . '</p>'
];
}
return $notices;
}
/**
* Include dashboard widget
*
* Include functionality the output of the widget on the dashboard.
* Only one dashboard widget must be shown for some plugins with this setting (dashboard_widget).
*
* @since 1.0.0 Added
*/
public function register_dashboard_widget() {
if ( $this->settings['dashboard_widget'] && current_user_can( 'manage_options' ) ) {
$current_screen = get_current_screen();
if ( ! in_array( $current_screen->id, [ 'dashboard', 'dashboard-network' ] ) ) {
return;
}
$content = $this->get_content( 'dashboard_widget' );
if ( empty( $content ) && defined( 'FACTORY_ADVERTS_DEBUG' ) && FACTORY_ADVERTS_DEBUG ) {
$content = $this->get_debug_message( 'dashboard_widget' );
}
require_once FACTORY_ADVERTS_159_DIR . '/includes/class-dashboard-widget.php';
new Dashboard_Widget( $this->plugin, $content );
}
}
/**
* Позволяет получить сообщение об ошибках
*
* Метод проверяет последние ошибки, которые могли произойти в результате api запроса.
* Если ошибки есть, он выводит предупреждение и список последних ошибок. Если ошибок нет,
* метод вернет просто предупреждение, что реклама не настроена.
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 1.0.1
*
* @param string $position Position for the widget
*
* @return string Возвращает сообщение с последниеми ошибками для отладки
*/
private function get_debug_message( $position ) {
$debug_massage = 'Plugin ads not configured or server unavailable. See full error report below.<br>';
if ( isset( $this->errors[ $position ] ) && ! empty( $this->errors ) ) {
$debug_massage .= '<b>Last errors:</b><br>';
foreach ( $this->errors[ $position ] as $error_code => $error_message ) {
$debug_massage .= 'Code: ' . $error_code . ' Error: ' . $error_message . '<br>';
}
}
return $debug_massage;
}
/**
* Get advert content for selected position.
*
* @since 1.0.1 Полностью переписан
* @since 1.0.0 Added
*
* @param string $position The position for advert
*
* @return string
*/
private function get_content( $position ) {
if ( isset( $this->placements[ $position ] ) ) {
return $this->placements[ $position ];
}
$content = $this->api->get_content( $position );
if ( is_wp_error( $content ) ) {
$this->errors[ $position ][ $content->get_error_code() ] = $content->get_error_message();
return null;
}
$this->placements[ $position ] = $content;
return $content;
}
}

View File

@@ -0,0 +1,125 @@
<?php
namespace WBCR\Factory_Adverts_159;
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Adverts Dashboard Widget.
*
* Adds a widget with a banner or a list of news.
*
* @author Alexander Vitkalov <nechin.va@gmail.com>
* @author Alexander Kovalev <alex.kovalevv@gmail.com>, Github: https://github.com/alexkovalevv
*
* @since 1.0.0 Added
* @package factory-adverts
* @copyright (c) 2019 Webcraftic Ltd
*/
class Dashboard_Widget {
/**
* Контент, который должен быть напечатан внутри дашбоард виджета
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 1.0.1
* @var string
*/
private $content;
/**
* Экзепляр плагина с которым взаимодействует этот модуль
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 1.0.1
* @var \Wbcr_Factory480_Plugin
*/
private $plugin;
/**
* Dashboard_Widget constructor.
*
* Call parent constructor. Registration hooks.
*
* @since 1.0.0 Added
*
* @param \Wbcr_Factory480_Plugin $plugin
* @param string $content
*/
public function __construct( \Wbcr_Factory480_Plugin $plugin, $content ) {
$this->plugin = $plugin;
$this->content = $content;
if ( ! empty( $this->content ) ) {
if ( $this->plugin->isNetworkActive() && $this->plugin->isNetworkAdmin() ) {
add_action( 'wp_network_dashboard_setup', [ $this, 'add_dashboard_widgets' ], 999 );
return;
}
add_action( 'wp_dashboard_setup', [ $this, 'add_dashboard_widgets' ], 999 );
}
}
/**
* Add the News widget to the dashboard.
*
* @since 1.0.0 Added
*/
public function add_dashboard_widgets() {
$widget_id = 'wbcr-factory-adverts-widget';
wp_add_dashboard_widget( $widget_id, $this->plugin->getPluginTitle() . ' News', [
$this,
'print_widget_content'
] );
$this->sort_dashboard_widgets( $widget_id );
}
/**
* Create the function to output the contents of the Dashboard Widget.
*
* @since 1.0.0 Added
*/
public function print_widget_content() {
?>
<div class="wordpress-news hide-if-no-js">
<div class="rss-widget">
<?php echo $this->content; ?>
</div>
</div>
<?php
}
/**
* Сортируем виджеты на странице дашбоард
*
* Виджеты должны быть в таком порядке, чтобы наш виджет был выше всех.
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @author Alexander Vitkalov <nechin.va@gmail.com>
*
* @since 1.0.2 Добавлена поддержка мультисайтов
* @since 1.0.0 Добавлен
*
* @param string $widget_id ID нашего виджета
*/
private function sort_dashboard_widgets( $widget_id ) {
global $wp_meta_boxes;
$location = $this->plugin->isNetworkAdmin() ? 'dashboard-network' : 'dashboard';
$normal_core = $wp_meta_boxes[ $location ]['normal']['core'];
$widget_backup = [ $widget_id => $normal_core[ $widget_id ] ];
unset( $normal_core[ $widget_id ] );
$sorted_core = array_merge( $widget_backup, $normal_core );
$wp_meta_boxes['dashboard']['normal']['core'] = $sorted_core;
}
}

View File

@@ -0,0 +1,217 @@
<?php
namespace WBCR\Factory_Adverts_159;
// Exit if accessed directly
if( !defined('ABSPATH') ) {
exit;
}
/**
* Factory request class.
*
* Performs a server request, retrieves banner data and stores it in the cache.
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>, Github: https://github.com/alexkovalevv
* @author Alexander Vitkalov <nechin.va@gmail.com>
*
* @since 1.0.1 Изменил имя класса и доработал его.
* @since 1.0.0 Added
*
* @package factory-adverts
* @copyright (c) 2019 Webcraftic Ltd
*/
class Creative_Motion_API {
/**
* Rest request url.
*
* Define rest request url for rest request to remote server.
*
* @since 1.2.1
*/
const SERVER_URL = 'https://api.cm-wp.com';
/**
* Rest route path.
*
* Define rest route path for rest request.
*
* @since 1.0.0
*/
const REST_ROUTE = '/adverds/v1/advt';
/**
* Интервал между запросами по умолчанию
*
* Значение в часах.
*
* @since 1.0.1
*/
const DEFAULT_REQUESTS_INTERVAL = 24;
/**
* Интервал между запросами, если сервер недоступен
*
* Значение в часах.
*
* @since 1.0.1
*/
const SERVER_UNAVAILABLE_INTERVAL = 4;
/**
* Экзепляр плагина с которым взаимодействует этот модуль
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 1.0.1
* @var \Wbcr_Factory480_Plugin
*/
private $plugin;
/**
* Request constructor.
*
* Variable initialization.
*
* @param \Wbcr_Factory480_Plugin $plugin_name
* @since 1.0.0 Added
*
*/
public function __construct(\Wbcr_Factory480_Plugin $plugin)
{
$this->plugin = $plugin;
}
/**
* Get adverts content.
*
* @param $position
*
* @return string|\WP_Error
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 1.0.1
*
*/
public function get_content($position)
{
$data = $this->get_cache($position);
if( is_wp_error($data) ) {
return $data;
}
return strip_tags($data['content'], '<b>,<a>,<i>,<strong>,<img>,<ul>,<ol>,<li>');
}
/**
* Get data from cache.
*
* If data in the cache, not empty and not expired, then get data from cache. Or get data from server.
*
* @return mixed array(
* 'plugin' => 'wbcr_insert_php',
* 'content' => '<p></p>',
* 'expires' => 1563542199,
* );
* @since 1.0.1 Полностью переписан, с перехватом api ошибок
* @since 1.0.0 Added
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
*
*/
private function get_cache($position)
{
if( defined('FACTORY_ADVERTS_DEBUG') && FACTORY_ADVERTS_DEBUG ) {
return $this->do_api_request($position);
}
$key = $this->plugin->getPrefix() . md5($position . 'adverts_transient_');
if( 'ru_RU' === get_locale() ) {
$key .= 'ru_';
}
$cached = get_transient($key);
if( $cached !== false ) {
if( isset($cached['error_code']) && isset($cached['error']) ) {
return new \WP_Error($cached['error_code'], $cached['error']);
}
return $cached;
}
$data = $this->do_api_request($position);
if( is_wp_error($data) ) {
set_transient($key, [
'error' => $data->get_error_message(),
'error_code' => $data->get_error_code()
], self::SERVER_UNAVAILABLE_INTERVAL * HOUR_IN_SECONDS);
return $data;
}
set_transient($key, $data, self::DEFAULT_REQUESTS_INTERVAL * HOUR_IN_SECONDS);
return $data;
}
/**
* Performs rest api request.
*
* In some case on the server (Apache) in the .htaccess must be set
* RewriteRule ^wp-json/(.*)[?](.*) /?rest_route=/$1&$2 [L]
*
* @return mixed array(
* 'plugin' => 'wbcr_insert_php',
* 'content' => '<p></p>',
* 'expires' => 1563542199,
* );
* @since 1.0.0 Added
*
* @since 1.0.1 Добавлен перехват ошибок, рефакторинг кода.
*/
private function do_api_request($position)
{
$default_result = [
'content' => '',
'expires' => self::DEFAULT_REQUESTS_INTERVAL * HOUR_IN_SECONDS,
];
$url = untrailingslashit(self::SERVER_URL) . '/wp-json' . self::REST_ROUTE;
$ads_ID = $this->plugin->getPluginName();
if( 'ru_RU' === get_locale() ) {
$ads_ID .= '-ru';
}
$url = add_query_arg([
'plugin' => $ads_ID,
'position' => $position,
'plugin_title' => $this->plugin->getPluginTitle(),
'lang' => get_locale()
], $url);
$response = wp_remote_get($url);
$code = wp_remote_retrieve_response_code($response);
$body = wp_remote_retrieve_body($response);
$data = @json_decode($body, true);
if( is_wp_error($response) ) {
return $response;
}
if( 200 !== $code ) {
return new \WP_Error('http_request_error', 'Failed request to the remote server. Code: ' . $code);
}
return wp_parse_args($data, $default_result);
}
}

View File

@@ -0,0 +1,2 @@
<?php
// Silence is golden.

View File

@@ -0,0 +1,2 @@
<?php
// Silence is golden.

View File

@@ -0,0 +1,83 @@
msgid ""
msgstr ""
"Project-Id-Version: factory_forms\n"
"POT-Creation-Date: 2018-10-16 22:44+0300\n"
"PO-Revision-Date: 2018-10-16 22:45+0300\n"
"Last-Translator: \n"
"Language-Team: Alex Kovalev <alex.kovalevv@gmail.com>\n"
"Language: ru_RU\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 2.1.1\n"
"X-Poedit-Basepath: ..\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c\n"
"X-Poedit-SearchPath-0: .\n"
#: includes/check-compatibility.php:80
msgid "warning"
msgstr "предупреждение"
#: includes/check-compatibility.php:82
#, php-format
msgid "The %s plugin has stopped."
msgstr "Работа плагина %s была остановлена."
#: includes/check-compatibility.php:83
msgid "Possible reasons:"
msgstr "Возможные причины:"
#: includes/check-compatibility.php:89
#, php-format
msgid "You need to update the PHP version to %s or higher!"
msgstr "Вам нужно обновить версию PHP до %s или выше!"
#: includes/check-compatibility.php:94
#, php-format
msgid "You need to update WordPress to %s or higher!"
msgstr "Вам нужно обновить WordPress до %s или выше!"
#: includes/functions.php:132
#, php-format
msgid ""
"%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead."
msgstr ""
"%1$s является <strong>устаревшим,</strong> начиная с версии %2$s в "
"Wordpress! Используйте %3$s."
#: includes/functions.php:134
#, php-format
msgid ""
"%1$s is <strong>deprecated</strong> since version %2$s with no alternative "
"available."
msgstr ""
"%1$s был вызван с параметром, который является <strong>устаревшими</strong> "
"начиная с версии %2$s , в настоящее время доступных альтернатив нет."
#: includes/plugin.class.php:202 includes/plugin.class.php:237
msgid ""
"You are trying to call this earlier than the plugin menu will be registered."
msgstr ""
"Вы пытаетесь вызвать это раньше, чем будет зарегистрировано меню плагина."
#: includes/plugin.class.php:220
msgid ""
"You are trying to get a link to a page that does not have multisite mode. "
"Clicking this link will lead the user to a non-existent page."
msgstr ""
"Вы пытаетесь получить ссылку на страницу, которая не имеет "
"многопользовательского режима. Щелчок по этой ссылке приведет пользователя "
"к несуществующей странице."
#: includes/plugin.class.php:222
msgid ""
"Trying to get a link to an unregistered page. You are trying to call this "
"earlier than the plugin menu will be registered."
msgstr ""
"Попытка получить ссылку на незарегистрированную страницу. Вы пытаетесь "
"вызвать это раньше, чем будет зарегистрировано меню плагина."

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,11 @@
/*!
* Bootstrap generator - v1.0.1, 2021-11-19
* Webcraftic factory build
*
* Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
* Site: http://webcraftic.com
* Support: http://webcraftic.com/contact-us/
*/
.factory-bootstrap-482 .factory-accordion{margin:0 0 30px;border-top:1px solid #DDD;border-right:1px solid #DDD;border-left:1px solid #DDD;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.factory-bootstrap-482 .factory-accordion>h3{border-bottom:1px solid #DDD;cursor:pointer;padding:8px 15px;margin:0}.factory-bootstrap-482 .factory-accordion>div{display:none;margin:0;border-bottom:1px solid #DDD}.factory-bootstrap-482 .factory-accordion-item{display:none}.factory-bootstrap-482 .inner-factory-accordion-item{padding:10px 0}.factory-bootstrap-482 .factory-accordion>h3.active:hover{cursor:default}

View File

@@ -0,0 +1,11 @@
/*!
* Bootstrap generator - v1.0.1, 2021-11-19
* Webcraftic factory build
*
* Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
* Site: http://webcraftic.com
* Support: http://webcraftic.com/contact-us/
*/
.factory-bootstrap-482 .btn-primary{background:#e1a948;border-color:#d39323;color:#fff;-webkit-box-shadow:inset 0 1px 0 #ecc88a,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #ecc88a,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-482 .btn-primary:focus,.factory-bootstrap-482 .btn-primary:hover{background:#db9825;border-color:#bd831f;color:#fff;-webkit-box-shadow:inset 0 1px 0 #e8be74,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #e8be74,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-482 .btn-primary:active{background:#db9825;border-color:#bd831f;color:#fff;-webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5);box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5)}.factory-bootstrap-482 .btn-primary:disabled,.factory-bootstrap-482 .btn-primary[disabled]{color:#d1cdc7!important;background:#db9825!important;border-color:#bd831f!important;text-shadow:none!important}.factory-bootstrap-482 .btn-group .btn.active.value{background-color:#e1a948;-webkit-box-shadow:inset 0 1px 2px #d39323;box-shadow:inset 0 1px 2px #d39323;border-top:1px solid #d39323;border-bottom:1px solid #d39323;border-left:1px solid #d39323}.factory-bootstrap-482 .pagination>.active>a,.factory-bootstrap-482 .pagination>.active>a:focus,.factory-bootstrap-482 .pagination>.active>a:hover,.factory-bootstrap-482 .pagination>.active>span,.factory-bootstrap-482 .pagination>.active>span:focus,.factory-bootstrap-482 .pagination>.active>span:hover{background-color:#e1a948;border-color:#d39323}

View File

@@ -0,0 +1,11 @@
/*!
* Bootstrap generator - v1.0.1, 2021-11-19
* Webcraftic factory build
*
* Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
* Site: http://webcraftic.com
* Support: http://webcraftic.com/contact-us/
*/
.factory-bootstrap-482 .btn-primary{background:#c7a589;border-color:#b78a66;color:#fff;-webkit-box-shadow:inset 0 1px 0 #e0cdbd,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #e0cdbd,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-482 .btn-primary:focus,.factory-bootstrap-482 .btn-primary:hover{background:#ba906d;border-color:#ae7d55;color:#fff;-webkit-box-shadow:inset 0 1px 0 #d7bfac,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #d7bfac,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-482 .btn-primary:active{background:#ba906d;border-color:#ae7d55;color:#fff;-webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5);box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5)}.factory-bootstrap-482 .btn-primary:disabled,.factory-bootstrap-482 .btn-primary[disabled]{color:#d1cbc7!important;background:#ba906d!important;border-color:#ae7d55!important;text-shadow:none!important}.factory-bootstrap-482 .btn-group .btn.active.value{background-color:#c7a589;-webkit-box-shadow:inset 0 1px 2px #b78a66;box-shadow:inset 0 1px 2px #b78a66;border-top:1px solid #b78a66;border-bottom:1px solid #b78a66;border-left:1px solid #b78a66}.factory-bootstrap-482 .pagination>.active>a,.factory-bootstrap-482 .pagination>.active>a:focus,.factory-bootstrap-482 .pagination>.active>a:hover,.factory-bootstrap-482 .pagination>.active>span,.factory-bootstrap-482 .pagination>.active>span:focus,.factory-bootstrap-482 .pagination>.active>span:hover{background-color:#c7a589;border-color:#b78a66}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,11 @@
/*!
* Bootstrap generator - v1.0.1, 2021-11-19
* Webcraftic factory build
*
* Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
* Site: http://webcraftic.com
* Support: http://webcraftic.com/contact-us/
*/
.factory-bootstrap-482 .btn-primary{background:#a3b745;border-color:#839237;color:#fff;-webkit-box-shadow:inset 0 1px 0 #c0cd7b,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #c0cd7b,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-482 .btn-primary:focus,.factory-bootstrap-482 .btn-primary:hover{background:#89993a;border-color:#727f30;color:#fff;-webkit-box-shadow:inset 0 1px 0 #b7c669,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #b7c669,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-482 .btn-primary:active{background:#89993a;border-color:#727f30;color:#fff;-webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5);box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5)}.factory-bootstrap-482 .btn-primary:disabled,.factory-bootstrap-482 .btn-primary[disabled]{color:#cfd1c7!important;background:#89993a!important;border-color:#727f30!important;text-shadow:none!important}.factory-bootstrap-482 .btn-group .btn.active.value{background-color:#a3b745;-webkit-box-shadow:inset 0 1px 2px #839237;box-shadow:inset 0 1px 2px #839237;border-top:1px solid #839237;border-bottom:1px solid #839237;border-left:1px solid #839237}.factory-bootstrap-482 .pagination>.active>a,.factory-bootstrap-482 .pagination>.active>a:focus,.factory-bootstrap-482 .pagination>.active>a:hover,.factory-bootstrap-482 .pagination>.active>span,.factory-bootstrap-482 .pagination>.active>span:focus,.factory-bootstrap-482 .pagination>.active>span:hover{background-color:#a3b745;border-color:#839237}

View File

@@ -0,0 +1,11 @@
/*!
* Bootstrap generator - v1.0.1, 2021-11-19
* Webcraftic factory build
*
* Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
* Site: http://webcraftic.com
* Support: http://webcraftic.com/contact-us/
*/
.factory-bootstrap-482 .factory-form-group .factory-legend{padding:9px 12px;background-color:#f9f9f9}.factory-bootstrap-482 .factory-form-group .factory-title{font-weight:700;font-size:14px;line-height:14px;color:#555;margin:0}.factory-bootstrap-482 .factory-form-group .factory-hint-icon{display:block;width:16px;height:16px;line-height:13px;padding:0;font-size:11px;text-align:center;position:absolute;top:-5px;right:-3px;color:#fff;background:#E91E63;border-radius:3px}.factory-bootstrap-482 .factory-form-group .factory-hint-icon.factory-hint-icon-green{background:#8bc34a}.factory-bootstrap-482 .factory-form-group .factory-hint-icon.factory-hint-icon-grey{background:#9e9e9e}.factory-bootstrap-482 .factory-form-group .factory-hint-icon.factory-hint-icon-red{background:#E91E63}.factory-bootstrap-482 .factory-form-group .factory-hint{margin:0;font-size:12px;line-height:16px;margin-top:6px}.factory-bootstrap-482 .factory-form-group+.factory-form-group{margin-top:30px}.factory-bootstrap-482 .factory-form-group legend+.control-group{margin-top:0}

View File

@@ -0,0 +1,11 @@
/*!
* Bootstrap generator - v1.0.1, 2021-11-19
* Webcraftic factory build
*
* Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
* Site: http://webcraftic.com
* Support: http://webcraftic.com/contact-us/
*/
.factory-bootstrap-482 .btn-primary{background:#04a4cc;border-color:#037c9a;color:#fff;-webkit-box-shadow:inset 0 1px 0 #22cffb,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #22cffb,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-482 .btn-primary:focus,.factory-bootstrap-482 .btn-primary:hover{background:#0384a4;border-color:#036881;color:#fff;-webkit-box-shadow:inset 0 1px 0 #09cafa,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #09cafa,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-482 .btn-primary:active{background:#0384a4;border-color:#036881;color:#fff;-webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5);box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5)}.factory-bootstrap-482 .btn-primary:disabled,.factory-bootstrap-482 .btn-primary[disabled]{color:#c7cfd1!important;background:#0384a4!important;border-color:#036881!important;text-shadow:none!important}.factory-bootstrap-482 .btn-group .btn.active.value{background-color:#04a4cc;-webkit-box-shadow:inset 0 1px 2px #037c9a;box-shadow:inset 0 1px 2px #037c9a;border-top:1px solid #037c9a;border-bottom:1px solid #037c9a;border-left:1px solid #037c9a}.factory-bootstrap-482 .pagination>.active>a,.factory-bootstrap-482 .pagination>.active>a:focus,.factory-bootstrap-482 .pagination>.active>a:hover,.factory-bootstrap-482 .pagination>.active>span,.factory-bootstrap-482 .pagination>.active>span:focus,.factory-bootstrap-482 .pagination>.active>span:hover{background-color:#04a4cc;border-color:#037c9a}

View File

@@ -0,0 +1,11 @@
/*!
* Bootstrap generator - v1.0.1, 2021-11-19
* Webcraftic factory build
*
* Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
* Site: http://webcraftic.com
* Support: http://webcraftic.com/contact-us/
*/
.factory-bootstrap-482 .btn-primary{background:#e14d43;border-color:#d02a21;color:#fff;-webkit-box-shadow:inset 0 1px 0 #ec8a85,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #ec8a85,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-482 .btn-primary:focus,.factory-bootstrap-482 .btn-primary:hover{background:#d92c23;border-color:#ba251e;color:#fff;-webkit-box-shadow:inset 0 1px 0 #e8756f,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #e8756f,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-482 .btn-primary:active{background:#d92c23;border-color:#ba251e;color:#fff;-webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5);box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5)}.factory-bootstrap-482 .btn-primary:disabled,.factory-bootstrap-482 .btn-primary[disabled]{color:#d1c7c7!important;background:#d92c23!important;border-color:#ba251e!important;text-shadow:none!important}.factory-bootstrap-482 .btn-group .btn.active.value{background-color:#e14d43;-webkit-box-shadow:inset 0 1px 2px #d02a21;box-shadow:inset 0 1px 2px #d02a21;border-top:1px solid #d02a21;border-bottom:1px solid #d02a21;border-left:1px solid #d02a21}.factory-bootstrap-482 .pagination>.active>a,.factory-bootstrap-482 .pagination>.active>a:focus,.factory-bootstrap-482 .pagination>.active>a:hover,.factory-bootstrap-482 .pagination>.active>span,.factory-bootstrap-482 .pagination>.active>span:focus,.factory-bootstrap-482 .pagination>.active>span:hover{background-color:#e14d43;border-color:#d02a21}

View File

@@ -0,0 +1,11 @@
/*!
* Bootstrap generator - v1.0.1, 2021-11-19
* Webcraftic factory build
*
* Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
* Site: http://webcraftic.com
* Support: http://webcraftic.com/contact-us/
*/
.factory-bootstrap-482 .btn-primary{background:#9ebaa0;border-color:#80a583;color:#fff;-webkit-box-shadow:inset 0 1px 0 #cbdacc,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #cbdacc,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-482 .btn-primary:focus,.factory-bootstrap-482 .btn-primary:hover{background:#86a988;border-color:#719a74;color:#fff;-webkit-box-shadow:inset 0 1px 0 #bccfbd,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #bccfbd,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-482 .btn-primary:active{background:#86a988;border-color:#719a74;color:#fff;-webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5);box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5)}.factory-bootstrap-482 .btn-primary:disabled,.factory-bootstrap-482 .btn-primary[disabled]{color:#c7d1c8!important;background:#86a988!important;border-color:#719a74!important;text-shadow:none!important}.factory-bootstrap-482 .btn-group .btn.active.value{background-color:#9ebaa0;-webkit-box-shadow:inset 0 1px 2px #80a583;box-shadow:inset 0 1px 2px #80a583;border-top:1px solid #80a583;border-bottom:1px solid #80a583;border-left:1px solid #80a583}.factory-bootstrap-482 .pagination>.active>a,.factory-bootstrap-482 .pagination>.active>a:focus,.factory-bootstrap-482 .pagination>.active>a:hover,.factory-bootstrap-482 .pagination>.active>span,.factory-bootstrap-482 .pagination>.active>span:focus,.factory-bootstrap-482 .pagination>.active>span:hover{background-color:#9ebaa0;border-color:#80a583}

View File

@@ -0,0 +1,11 @@
/*!
* Bootstrap generator - v1.0.1, 2021-11-19
* Webcraftic factory build
*
* Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
* Site: http://webcraftic.com
* Support: http://webcraftic.com/contact-us/
*/
.factory-bootstrap-482 .factory-separator{border-bottom:1px solid #f9f9f9;border-top:1px solid #d1d1d1;margin-bottom:25px}

View File

@@ -0,0 +1,11 @@
/*!
* Bootstrap generator - v1.0.1, 2021-11-19
* Webcraftic factory build
*
* Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
* Site: http://webcraftic.com
* Support: http://webcraftic.com/contact-us/
*/
.factory-bootstrap-482 .btn-primary{background:#dd823b;border-color:#c36822;color:#fff;-webkit-box-shadow:inset 0 1px 0 #e8ab7c,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #e8ab7c,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-482 .btn-primary:focus,.factory-bootstrap-482 .btn-primary:hover{background:#cc6c23;border-color:#ad5c1e;color:#fff;-webkit-box-shadow:inset 0 1px 0 #e59d66,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #e59d66,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-482 .btn-primary:active{background:#cc6c23;border-color:#ad5c1e;color:#fff;-webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5);box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5)}.factory-bootstrap-482 .btn-primary:disabled,.factory-bootstrap-482 .btn-primary[disabled]{color:#d1cbc7!important;background:#cc6c23!important;border-color:#ad5c1e!important;text-shadow:none!important}.factory-bootstrap-482 .btn-group .btn.active.value{background-color:#dd823b;-webkit-box-shadow:inset 0 1px 2px #c36822;box-shadow:inset 0 1px 2px #c36822;border-top:1px solid #c36822;border-bottom:1px solid #c36822;border-left:1px solid #c36822}.factory-bootstrap-482 .pagination>.active>a,.factory-bootstrap-482 .pagination>.active>a:focus,.factory-bootstrap-482 .pagination>.active>a:hover,.factory-bootstrap-482 .pagination>.active>span,.factory-bootstrap-482 .pagination>.active>span:focus,.factory-bootstrap-482 .pagination>.active>span:hover{background-color:#dd823b;border-color:#c36822}

View File

@@ -0,0 +1,11 @@
/*!
* Bootstrap generator - v1.0.1, 2021-11-19
* Webcraftic factory build
*
* Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
* Site: http://webcraftic.com
* Support: http://webcraftic.com/contact-us/
*/
#side-sortables .factory-bootstrap-482 .factory-buttons-way{float:right;position:relative;top:-25px;left:5px;border:3px solid #f9f9f9;border-radius:4px}.factory-bootstrap-482 .factory-checkbox-disabled button,.factory-bootstrap-482 .factory-checkbox-disabled input{pointer-events:none;cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.factory-bootstrap-482 .factory-buttons-way{border:3px solid #f9f9f9;border-radius:4px}.factory-bootstrap-482 .factory-buttons-way button{padding-left:10px;padding-right:10px}.factory-bootstrap-482 .factory-buttons-way .factory-on.active{text-shadow:none;color:#fff;background-color:#33aad5;-webkit-box-shadow:inset 0 1px 1px #0074a2;box-shadow:inset 0 1px 3px #0074a2;border-top:1px solid #0074a2;border-bottom:1px solid #0074a2;border-left:1px solid #0074a2}.factory-bootstrap-482 .factory-checkbox-tumbler-hint{margin-top:5px}.factory-bootstrap-482 .factory-checkbox-tumbler-hint .factory-tumbler-content{display:inline-block;background-color:#ffd;padding:1px 5px}.admin-color-light .factory-bootstrap-482 .factory-buttons-way .factory-on.active{background-color:#04a4cc;-webkit-box-shadow:inset 0 1px 2px #037c9a;box-shadow:inset 0 1px 2px #037c9a;border-top:1px solid #037c9a;border-bottom:1px solid #037c9a;border-left:1px solid #037c9a}.admin-color-blue .factory-bootstrap-482 .factory-buttons-way .factory-on.active{background-color:#e1a948;-webkit-box-shadow:inset 0 1px 2px #d39323;box-shadow:inset 0 1px 2px #d39323;border-top:1px solid #d39323;border-bottom:1px solid #d39323;border-left:1px solid #d39323}.admin-color-coffee .factory-bootstrap-482 .factory-buttons-way .factory-on.active{background-color:#c7a589;-webkit-box-shadow:inset 0 1px 2px #b78a66;box-shadow:inset 0 1px 2px #b78a66;border-top:1px solid #b78a66;border-bottom:1px solid #b78a66;border-left:1px solid #b78a66}.admin-color-ectoplasm .factory-bootstrap-482 .factory-buttons-way .factory-on.active{background-color:#a3b745;-webkit-box-shadow:inset 0 1px 2px #839237;box-shadow:inset 0 1px 2px #839237;border-top:1px solid #839237;border-bottom:1px solid #839237;border-left:1px solid #839237}.admin-color-midnight .factory-bootstrap-482 .factory-buttons-way .factory-on.active{background-color:#e14d43;-webkit-box-shadow:inset 0 1px 2px #d02a21;box-shadow:inset 0 1px 2px #d02a21;border-top:1px solid #d02a21;border-bottom:1px solid #d02a21;border-left:1px solid #d02a21}.admin-color-ocean .factory-bootstrap-482 .factory-buttons-way .factory-on.active{background-color:#9ebaa0;-webkit-box-shadow:inset 0 1px 2px #80a583;box-shadow:inset 0 1px 2px #80a583;border-top:1px solid #80a583;border-bottom:1px solid #80a583;border-left:1px solid #80a583}.admin-color-sunrise .factory-bootstrap-482 .factory-buttons-way .factory-on.active{background-color:#dd823b;-webkit-box-shadow:inset 0 1px 2px #c36822;box-shadow:inset 0 1px 2px #c36822;border-top:1px solid #c36822;border-bottom:1px solid #c36822;border-left:1px solid #c36822}

View File

@@ -0,0 +1,11 @@
/*!
* Bootstrap generator - v1.0.1, 2021-11-19
* Webcraftic factory build
*
* Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
* Site: http://webcraftic.com
* Support: http://webcraftic.com/contact-us/
*/
.factory-bootstrap-482 .factory-color{position:relative}.factory-bootstrap-482 .factory-color .factory-color-hex{display:inline-block;width:65px;text-align:left;vertical-align:top;border-top-right-radius:3px;border-bottom-right-radius:3px;border-radius:3px;z-index:1;position:relative;margin-left:26px;border-top-left-radius:0;border-bottom-left-radius:0}.factory-bootstrap-482 .factory-color .factory-background,.factory-bootstrap-482 .factory-color .factory-pattern{cursor:pointer;height:26px;width:26px;position:absolute;border-radius:5px;background:transparent url(../../assets/images/color_picker_pattern.jpg) center center repeat;-moz-box-sizing:border-box;box-sizing:border-box;border-bottom:2px solid rgba(0,0,0,.34);z-index:1;border-top-right-radius:0!important;border-bottom-right-radius:0!important}.factory-bootstrap-482 .factory-color .factory-background{z-index:2;border-radius:3px}

View File

@@ -0,0 +1,11 @@
/*!
* Bootstrap generator - v1.0.1, 2021-11-19
* Webcraftic factory build
*
* Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
* Site: http://webcraftic.com
* Support: http://webcraftic.com/contact-us/
*/
.factory-bootstrap-482 .factory-dropdown.factory-buttons-way .fa{margin-right:6px;position:relative}.factory-bootstrap-482 .factory-dropdown.factory-buttons-way{border:0;border-radius:0}.factory-bootstrap-482 .factory-hints .factory-hint{margin-top:5px;display:inline-block;background-color:#ffd;padding:1px 5px}.admin-color-light .factory-bootstrap-482 .factory-dropdown.factory-buttons-way .active{background-color:#04a4cc;-webkit-box-shadow:inset 0 1px 2px #037c9a;box-shadow:inset 0 1px 2px #037c9a;border-top:1px solid #037c9a;border-bottom:1px solid #037c9a;border-left:1px solid #037c9a}.admin-color-blue .factory-bootstrap-482 .factory-dropdown.factory-buttons-way .active{background-color:#e1a948;-webkit-box-shadow:inset 0 1px 2px #d39323;box-shadow:inset 0 1px 2px #d39323;border-top:1px solid #d39323;border-bottom:1px solid #d39323;border-left:1px solid #d39323}.admin-color-coffee .factory-bootstrap-482 .factory-dropdown.factory-buttons-way .active{background-color:#c7a589;-webkit-box-shadow:inset 0 1px 2px #b78a66;box-shadow:inset 0 1px 2px #b78a66;border-top:1px solid #b78a66;border-bottom:1px solid #b78a66;border-left:1px solid #b78a66}.admin-color-ectoplasm .factory-bootstrap-482 .factory-dropdown.factory-buttons-way .active{background-color:#a3b745;-webkit-box-shadow:inset 0 1px 2px #839237;box-shadow:inset 0 1px 2px #839237;border-top:1px solid #839237;border-bottom:1px solid #839237;border-left:1px solid #839237}.admin-color-midnight .factory-bootstrap-482 .factory-dropdown.factory-buttons-way .active{background-color:#e14d43;-webkit-box-shadow:inset 0 1px 2px #d02a21;box-shadow:inset 0 1px 2px #d02a21;border-top:1px solid #d02a21;border-bottom:1px solid #d02a21;border-left:1px solid #d02a21}.admin-color-ocean .factory-bootstrap-482 .factory-dropdown.factory-buttons-way .active{background-color:#9ebaa0;-webkit-box-shadow:inset 0 1px 2px #80a583;box-shadow:inset 0 1px 2px #80a583;border-top:1px solid #80a583;border-bottom:1px solid #80a583;border-left:1px solid #80a583}.admin-color-sunrise .factory-bootstrap-482 .factory-dropdown.factory-buttons-way .active{background-color:#dd823b;-webkit-box-shadow:inset 0 1px 2px #c36822;box-shadow:inset 0 1px 2px #c36822;border-top:1px solid #c36822;border-bottom:1px solid #c36822;border-left:1px solid #c36822}.factory-bootstrap-482 .factory-dropdown.factory-ddslick-way .dd-select{background-color:#fff!important}.factory-bootstrap-482 .factory-dropdown.factory-ddslick-way label{margin-bottom:1px}.factory-bootstrap-482 .factory-dropdown.factory-ddslick-way .dd-option,.factory-bootstrap-482 .factory-dropdown.factory-ddslick-way .dd-selected{padding:8px 12px 8px 11px!important}

View File

@@ -0,0 +1,11 @@
/*!
* Bootstrap generator - v1.0.1, 2021-11-19
* Webcraftic factory build
*
* Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
* Site: http://webcraftic.com
* Support: http://webcraftic.com/contact-us/
*/
.factory-bootstrap-482 .factory-mtextbox-item{position:relative;margin-bottom:5px}.factory-bootstrap-482 .factory-mtextbox-item input,.factory-mtextbox-remove-item{display:inline-block}.factory-bootstrap-482 .factory-mtextbox-item .factory-mtextbox-remove-item{position:absolute;top:0;right:0;bottom:0;width:40px;border-radius:0 3px 3px 0;outline:0}.factory-bootstrap-482 .factory-mtextbox-item .factory-mtextbox-remove-item:focus,.factory-bootstrap-482 .factory-mtextbox-item .factory-mtextbox-remove-item:hover{box-shadow:none;outline:0}.factory-bootstrap-482 .factory-mtextbox-add-item{display:block;margin-top:10px}

View File

@@ -0,0 +1,11 @@
/*!
* Bootstrap generator - v1.0.1, 2021-11-19
* Webcraftic factory build
*
* Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
* Site: http://webcraftic.com
* Support: http://webcraftic.com/contact-us/
*/
.factory-bootstrap-482 .factory-more-link-content{border-top:1px dashed #DDD;padding-top:25px;width:100%;padding-right:20px;position:relative}.factory-bootstrap-482 .factory-tab .factory-more-link-show{display:inline-block;text-decoration:none;border-bottom:1px dotted #21759b;position:relative}.factory-bootstrap-482 .factory-tab .factory-more-link-show:hover{border-color:#d54e21}.factory-bootstrap-482 .factory-tab .factory-more-link-hide{position:absolute;margin-top:-35px;background-color:#fff;padding:0 5px;right:20px;color:#bbb;text-decoration:none}.factory-bootstrap-482 .factory-tab .factory-more-link-hide:hover{color:#999}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@@ -0,0 +1,10 @@
/*!
* Bootstrap generator - v1.0.1, 2021-11-19
* Webcraftic factory build
*
* Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
* Site: http://webcraftic.com
* Support: http://webcraftic.com/contact-us/
*/
+function(a){"use strict";function b(){a(d).remove(),a(e).each(function(b){var d=c(a(this));d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown")),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown"))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=factory-dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){if("ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('<div class="dropdown-backdrop"/>').insertAfter(a(this)).on("click",b),f.trigger(d=a.Event("show.bs.dropdown")),d.isDefaultPrevented())return;f.toggleClass("open").trigger("shown.bs.dropdown"),e.focus()}return!1}},f.prototype.keydown=function(b){if(/(38|40|27)/.test(b.keyCode)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var f=c(d),g=f.hasClass("open");if(!g||g&&27==b.keyCode)return 27==b.which&&f.find(e).focus(),d.click();var h=a("[role=menu] li:not(.divider):visible a",f);if(h.length){var i=h.index(h.filter(":focus"));38==b.keyCode&&i>0&&i--,40==b.keyCode&&i<h.length-1&&i++,~i||(i=0),h.eq(i).focus()}}}},a.fn.factoryBootstrap482_dropdown=function(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new f(this)),"string"==typeof b&&d[b].call(c)})},a.fn.factoryBootstrap482_dropdown.Constructor=f,a(document).on("click.bs.dropdown.data-api",b).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",e,f.prototype.toggle).on("keydown.bs.dropdown.data-api",e+", [role=menu]",f.prototype.keydown)}(jQuery);

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,10 @@
/*!
* Bootstrap generator - v1.0.1, 2021-11-19
* Webcraftic factory build
*
* Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
* Site: http://webcraftic.com
* Support: http://webcraftic.com/contact-us/
*/
!function(a){var b=function(b){var c=this;this.$element=a(b),this.$result=this.$element.find(".factory-result"),this.$on=this.$element.find(".factory-on"),this.$off=this.$element.find(".factory-off");var d=this.$element.is(".factory-tumbler"),e=this.$element.is(".factory-has-tumbler-hint"),f=this.$element.data("tumbler-function"),g=this.$element.data("tumbler-delay");g||(g=3e3),this.callByPath=function(a,b){for(var c=a.split("."),d=window,e=0;e<c.length;e++)d=d[c[e]];d.apply(d,b)},this.$on.click(function(){return c.$off.removeClass("active"),c.$on.addClass("active"),d?setTimeout(function(){c.$on.removeClass("active"),c.$off.addClass("active");var a=e?c.$element.next():null;f?c.callByPath(f,[c.$element,a]):e&&(c.$element.next().fadeIn(300),setTimeout(function(){c.$element.next().fadeOut(500)},g))},300):(c.$result.prop("checked",!0),c.$result.val(1),c.$result.trigger("change")),!1}),this.$off.click(function(){return c.$on.removeClass("active"),c.$off.addClass("active"),d?setTimeout(function(){c.$off.removeClass("active"),c.$on.addClass("active");var a=e?c.$element.next():null;f?c.callByPath(f,[c.$element,a]):e&&(c.$element.next().fadeIn(300),setTimeout(function(){c.$element.next().fadeOut(500)},g))},300):(c.$result.prop("checked",!1),c.$result.val(0),c.$result.trigger("change")),!1}),this.hashCode=function(a){var b=0;if(!a||0===a.length)return b;for(var c=0;c<a.length;c++){var d=a.charCodeAt(c);b=(b<<5)-b+d,b&=b}return b=b.toString(16),b=b.replace("-","")},this.executeEvents=function(a){(void 0!==window.__factory_checkbox_control_events_off_data||void 0!==window.__factory_checkbox_control_events_on_data)&&(a.change(function(){c.eventsProcess(a)}),c.eventsProcess(a))},this.eventsProcess=function(b){var d=b.attr("name"),e=b.prop("checked"),f=window.__factory_checkbox_control_events_on_data[d],g=window.__factory_checkbox_control_events_off_data[d];if(f||g){var h,i;void 0===window.__factory_checkbox_control_detach_elements&&(window.__factory_checkbox_control_detach_elements={}),h=window.__factory_checkbox_control_detach_elements,i=e?f:g;for(var j in i)if(i.hasOwnProperty(j)){var k,l=i[j];a.isArray(l)||(k=c.hashCode(d+l));var m;switch(j){case"hide":"string"==typeof l&&a(l).hide(0);break;case"show":"string"==typeof l&&a(l).fadeIn(200);break;case"detach":"string"==typeof l&&a(l).each(function(b){h[k]||(h[k]={}),h[k][b]||(h[k][b]={}),h[k][b].recovery_contanier=a(this).parent(),h[k][b].element=a(this).clone(!0),a(this).remove()});break;case"recovery":if(h[k]){for(var n in h[k])h[k].hasOwnProperty(n)&&h[k][n].recovery_contanier&&h[k][n].element&&h[k][n].recovery_contanier.append(h[k][n].element);delete h[k]}break;case"removeClasses":if("object"==typeof l)for(m in l)l.hasOwnProperty(m)&&l[m]&&a(m).removeClass(l[m]);break;case"addClasses":if("object"==typeof l)for(m in l)l.hasOwnProperty(m)&&l[m]&&a(m).addClass(l[m]);break;case"setValue":if("object"==typeof l)for(m in l)l.hasOwnProperty(m)&&void 0!==l[m]&&null!==l[m]&&a(m).val(l[m])}}}},this.executeEvents(this.$result)};a.fn.factoryBootstrap482_checkboxControl=function(c){if("string"==typeof c){var d=a(this).data("factory.checkbox.control");return d?d[c]():null}return this.each(function(){var c=a(this),d=c.data("factory.checkbox.control");d||c.data("factory.checkbox.control",d=new b(this))})},a.fn.factoryBootstrap482_checkboxControl.Constructor=b,a(function(){a(".factory-bootstrap-482 .factory-checkbox.factory-buttons-way").factoryBootstrap482_checkboxControl(),a(".factory-bootstrap-482 .factory-checkbox").not(".factory-buttons-way").click(function(){a(this).prop("checked")?a(this).val(1):a(this).val(0)})})}(jQuery);

View File

@@ -0,0 +1,10 @@
/*!
* Bootstrap generator - v1.0.1, 2021-11-19
* Webcraftic factory build
*
* Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
* Site: http://webcraftic.com
* Support: http://webcraftic.com/contact-us/
*/
!function(a){a.widget("factoryBootstrap482.colorControl",{_create:function(){this.$element=this.element,this.$picker=this.$element.find(".factory-color-hex"),this.$preview=this.$element.find(".factory-preview"),this.$background=this.$element.find(".factory-background"),this._init()},_init:function(b){var c=this,d={width:216,palettes:["#16a086","#27ae61","#2a80b9","#8f44ad","#2d3e50","#f49c14","#c1392b","#bec3c7"],hide:!0,change:function(a,b){c.$background.css({background:b.color.toString()}),c.$element.trigger("change.color.factory",[b.color.toString()]),c.$element.trigger("updated.color.factory",[b.color.toString()])}},e=this.$element.data("picker-target");e&&(d.target=a(e)),this.$picker.factoryBootstrap482_iris(d),this.$picker.off("focus"),a(document).on("click.color.factory",function(){c.$picker.factoryBootstrap482_iris("hide")}),this.$picker.add(this.$background).on("click.color.factory",function(a){a.stopPropagation(),c.$picker.factoryBootstrap482_iris("show")})},togglePicker:function(){this.$element.hasClass("factory-picker-active")?this.hidePicker():this.showPicker()},hidePicker:function(){this.$element.removeClass("factory-picker-active"),this.$picker.factoryBootstrap482_iris("hide")},showPicker:function(){this.$element.addClass("factory-picker-active"),this.$picker.factoryBootstrap482_iris("show")},getValue:function(){return this.$picker.val()},setValue:function(a,b){this.$picker.val(a),b&&self.$picker.trigger("change")}}),a(function(){a.widget.bridge("factoryBootstrap482_colorControl",a.factoryBootstrap482.colorControl),a(".factory-bootstrap-482 .factory-color").factoryBootstrap482_colorControl({})})}(jQuery);

View File

@@ -0,0 +1,10 @@
/*!
* Bootstrap generator - v1.0.1, 2021-11-19
* Webcraftic factory build
*
* Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
* Site: http://webcraftic.com
* Support: http://webcraftic.com/contact-us/
*/
!function(a){var b=function(b){var c=this;if(this.$element=a(b),this.way=this.$element.data("way"),this.name=this.$element.data("name")||this.$element.attr("name"),this.hashCode=function(a){var b=0;if(!a||0===a.length)return b;for(var c=0;c<a.length;c++){var d=a.charCodeAt(c);b=(b<<5)-b+d,b&=b}return b=b.toString(16),b=b.replace("-","")},this.executeEvents=function(a){void 0!==window.factory_dropdown_control_events_data&&(a.change(function(){c.eventsProcess(a)}),c.eventsProcess(a))},this.eventsProcess=function(b){var d=b.attr("name"),e=b.val(),f=window.factory_dropdown_control_events_data[d];if(f&&f[e]){var g;void 0===window.__factory_dropdown_control_detach_elements&&(window.__factory_dropdown_control_detach_elements={}),g=window.__factory_dropdown_control_detach_elements;for(var h in f[e])if(f[e].hasOwnProperty(h)){var i,j=f[e][h];switch(a.isArray(j)||(i=c.hashCode(d+j)),h){case"hide":"string"==typeof j&&a(j).hide(0);break;case"show":"string"==typeof j&&a(j).fadeIn(200);break;case"detach":"string"==typeof j&&a(j).each(function(b){g[i]||(g[i]={}),g[i][b]||(g[i][b]={}),g[i][b].recovery_contanier=a(this).parent(),g[i][b].element=a(this).clone(!0),a(this).remove()});break;case"recovery":if(g[i]){for(var k in g[i])g[i].hasOwnProperty(k)&&g[i][k].recovery_contanier&&g[i][k].element&&g[i][k].recovery_contanier.append(g[i][k].element);delete g[i]}break;case"removeClasses":if("object"==typeof j)for(var l in j)j.hasOwnProperty(l)&&j[l]&&a(l).removeClass(j[l]);break;case"addClasses":if("object"==typeof j)for(var l in j)j.hasOwnProperty(l)&&j[l]&&a(l).addClass(j[l])}}}},"buttons"===this.way)this.$result=this.$element.find(".factory-result"),this.$hints=this.$element.find(".factory-hints"),this.$buttons=this.$element.find(".btn"),c.executeEvents(this.$result),this.$buttons.click(function(){var b=a(this).data("value");return c.$buttons.removeClass("active"),a(this).addClass("active"),c.$hints.find(".factory-hint").hide(),c.$hints.find(".factory-hint-"+b).fadeIn(),c.$result.val(b),c.$result.trigger("change"),!1});else if("ddslick"===this.way){c.executeEvents(c.$element.find(".factory-result"));var d=window["factory_"+this.name+"_data"],e=this.$element.find(".factory-ddslick"),f=this.$element.data("width")||300,g=this.$element.data("align")||"right";a(d).each(function(){return this.imageHoverSrc?void(a("<img/>")[0].src=this.imageHoverSrc):!0}),e.ddslick({data:d,width:f,imagePosition:g,selectText:"- select -",onSelected:function(a){a.selectedData.imageHoverSrc&&c.$element.find(".dd-selected-image").attr("src",a.selectedData.imageHoverSrc);var b=c.$element.find(".factory-result").val(a.selectedData.value);b.change()}})}else{c.executeEvents(this.$element),this.$hints=this.$element.next(),this.$hints.hasClass("factory-hints")&&(this.$element.change(function(){return c.updateHints(),!1}),this.updateHints=function(){var a=c.$element.val();c.$hints.find(".factory-hint").hide(),c.$hints.find(".factory-hint-"+a).show()},c.updateHints()),this.getAjaxData=function(){var a=c.$element.data("ajax-data-id");return window[a]},this.loadData=function(){var b=c.getAjaxData();a.ajax({url:b.url,data:b.data,dataType:"json",success:function(a){return a.error?c.showError(a.error):void c.fill(a.items)},error:function(a){console&&console.log&&console.log(a.responseText),c.showError("Unexpected error occurred during the ajax request.")},complete:function(){c.removeLoader()}})},this.fill=function(a){this.clearList();var b=c.getAjaxData();if(a&&a.length)for(var d in a){var e=a[d];c.addListItem(e)}else this.$element.append("<option>"+b.emptyList+"</li>");this.$element.trigger("factory-loaded")},this.clearList=function(){this.$element.html("")},this.addListItem=function(b){var d=a("<option />").attr("value",b.value).text(b.title).appendTo(this.$element),e=c.getAjaxData();e.selected&&e.selected==b.value&&d.attr("selected","selected")},this.showError=function(b){this.clearList();var d=a("<div class='factory-control-error'></div>").append(a("<i class='fa fa-exclamation-triangle'></i>")).append(b),e=c.getAjaxData();this.$element.append("<option>"+e.emptyList+"</li>"),this.$element.after(d),this.$element.addClass("factory-has-error")},this.removeLoader=function(){this.$element.removeClass("factory-hidden");var b=c.getAjaxData();a(b.loader).remove()};var h=this.$element.data("ajax");h&&this.loadData()}};a.fn.factoryBootstrap482_dropdownControl=function(c){if("string"==typeof c){var d=a(this).data("factory.dropdown.control");return d?d[c]():null}return this.each(function(){var c=a(this),d=c.data("factory.dropdown.control");d||c.data("factory.dropdown.control",d=new b(this))})},a.fn.factoryBootstrap482_dropdownControl.Constructor=b,a(function(){a(".factory-bootstrap-482 .factory-dropdown").factoryBootstrap482_dropdownControl()})}(jQuery);

View File

@@ -0,0 +1,10 @@
/*!
* Bootstrap generator - v1.0.1, 2021-11-19
* Webcraftic factory build
*
* Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
* Site: http://webcraftic.com
* Support: http://webcraftic.com/contact-us/
*/
!function(a){var b=function(b){var c=this;if(this.$element=a(b),this.way=this.$element.data("way"),this.name=this.$element.data("name"),"checklist"===this.way){this.getAjaxData=function(){var a=c.$element.data("ajax-data-id");return window[a]},this.loadData=function(){var b=c.getAjaxData();a.ajax({url:b.url,data:b.data,dataType:"json",success:function(a){return a.error?c.showError(a.error):void c.fill(a.items)},error:function(){c.showError("Unexpected error occurred during the ajax request.")},complete:function(){c.removeLoader()}})},this.fill=function(a){this.clearList();var b=c.getAjaxData();if(a&&a.length){this.$element.removeClass("factory-empty");for(var d in a){var e=a[d];c.addListItem(e)}}else this.$element.addClass("factory-empty"),this.$element.append("<li>"+b.emptyList+"</li>")},this.clearList=function(){this.$element.html("")},this.addListItem=function(b){var d=a("<li>"),e=a("<label>").attr("for","factory-checklist-"+c.name+"-"+b.value).appendTo(d),f=a("<span>").appendTo(e),g=a("<input />").attr("type","checkbox").attr("name",c.name+"[]").val(b.value).attr("id","factory-checklist-"+c.name+"-"+b.value).appendTo(f),h=(a("<span>"+b.title+"</span>").appendTo(e),c.getAjaxData());h.selected.length&&a.inArray(b.value,h.selected)>=0&&g.attr("checked","checked"),this.$element.append(d)},this.showError=function(b){this.$element.html("").append(a("<i class='fa fa-exclamation-triangle'></i>")).append(b),this.$element.addClass("factory-list-error")},this.removeLoader=function(){this.$element.removeClass("factory-hidden");var b=c.getAjaxData();a(b.loader).remove()};var d=this.$element.data("ajax");d&&this.loadData()}};a.fn.factoryBootstrap482_listControl=function(c){if("string"==typeof c){var d=a(this).data("factory.list.control");return d?d[c]():null}return this.each(function(){var c=a(this),d=c.data("factory.list.control");d||c.data("factory.list.control",d=new b(this))})},a.fn.factoryBootstrap482_listControl.Constructor=b,a(function(){a(".factory-bootstrap-482 .factory-list").factoryBootstrap482_listControl()})}(jQuery);

View File

@@ -0,0 +1,10 @@
/*!
* Bootstrap generator - v1.0.1, 2021-11-19
* Webcraftic factory build
*
* Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
* Site: http://webcraftic.com
* Support: http://webcraftic.com/contact-us/
*/
!function(a){"use strict";var b=function(b){this.$element=a(b);var c=a(".factory-mtextbox-item",this.$element).eq(0).clone(!0);a(".factory-mtextbox-add-item",this.$element).on("click",function(){var b=a(this).closest(".factory-multiple-textbox-group").find(".factory-mtextbox-items"),d=c.clone(!0),e=a('<button class="btn btn-default btn-small factory-mtextbox-remove-item"><i class="fa fa-times" aria-hidden="true"></i></button>');return b.append(d.append(e)),d.find('input[type="text"]').val("").focus(),!1}),a(document).on("click",".factory-mtextbox-remove-item",function(){return a(this).closest(".factory-mtextbox-item").remove(),!1})};a.fn.factoryBootstrap482_MultipleTextboxControl=function(){return this.each(function(){new b(this)})},a(function(){a(".factory-bootstrap-482 .factory-multiple-textbox-group").factoryBootstrap482_MultipleTextboxControl()})}(jQuery);

View File

@@ -0,0 +1,10 @@
/*!
* Bootstrap generator - v1.0.1, 2021-11-19
* Webcraftic factory build
*
* Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
* Site: http://webcraftic.com
* Support: http://webcraftic.com/contact-us/
*/
!function(a,b,c,d){"use strict";var e="factoryBootstrap482_moreLink";a.fn[e]=function(b,c){return this.each(function(){var b=a(this);b.find(".factory-more-link-show").click(function(){return a(a(this).attr("href")).fadeIn(),a(this).hide(),!1}),b.find(".factory-more-link-hide").click(function(){var b=a(a(this).attr("href"));return b.fadeOut(300,function(){b.parents(".factory-more-link").find(".factory-more-link-show").show()}),!1})})},a(function(){a(".factory-bootstrap-482 .factory-more-link").factoryBootstrap482_moreLink()})}(jQuery,window,document);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,47 @@
<?php
/**
* Factory Bootstrap
*
* @author Alex Kovalev <alex.kovalevv@gmail.com>
* @since 1.0.0
* @package factory-bootstrap
* @copyright (c) 2018, Webcraftic Ltd
*
*/
// Exit if accessed directly
if( !defined('ABSPATH') ) {
exit;
}
// module provides function only for the admin area
if( !is_admin() ) {
return;
}
if( defined('FACTORY_BOOTSTRAP_482_LOADED') ) {
return;
}
define('FACTORY_BOOTSTRAP_482_VERSION', '4.8.5');
define('FACTORY_BOOTSTRAP_482_LOADED', true);
if( !defined('FACTORY_FLAT_ADMIN') ) {
define('FACTORY_FLAT_ADMIN', true);
}
define('FACTORY_BOOTSTRAP_482_DIR', dirname(__FILE__));
define('FACTORY_BOOTSTRAP_482_URL', plugins_url('', __FILE__));
require_once(FACTORY_BOOTSTRAP_482_DIR . '/includes/functions.php');
/**
* @param Wbcr_Factory480_Plugin $plugin
*/
add_action('wbcr_factory_bootstrap_482_plugin_created', function ($plugin) {
$manager = new Wbcr_FactoryBootstrap482_Manager($plugin);
$plugin->setBootstap($manager);
});

View File

@@ -0,0 +1,242 @@
<?php
/**
* This file manages assets of the Factory Bootstap.
*
* @author Alex Kovalev <alex@byonepress.com>
* @author Paul Kashtanoff <paul@byonepress.com>
* @since 1.0.0
* @package factory-bootstrap
* @copyright (c) 2018, OnePress Ltd
*
*/
// Exit if accessed directly
if( !defined('ABSPATH') ) {
exit;
}
/**
* The Bootstrap Manager class.
*
* @since 3.2.0
*/
class Wbcr_FactoryBootstrap482_Manager {
/**
* A plugin for which the manager was created.
*
* @since 3.2.0
* @var Wbcr_Factory480_Plugin
*/
public $plugin;
/**
* Contains scripts to include.
*
* @since 3.2.0
* @var string[]
*/
public $scripts = [];
/**
* Contains styles to include.
*
* @since 3.2.0
* @var string[]
*/
public $styles = [];
/**
* Createas a new instance of the license api for a given plugin.
*
* @since 1.0.0
*/
public function __construct(Wbcr_Factory480_Plugin $plugin)
{
$this->plugin = $plugin;
add_action('admin_enqueue_scripts', [$this, 'loadAssets']);
add_filter('admin_body_class', [$this, 'adminBodyClass']);
}
/**
* Includes the Bootstrap scripts.
*
* @param array|string $scripts
* @since 3.2.0
*
*/
public function enqueueScript($scripts)
{
if( is_array($scripts) ) {
foreach($scripts as $script) {
if( !in_array($script, $this->scripts) ) {
$this->scripts[] = $script;
}
}
} else {
if( !in_array($scripts, $this->scripts) ) {
$this->scripts[] = $scripts;
}
}
}
/**
* * Includes the Bootstrap styles.
*
* @param array|string $styles
* @since 3.2.0
*
*/
public function enqueueStyle($styles)
{
if( is_array($styles) ) {
foreach($styles as $style) {
if( !in_array($style, $this->styles) ) {
$this->styles[] = $style;
}
}
} else {
if( !in_array($styles, $this->styles) ) {
$this->styles[] = $styles;
}
}
}
/**
* Loads Bootstrap assets.
*
* @return void
* @since 3.2.0
* @see admin_enqueue_scripts
*
*/
public function loadAssets($hook)
{
do_action('wbcr_factory_480_bootstrap_enqueue_scripts', $hook);
do_action('wbcr_factory_480_bootstrap_enqueue_scripts_' . $this->plugin->getPluginName(), $hook);
$dependencies = [];
if( !empty($this->scripts) ) {
$dependencies[] = 'jquery';
$dependencies[] = 'jquery-ui-core';
$dependencies[] = 'jquery-ui-widget';
}
foreach($this->scripts as $script) {
switch( $script ) {
case 'plugin.iris':
$dependencies[] = 'jquery-ui-widget';
$dependencies[] = 'jquery-ui-slider';
$dependencies[] = 'jquery-ui-draggable';
break;
}
}
if( !empty($this->scripts) ) {
$this->enqueueScripts($this->scripts, 'js', $dependencies);
}
if( !empty($this->styles) ) {
$this->enqueueScripts($this->styles, 'css', $dependencies);
}
}
/**
* @param array $scripts
* @param string $type
* @param array $dependencies
*/
protected function enqueueScripts(array $scripts, $type, array $dependencies)
{
$is_first = true;
/**
* Sets permission for file caching and combining into one file.
*
* @since 4.1.0
*/
$cache_enable = apply_filters('wbcr/factory/bootstrap/cache_enable', true);
$cache_id = md5(implode(',', $this->scripts) . $type . $this->plugin->getPluginVersion());
$cache_dir_path = FACTORY_BOOTSTRAP_482_DIR . '/assets/cache/';
$cache_dir_url = FACTORY_BOOTSTRAP_482_URL . '/assets/cache/';
$cache_filepath = $cache_dir_path . $cache_id . ".min." . $type;
$cache_fileurl = $cache_dir_url . $cache_id . ".min." . $type;
if( $cache_enable && file_exists($cache_filepath) ) {
if( $type == 'js' ) {
wp_enqueue_script('wbcr-factory-bootstrap-cached', $cache_fileurl, $dependencies, $this->plugin->getPluginVersion());
} else {
wp_enqueue_style('wbcr-factory-bootstrap-cached', $cache_fileurl, [], $this->plugin->getPluginVersion());
}
} else {
$cache_dir_exists = false;
if( !file_exists($cache_dir_path) ) {
if( @mkdir($cache_dir_path, 0755) && wp_is_writable($cache_dir_path) ) {
$cache_dir_exists = true;
}
} else {
if( wp_is_writable($cache_dir_path) ) {
$cache_dir_exists = true;
}
}
$concat_files = [];
foreach($scripts as $script_to_load) {
$script_to_load = sanitize_text_field($script_to_load);
if( $cache_enable && $cache_dir_exists ) {
$fname = FACTORY_BOOTSTRAP_482_DIR . "/assets/$type-min/$script_to_load.min." . $type;
if( file_exists($fname) ) {
$f = @fopen($fname, 'r');
$concat_files[] = @fread($f, filesize($fname));
@fclose($f);
}
} else {
if( $type == 'js' ) {
wp_enqueue_script(md5($script_to_load), FACTORY_BOOTSTRAP_482_URL . "/assets/$type-min/$script_to_load.min." . $type, $is_first ? $dependencies : false, $this->plugin->getPluginVersion());
} else {
wp_enqueue_style(md5($script_to_load), FACTORY_BOOTSTRAP_482_URL . "/assets/$type-min/$script_to_load.min." . $type, [], $this->plugin->getPluginVersion());
}
$is_first = false;
}
}
if( $cache_enable && $cache_dir_exists && !empty($concat_files) ) {
$cf = @fopen($cache_filepath, 'w');
$write_content = implode(PHP_EOL, $concat_files);
@fwrite($cf, $write_content);
@fclose($cf);
chmod($cache_filepath, 0755);
if( file_exists($cache_filepath) ) {
if( $type == 'js' ) {
wp_enqueue_script('wbcr-factory-bootstrap-' . $cache_id, $cache_fileurl, $dependencies, $this->plugin->getPluginVersion());
} else {
wp_enqueue_style('wbcr-factory-bootstrap-' . $cache_id, $cache_fileurl, [], $this->plugin->getPluginVersion());
}
}
}
}
}
/**
* Adds the body classes: 'factory-flat or 'factory-volumetric'.
*
* @param string $classes
*
* @return string
* @since 3.2.0
*
*/
public function adminBodyClass($classes)
{
$classes .= FACTORY_FLAT_ADMIN ? ' factory-flat ' : ' factory-volumetric ';
return $classes;
}
}

View File

@@ -0,0 +1,2 @@
<?php
// Silence is golden.

View File

@@ -0,0 +1,2 @@
<?php
// Silence is golden.

View File

@@ -0,0 +1,260 @@
/**
* Базовые стили для всех копомпонентов Clearfy
* @author Webcraftic <wordpress.webraftic@gmail.com>
* @copyright Webcraftic 06.10.2018
* @sicne 2.0.5
*/
#WBCR {
/* subscribe widget */
}
#WBCR .wbcr-factory-pages-480-impressive-page-template .factory-checkbox.wbcr-factory-clearfy-icon-pro:after {
display: inline-block;
position: relative;
content: 'PRO';
background: #ff5722;
border-radius: 4px;
color: #fff;
font-size: 10px;
line-height: 1;
font-style: normal;
padding: 4px 6px;
margin-left: 4px;
vertical-align: top;
top: -8px;
left: -10px;
right: auto;
z-index: 11;
}
#WBCR .wbcr-factory-pages-480-impressive-page-template .wbcr-factory-clearfy-246-multisite-suggetion {
padding: 30px 80px;
}
#WBCR .wbcr-factory-pages-480-impressive-page-template .wbcr-factory-clearfy-246-multisite-suggetion h3 {
margin: 0 0 20px;
}
#WBCR .wbcr-factory-pages-480-impressive-page-template .wbcr-factory-clearfy-246-multisite-suggetion .wbcr-factory-inner-contanier {
border: 2px dashed #8bc34a;
background: #fff;
padding: 20px;
}
#WBCR .wbcr-factory-pages-480-impressive-page-template .wbcr-factory-clearfy-246-multisite-suggetion .wbcr-factory-activate-premium {
display: inline-block;
cursor: pointer;
line-height: 16px;
font-size: 13px;
font-weight: 600;
padding: 12px 20px;
text-align: center;
text-decoration: none;
text-transform: uppercase;
border-radius: 2px;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
color: #353535;
background: #e8e8e8;
box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
-moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
-webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
}
#WBCR .wbcr-factory-pages-480-impressive-page-template .wbcr-factory-clearfy-246-multisite-suggetion .wbcr-factory-activate-premium:active {
box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.2);
-moz-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.2);
-webkit-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.2);
}
#WBCR .wbcr-factory-pages-480-impressive-page-template .wbcr-factory-clearfy-246-multisite-suggetion .wbcr-factory-activate-premium:focus {
outline: none;
border: 0;
}
#WBCR .wbcr-factory-pages-480-impressive-page-template .wbcr-factory-clearfy-246-multisite-suggetion .wbcr-factory-purchase-premium {
display: inline-block;
cursor: pointer;
line-height: 16px;
font-size: 13px;
font-weight: 600;
padding: 12px 20px;
text-align: center;
text-decoration: none;
text-transform: uppercase;
border-radius: 2px;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
color: #755c0e;
background: #fdd868;
box-shadow: 0 1px 0 rgba(60, 45, 2, 0.31);
-moz-box-shadow: 0 1px 0 rgba(60, 45, 2, 0.31);
-webkit-box-shadow: 0 1px 0 rgba(60, 45, 2, 0.31);
}
#WBCR .wbcr-factory-pages-480-impressive-page-template .wbcr-factory-clearfy-246-multisite-suggetion .wbcr-factory-purchase-premium:active {
box-shadow: inset 0 1px 0 rgba(60, 45, 2, 0.31);
-moz-box-shadow: inset 0 1px 0 rgba(60, 45, 2, 0.31);
-webkit-box-shadow: inset 0 1px 0 rgba(60, 45, 2, 0.31);
}
#WBCR .wbcr-factory-pages-480-impressive-page-template .wbcr-factory-clearfy-246-multisite-suggetion .wbcr-factory-purchase-premium:focus {
outline: none;
border: 0;
}
#WBCR .wbcr-factory-pages-480-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-246-pro-suggettion {
background: #fff;
color: #353535;
font-weight: 600;
border: 2px dashed #8bc34a;
}
#WBCR .wbcr-factory-pages-480-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-246-pro-suggettion h3 {
margin: 0 0 20px;
padding: 10px 0;
text-align: center;
border-bottom: 2px solid #e6e6e6;
color: #636363;
font-size: 17px;
font-weight: 600;
vertical-align: middle;
text-transform: uppercase;
}
#WBCR .wbcr-factory-pages-480-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-246-pro-suggettion ul {
position: relative;
margin-bottom: 20px;
}
#WBCR .wbcr-factory-pages-480-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-246-pro-suggettion ul li {
font-size: 15px;
padding: 7px;
padding-left: 20px;
}
#WBCR .wbcr-factory-pages-480-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-246-pro-suggettion ul li:before {
content: " ";
display: inline-block;
width: 0.4em;
height: 0.7em;
border: solid #8bc34a;
border-width: 0 0.2em 0.2em 0;
left: 0;
margin-right: 10px;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
}
#WBCR .wbcr-factory-pages-480-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-246-pro-suggettion .wbcr-factory-purchase-premium {
display: block;
cursor: pointer;
line-height: 16px;
font-size: 13px;
font-weight: 600;
padding: 12px 20px;
text-align: center;
text-decoration: none;
text-transform: uppercase;
border-radius: 2px;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
color: #353535;
background: #e8e8e8;
box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
-moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
-webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
}
#WBCR .wbcr-factory-pages-480-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-246-pro-suggettion .wbcr-factory-purchase-premium:active {
box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.2);
-moz-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.2);
-webkit-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.2);
}
#WBCR .wbcr-factory-pages-480-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-246-pro-suggettion .wbcr-factory-purchase-premium:focus {
outline: none;
border: 0;
}
#WBCR .wbcr-factory-subscribe-widget {
margin-top: 0 !important;
border: 1px solid rgba(0, 0, 0, 0.1);
border-radius: 5px;
}
#WBCR .wbcr-factory-subscribe-widget__field {
margin: 10px auto;
display: block;
width: 100%;
text-align: center;
box-shadow: 0 0 0 transparent;
border-radius: 4px;
border: 1px solid #d6d4d4;
background-color: #fff;
color: #32373c;
}
#WBCR .wbcr-factory-subscribe-widget__button {
display: block;
width: 100%;
text-align: center;
margin: 14px 0 0;
box-shadow: none;
min-width: 100px;
background-color: #ff5722;
border: 0;
color: #fff;
}
#WBCR .wbcr-factory-subscribe-widget__button:active,
#WBCR .wbcr-factory-subscribe-widget__button:focus {
box-shadow: inset -1px 1px 1px #222;
outline: none;
}
#WBCR .wbcr-factory-subscribe-widget__msgbox {
font-weight: bold;
}
#WBCR .wbcr-factory-subscribe-widget__text {
display: none;
padding: 10px 14px;
margin: 0 0 10px;
}
#WBCR .wbcr-factory-subscribe-widget__text--success {
background: #d6efbe;
color: #61824b;
}
#WBCR .wbcr-factory-subscribe-widget__text--success2 {
background: #ffe0b3;
}
#WBCR .wbcr-factory-subscribe-widget__text--error {
background: #f1b1b6;
}
#WBCR .wbcr-factory-subscribe-widget__checkbox {
margin: 0 10px 0 0;
}
#WBCR .wbcr-factory-subscribe-widget__checkbox-label {
font-weight: normal;
color: #8c8888;
font-size: 12px;
}
@media screen and (max-width: 1550px) {
#WBCR .wbcr-factory-pages-480-impressive-page-template .wbcr-factory-clearfy-246-multisite-pro-suggetion {
padding: 10px 80px;
}
#WBCR .wbcr-factory-pages-480-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-246-pro-suggettion {
padding: 10px;
}
#WBCR .wbcr-factory-pages-480-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-246-pro-suggettion h3 {
margin: 0 0 20px;
padding: 10px 0;
font-size: 13px;
font-weight: 600;
}
#WBCR .wbcr-factory-pages-480-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-246-pro-suggettion ul {
margin-bottom: 20px;
}
#WBCR .wbcr-factory-pages-480-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-246-pro-suggettion ul li {
font-size: 13px;
padding: 2px;
padding-left: 10px;
}
#WBCR .wbcr-factory-pages-480-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-246-pro-suggettion ul li:before {
width: 0.4em;
height: 0.7em;
border-width: 0 0.2em 0.2em 0;
left: 0;
margin-right: 10px;
}
#WBCR .wbcr-factory-pages-480-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-clearfy-246-pro-suggettion .wbcr-factory-purchase-premium {
font-weight: 700;
line-height: 16px;
font-size: 12px;
padding: 8px 12px;
border-radius: 2px;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
}
}
/*# sourceMappingURL=clearfy-base.css.map */

View File

@@ -0,0 +1,140 @@
/**
* Page components
* @author Alex Kovalev <alex.kovalevv@gmail.com>
* @copyright Alex Kovalev 30.09.2017
*/
#WBCR .wbc-factory-clearfy-246-components {
padding: 0 20px 20px;
text-align: center;
}
#WBCR .wbc-factory-clearfy-246-components .plugin-card {
position: relative;
display: inline-block;
width: 32.7%;
height: 250px;
margin-left: 0;
margin-right: 0;
text-align: left;
float: none;
vertical-align: top;
}
#WBCR .wbc-factory-clearfy-246-components .plugin-card:first-child {
margin-left: 0;
}
#WBCR .wbc-factory-clearfy-246-components .plugin-card .plugin-card-bottom {
position: absolute;
bottom: 0;
right: 0;
left: 0;
}
#WBCR .wbc-factory-clearfy-246-components .plugin-card .plugin-card-top {
min-height: 163px;
}
#WBCR .wbc-factory-clearfy-246-components .plugin-card .desc,
#WBCR .wbc-factory-clearfy-246-components .plugin-card .name {
margin-right: 0 !important;
}
#WBCR .wbc-factory-clearfy-246-components .plugin-card .name h3 {
font-size: 17px;
margin-top: 0 !important;
}
#WBCR .wbc-factory-clearfy-246-components .plugin-card .install-now {
float: right;
}
#WBCR .wbc-factory-clearfy-246-components .plugin-card .delete-now {
float: right;
margin-left: 5px;
}
#WBCR .wbc-factory-clearfy-246-components .plugin-card .delete-now .dashicons,
#WBCR .wbc-factory-clearfy-246-components .plugin-card .delete-now .dashicons-before:before {
font-size: 16px !important;
line-height: 1.5 !important;
color: #62696f;
}
#WBCR .wbc-factory-clearfy-246-components .plugin-card a.open-plugin-details-modal {
color: #5c5d5f;
text-decoration: none;
font-weight: 600;
font-size: 15px;
}
#WBCR .wbc-factory-clearfy-246-components .plugin-card .plugin-card-premium-ribbon {
position: absolute;
bottom: 60px;
right: 0;
height: 30px;
width: 120px;
border-radius: 3px 0 0 3px;
background-color: #f7dea9;
color: #67532f;
text-align: center;
font-size: 12px;
font-weight: 600;
line-height: 2.4;
text-transform: uppercase;
z-index: 1;
}
#WBCR .wbc-factory-clearfy-246-components .plugin-card .plugin-card-free-ribbon {
position: absolute;
bottom: 60px;
right: 0;
height: 30px;
width: 120px;
border-radius: 3px 0 0 3px;
background-color: #cccccc;
color: #6b6b6b;
text-align: center;
font-size: 12px;
font-weight: 600;
line-height: 2.4;
text-transform: uppercase;
z-index: 1;
}
#WBCR .wbc-factory-clearfy-246-components .plugin-card .plugin-card-freemium-ribbon {
position: absolute;
bottom: 60px;
right: 0;
height: 30px;
width: 120px;
border-radius: 3px 0 0 3px;
background-color: #cae2b3;
color: #546742;
text-align: center;
font-size: 12px;
font-weight: 600;
line-height: 2.4;
text-transform: uppercase;
z-index: 1;
}
#WBCR .wbc-factory-clearfy-246-components .plugin-card.premium {
border-color: #e8d7b2;
background-color: #fff9eb;
}
#WBCR .wbc-factory-clearfy-246-components .plugin-card.plugin-status-deactive {
background-color: #f1f1f1;
}
#WBCR .wbc-factory-clearfy-246-components .plugin-card.plugin-status-deactive a.open-plugin-details-modal {
color: #ababab;
text-decoration: none;
font-weight: 600;
font-size: 15px;
}
#WBCR .wbc-factory-clearfy-246-components .plugin-card.plugin-status-deactive .plugin-icon {
opacity: 0.3;
}
#WBCR .wbc-factory-clearfy-246-components .plugin-card.plugin-status-deactive .desc {
color: #afafaf;
}
#WBCR .wbc-factory-clearfy-246-components .plugin-card.plugin-status-deactive.premium {
background-color: #f9f2f1;
}
@media screen and (max-width: 1750px) {
#WBCR .wbc-factory-clearfy-246-components .plugin-card {
width: 49%;
}
}
@media screen and (max-width: 1350px) {
#WBCR .wbc-factory-clearfy-246-components .plugin-card {
width: 100%;
}
}
/*# sourceMappingURL=components.css.map */

View File

@@ -0,0 +1,57 @@
/**
* Styles for plugin options search form
* @author Alex Kovlaev <alex.kovalevv@gmail.com>, https://github.com/alexkovalevv
*
* @since 2.2.0
*/
#wbcr-factory-clearfy-246__search_options_form #wbcr-factory-clearfy-246__autocomplete {
width: 100%;
box-sizing: border-box;
border-color: #d6d4d4;
}
#wbcr-factory-clearfy-246__search_options_form #wbcr-factory-clearfy-246__autocomplete::placeholder {
color: #eae9e9;
}
#wbcr-factory-clearfy-246__search_options_form.wbcr-factory-clearfy-246__autocomplete-wrap {
padding: 10px;
}
#wbcr-factory-clearfy-246__search_options_form .wbcr-factory-clearfy-246__autocomplete-label {
display: block !important;
}
.wbcr-factory-clearfy-246__autocomplete-suggestions {
border: 1px solid #999;
background: #FFF;
overflow: auto;
}
.wbcr-factory-clearfy-246__autocomplete-suggestion {
padding: 2px 5px;
white-space: nowrap;
overflow: hidden;
cursor: pointer;
}
.wbcr-factory-clearfy-246__autocomplete-selected {
background: #F0F0F0;
}
.wbcr-factory-clearfy-246__autocomplete-suggestions strong {
font-weight: normal;
color: #3399FF;
}
.wbcr-factory-clearfy-246__autocomplete-group {
padding: 2px 5px;
}
.wbcr-factory-clearfy-246__autocomplete-group strong {
display: block;
border-bottom: 1px solid #000;
}
/*# sourceMappingURL=autocomplete.css.map */

View File

@@ -0,0 +1,663 @@
.not-visible-in-manager {
display: none;
}
/**
* Global License Message
*/
.global-license-message {
width: 600px;
margin: auto;
/*margin-top: 100px;*/
font-size: 14px;
line-height: 170%;
}
.global-license-message h2, .global-license-message h3 {
padding: 0px;
margin: 5px 0;
}
.onp-page-wrap {
max-width: 720px;
margin: auto;
margin-top: 40px;
font-size: 14px;
line-height: 170%;
}
.onp-container {
border: 0px;
padding: 0px;
border-radius: 5px;
background: rgb(255, 255, 255) !important;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
-moz-box-sizing: border-box;
box-sizing: border-box;
}
#license-manager {
padding: 0 0 40px;
}
#license-manager .onp-container {
background: -moz-linear-gradient(top, rgba(255, 255, 255, 1) 63%, rgba(246, 246, 246, 1) 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(63%, rgba(255, 255, 255, 1)), color-stop(100%, rgba(246, 246, 246, 1))); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, rgba(255, 255, 255, 1) 63%, rgba(246, 246, 246, 1) 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, rgba(255, 255, 255, 1) 63%, rgba(246, 246, 246, 1) 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, rgba(255, 255, 255, 1) 63%, rgba(246, 246, 246, 1) 100%); /* IE10+ */
background: linear-gradient(to bottom, rgba(255, 255, 255, 1) 63%, rgba(246, 246, 246, 1) 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f6f6f6', GradientType=0); /* IE6-9 */
}
.onp-container h2 {
margin: 0px;
padding: 0px;
}
.onp-container p {
margin: 0 0 2px 0;
padding: 0px;
line-height: 170%;
}
.btn-uppercase {
font-size: 12px;
letter-spacing: 1px;
text-transform: uppercase;
text-decoration: none;
}
.btn-uppercase *[class^=icon] {
position: relative;
top: -1px;
left: -1px;
}
.onp-page-wrap .license-message {
margin-bottom: 20px;
overflow: hidden;
}
.onp-page-wrap .license-message .alert {
margin: 0px;
}
.onp-page-wrap .license-message strong {
display: block;
margin-bottom: 0px;
}
.onp-page-wrap .license-message p {
margin: 1px 0 1px 0;
padding: 0px;
}
.onp-page-wrap .license-message a {
font-weight: bold;
}
.license-message .alert-warning-icon {
padding-left: 60px;
background-image: url("../img/warning.png");
background-position: 15px 11px;
background-repeat: no-repeat;
}
#onp-hide-license-manager {
position: absolute;
top: 2px;
right: 15px;
font-size: 12px;
color: #777;
font-weight: bold;
}
#onp-hide-license-manager:hover {
text-decoration: none;
}
#onp-hide-license-manager,
#onp-hide-license-manager:focus,
#onp-hide-license-manager:hover {
outline: none;
border: 0px;
box-shadow: none;
}
#onp-hide-license-manager .fa {
margin-right: 5px;
}
#license-manager .license-details-wrap {
border: 1px solid #e9e9e9;
padding: 0px;
border-radius: 5px;
background: rgb(255, 255, 255); /* Old browsers */
background: -moz-linear-gradient(top, rgba(255, 255, 255, 1) 63%, rgba(246, 246, 246, 1) 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(63%, rgba(255, 255, 255, 1)), color-stop(100%, rgba(246, 246, 246, 1))); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, rgba(255, 255, 255, 1) 63%, rgba(246, 246, 246, 1) 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, rgba(255, 255, 255, 1) 63%, rgba(246, 246, 246, 1) 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, rgba(255, 255, 255, 1) 63%, rgba(246, 246, 246, 1) 100%); /* IE10+ */
background: linear-gradient(to bottom, rgba(255, 255, 255, 1) 63%, rgba(246, 246, 246, 1) 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f6f6f6', GradientType=0); /* IE6-9 */
box-shadow: 0px 2px 1px #c9c9c9;
}
#license-manager .activate-trial-hint {
background-color: #f8f8f8;
padding: 10px 20px;
position: relative;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
#license-manager .activate-error-hint {
background-color: #fb7976;
color: #f5f5f5;
text-shadow: none;
padding: 2px 9px;
width: 100%;
position: relative;
margin-left: -9px;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
#license-manager .license-details {
padding: 20px;
padding-bottom: 0px;
-webkit-border-top-left-radius: 5px;
-webkit-border-top-right-radius: 5px;
-moz-border-radius-topleft: 5px;
-moz-border-radius-topright: 5px;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
position: relative;
z-index: 10;
}
#license-manager .license-key-identity {
font-style: italic;
position: relative;
top: -6px;
}
#license-manager .license-key-identity code {
display: inline-block;
padding: 2px 5px;
font-size: 16px;
}
#license-manager .license-key-description {
font-size: 12px;
}
#license-manager .license-delete-button {
float: right;
text-decoration: none;
position: relative;
top: -7px;
left: 10px;
}
#license-manager .license-synchronization-button {
float: right;
text-decoration: none;
position: relative;
top: -7px;
left: 5px;
}
#license-manager .license-details-block {
padding: 28px 35px 15px 35px;
margin-left: -35px;
width: 100%;
position: relative;
margin-top: 20px;
background: #fff;
border: 0px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
color: #333;
border-radius: 5px;
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
#license-manager .license-details-block p + p {
margin-top: 10px;
}
#license-manager .license-details-block a {
font-weight: bold;
}
#license-manager .license-details-block.trial-details-block {
background: #ffdede;
border: 0;
box-shadow: 0 0 7px #cf4944;
color: #a04342;
text-shadow: 1px 1px 2px #fff2f2;
}
#license-manager .license-details-block.trial-details-block a {
color: #a04342;
}
#license-manager .license-details-block.paid-details-block {
border: 0;
box-shadow: 0 0 7px #b8823b;
color: #8a6d3b;
background: #fcf8e3;
}
#license-manager .license-details-block.paid-details-block a {
color: #7a4c00;
}
#license-manager .license-details-block.gift-details-block {
background: #DFF0D8;
border: 1px solid #D6E9C6;
box-shadow: 0px 0px 5px #D6E9C6;
color: #468847;
}
#license-manager .license-details-block.gift-details-block a {
color: #468847;
}
#license-manager .license-params {
margin-top: 15px;
position: relative;
left: -2px;
}
#license-manager .license-value {
display: block;
font-size: 16px;
font-weight: bold;
}
#license-manager .license-value small {
font-weight: normal;
}
#license-manager .license-value-name {
display: block;
font-size: 12px;
}
#license-manager .license-param {
white-space: nowrap;
line-height: 130%;
padding: 10px 0 10px 35px;
vertical-align: top;
}
#license-manager .license-param-domain {
padding-left: 65px;
background: url('../img/free-license-chip.png') -3px 0px no-repeat;
}
#license-manager .trial-details-block .license-param-domain {
background: url('../img/trial-license-chip.png') -3px 0px no-repeat;
}
#license-manager .paid-details-block .license-param-domain {
background: url('../img/paid-license-chip.png') -3px 0px no-repeat;
}
#license-manager .license-details-block h3 {
margin: 0px;
padding: 0px;
font-size: 22px;
margin-bottom: 10px;
}
#license-manager .license-details-block a {
color: #a04342;
}
#license-manager .license-input {
padding: 20px;
-webkit-border-bottom-right-radius: 5px;
-webkit-border-bottom-left-radius: 5px;
-moz-border-radius-bottomright: 5px;
-moz-border-radius-bottomleft: 5px;
border-bottom-right-radius: 5px;
border-bottom-left-radius: 5px;
}
#license-manager .license-input .btn {
text-decoration: none;
}
#license-manager .license-key-wrap {
padding-right: 110px;
}
#license-key {
width: 100%;
position: relative;
font-size: 18px;
line-height: 20px;
position: relative;
top: -1px;
height: 36px;
color: #000;
}
#license-submit {
float: right;
padding: 7px 14px 6px 14px;
}
#plugin-update-block {
padding-top: 10px;
font-size: 10px;
color: #666;
max-width: 700px;
margin: auto;
}
#plugin-update-block a {
color: #000;
}
.purchase-premium {
float: right;
position: relative;
top: -11px;
left: 8px;
text-decoration: none;
font-weight: bold;
background: #fffaea;
padding: 0px;
border-radius: 4px;
outline: none;
margin-top: 4px;
box-shadow: 0 0 8px #fddf67;
}
.purchase-premium .fa {
position: relative;
margin-right: 3px;
margin-left: 3px;
}
/*
* Manual Trial Activation
*/
#trial-manual .onp-container {
padding: 20px;
overflow: hidden;
}
#trial-manual ul {
margin: 0px;
padding: 0px;
margin-top: 10px;
}
#trial-manual ul li {
margin-bottom: 10px;
}
#trial-manual .license-reponse-code {
width: 100%;
height: 150px;
margin-top: 5px;
}
/*
* Manual Key Activation
*/
#activate-key-manual .onp-container {
padding: 20px;
overflow: hidden;
}
#activate-key-manual ul {
margin: 0px;
padding: 0px;
margin-top: 10px;
}
#activate-key-manual ul li {
margin-bottom: 10px;
}
#activate-key-manual .license-reponse-code {
width: 100%;
height: 150px;
margin-top: 5px;
}
/**
* FAQ
*/
#faq-block {
border-top: 1px solid #d7d7d7;
margin-top: 20px;
width: 100%;
padding: 10px 20px;
position: relative;
}
#faq-block .faq-header {
border-bottom: 1px dotted #333;
display: inline-block;
cursor: pointer;
font-weight: bold;
line-height: 16px;
font-size: 13px;
color: #333;
}
#faq-block .faq-header:hover {
border-bottom: 0px;
}
#faq-block .faq-header:focus, #faq-block .faq-header:active {
outline: 0;
}
#faq-block li > div {
display: none;
}
#faq-block p {
margin: 6px 0 10px 0;
font-size: 13px;
line-height: 170%;
}
#open-faq {
color: #000 !important;
text-decoration: none;
border-bottom: 1px dotted #000;
margin-left: 4px;
}
#open-faq:hover {
border-bottom: 0px;
}
.gray-link, .gray-link a {
color: #666666 !important;
}
/**
* A form to create a customer account
*/
.onp-single-block .onp-header {
text-align: center;
padding: 10px;
}
.onp-single-block .onp-header h4 {
font-size: 26px;
line-height: 130%;
}
.onp-single-block .onp-container {
padding: 50px 60px;
border: 1px solid #bbb;
position: relative;
}
.onp-single-block .onp-container .onp-container-header {
margin-bottom: 20px;
}
.onp-single-block .onp-container .onp-container-header h4 {
color: #000;
margin: 0px;
font-size: 20px;
}
.onp-single-block .onp-container .onp-container-header .onp-key-info {
color: #666;
}
.onp-single-block .onp-container .onp-container-header .onp-key-info .fa {
color: #777;
}
.onp-single-block .onp-container .onp-container-header .onp-icon {
position: absolute;
top: 30px;
right: 30px;
}
.onp-single-block .onp-container p,
.onp-single-block .onp-container li {
color: #333;
font-size: 14px;
}
.onp-single-block .onp-container p + p {
margin-top: 15px;
}
.onp-single-block .onp-container .onp-form {
text-align: left;
padding: 10px 0 0 0;
}
.onp-single-block #email {
font-size: 26px;
line-height: 26px;
height: 50px;
}
.onp-single-block .checkbox {
padding-left: 25px;
color: #999;
font-style: italic;
}
.onp-single-block .checkbox input {
margin-left: -25px;
}
.onp-single-block .onp-actions {
padding-top: 20px;
}
.onp-single-block .onp-actions .btn-primary {
margin-right: 15px;
}
.onp-single-block .onp-actions a.onp-cancel {
text-decoration: none;
color: #111;
}
.onp-single-block .onp-actions a.onp-cancel:hover {
text-decoration: none;
border-bottom: 1px solid #111;
background-color: #f9f9f9;
}
.onp-single-block .onp-benefits {
padding-left: 25px;
margin-top: 15px;
list-style: initial;
}
.onp-single-block .onp-login-details {
}
.onp-single-block .onp-text-seporator {
border-top: 1px solid #eee;
margin: 30px 0;
}
#create-account .onp-container {
background: #fff url("../img/create-account-bg.png") no-repeat 370px 230px !important;
}
#account-created .onp-step {
overflow: hidden;
}
#account-created .onp-steps {
padding: 25px 0 20px 10px;
}
#account-created .onp-step + .onp-step {
margin-top: 20px;
}
#account-created .onp-step .onp-num {
font-size: 25px;
line-height: 40px;
background-color: #f5f5f5;
width: 40px;
height: 40px;
display: inline-block;
border-radius: 7px;
text-align: center;
-moz-box-sizing: border-box;
box-sizing: border-box;
margin-right: 10px;
vertical-align: middle;
font-weight: bolder;
font-family: Arial, sans-serif;
}
#account-created .onp-step .onp-desc {
width: 490px;
display: inline-block;
vertical-align: middle;
line-height: 150%;
}
#finish .onp-container {
background: #fff url("../img/finish.png") no-repeat 0 -90px !important;
padding-left: 260px;
min-height: 250px;
border-bottom: 3px solid #ccc;
}
.wcl-loader {
float: right;
width: 32px;
}

View File

@@ -0,0 +1,454 @@
#WBCR {
margin: 0;
padding: 0;
}
.w-factory-clearfy-246__form-buttons {
text-align: right;
padding: 10px;
background: #f7f7f7;
border-top: 1px solid #e8e8e8;
}
.w-factory-clearfy-246__form-buttons .w-factory-clearfy-246__skip-button {
background-color: #e7e7e7;
border-color: #e7e7e7;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 0 #e7e7e7;
text-shadow: 0 -1px 1px #e7e7e7, 1px 0 1px #e7e7e7, 0 1px 1px #e7e7e7, -1px 0 1px #e7e7e7;
margin: 0;
color: #8a8a8a;
}
.w-factory-clearfy-246__form-buttons .w-factory-clearfy-246__skip-button:active,
.w-factory-clearfy-246__form-buttons .w-factory-clearfy-246__skip-button:hover,
.w-factory-clearfy-246__form-buttons .w-factory-clearfy-246__skip-button:focus {
background: #dddddd;
border-color: #dddddd;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 0 #dddddd;
color: #8a8a8a;
}
.w-factory-clearfy-246__form-buttons .w-factory-clearfy-246__continue-button {
background-color: #f57d4f;
border-color: #f77d50;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 0 #f77d50;
text-shadow: 0 -1px 1px #f77d50, 1px 0 1px #f77d50, 0 1px 1px #f77d50, -1px 0 1px #f77d50;
margin: 0;
}
.w-factory-clearfy-246__form-buttons .w-factory-clearfy-246__continue-button:active,
.w-factory-clearfy-246__form-buttons .w-factory-clearfy-246__continue-button:hover,
.w-factory-clearfy-246__form-buttons .w-factory-clearfy-246__continue-button:focus {
background: #f86b3b;
border-color: #f86b3b;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 0 #f86b3b;
}
.w-factory-clearfy-246-setup {
text-align: center;
max-width: 900px;
margin: 65px auto 24px;
box-shadow: none;
background: #f1f1f1;
padding: 0;
}
.w-factory-clearfy-246-setup__inner-wrap,
.w-factory-clearfy-246__setup-form .factory-form-layout {
padding: 30px;
}
.w-factory-clearfy-246-setup-steps {
padding: 0 0 24px;
margin: 0;
list-style: none outside;
overflow: hidden;
color: #ccc;
width: 100%;
display: -webkit-inline-box;
display: inline-flex;
}
.w-factory-clearfy-246-setup-steps li {
width: 100%;
float: left;
padding: 0 0 0.8em;
margin: 0;
text-align: center;
position: relative;
border-bottom: 4px solid #ccc;
line-height: 1.4;
}
.w-factory-clearfy-246-setup-steps li::before {
content: "";
border: 4px solid #ccc;
border-radius: 100%;
width: 4px;
height: 4px;
position: absolute;
bottom: 0;
left: 50%;
margin-left: -6px;
margin-bottom: -8px;
background: #fff;
}
.w-factory-clearfy-246-setup-steps li.active {
border-color: #ff1c40 !important;
color: #222;
font-weight: 700;
}
.w-factory-clearfy-246-setup-steps li.active::before {
border-color: #ff1c40 !important;
}
.w-factory-clearfy-246-setup-steps li a {
color: #a16696;
text-decoration: none;
padding: 1.5em;
margin: -1.5em;
position: relative;
z-index: 1;
}
.w-factory-clearfy-246-setup-steps li a:focus,
.w-factory-clearfy-246-setup-steps li a:hover {
color: #111;
text-decoration: underline;
}
/*.w-factory-clearfy-246-setup-steps li.done {
border-color: #f57d4f;
color: #f57d4f
}
.w-factory-clearfy-246-setup-steps li.done::before {
border-color: #f57d4f;
background: #f57d4f
}*/
.w-factory-clearfy-246-setup .w-factory-clearfy-246-setup-actions {
overflow: hidden;
margin: 20px 0 0;
position: relative;
}
.w-factory-clearfy-246-setup-content p:last-child {
margin-bottom: 0;
}
.w-factory-clearfy-246-setup-content p.store-setup {
margin-top: 0;
}
.w-factory-clearfy-246-setup-footer-links {
font-size: 0.85em;
color: #7b7b7b;
margin: 1.18em auto;
display: inline-block;
text-align: center;
}
.w-factory-clearfy-246-logo {
text-align: center;
}
.w-factory-clearfy-246-logo img {
max-width: 250px;
}
.w-factory-clearfy-246-setup-content {
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.13);
margin: 0 0 20px;
background: #fff;
zoom: 1;
text-align: left;
}
.w-factory-clearfy-246-setup-content table {
font-size: 1em;
line-height: 1.75;
color: #666;
}
.w-factory-clearfy-246-setup-content table thead {
background: #f1f1f1;
}
.w-factory-clearfy-246-setup-content table th,
.w-factory-clearfy-246-setup-content table td {
padding: 10px 15px;
}
.w-factory-clearfy-246-setup-content h1,
.w-factory-clearfy-246-setup-content h2,
.w-factory-clearfy-246-setup-content h3,
.w-factory-clearfy-246-setup-content table {
margin: 0 0 20px;
border: 0;
padding: 0;
color: #666;
clear: none;
font-weight: 500;
}
.w-factory-clearfy-246-setup-content p {
margin: 20px 0;
font-size: 1.15em;
line-height: 1.75;
color: #666;
text-align: center;
}
.w-factory-clearfy-246-setup-step__new_onboarding-welcome {
font-size: 22px !important;
}
.w-factory-clearfy-246-setup-content a {
color: #f57d4f;
}
.w-factory-clearfy-246-setup-content a:focus,
.w-factory-clearfy-246-setup-content a:hover {
color: #111;
}
.w-factory-clearfy-246-setup-content table.tax-rates {
width: 100%;
font-size: 0.92em;
}
.w-factory-clearfy-246-setup-content table.tax-rates th {
padding: 0;
text-align: center;
width: auto;
vertical-align: middle;
}
.w-factory-clearfy-246-setup-content table.tax-rates td {
border: 1px solid #f5f5f5;
padding: 6px;
text-align: center;
vertical-align: middle;
}
.w-factory-clearfy-246-setup-content table.tax-rates td input {
outline: 0;
border: 0;
padding: 0;
box-shadow: none;
text-align: center;
width: 100%;
}
.w-factory-clearfy-246-setup-content table.tax-rates td.sort {
cursor: move;
color: #ccc;
}
.w-factory-clearfy-246-setup-content table.tax-rates td.sort::before {
content: "\f333";
font-family: dashicons;
}
.w-factory-clearfy-246-setup-content table.tax-rates td.readonly {
background: #f5f5f5;
}
.w-factory-clearfy-246-setup-content table.tax-rates .add {
padding: 1em 0 0 1em;
line-height: 1;
font-size: 1em;
width: 0;
margin: 6px 0 0;
height: 0;
overflow: hidden;
position: relative;
display: inline-block;
}
.w-factory-clearfy-246-setup-content table.tax-rates .add::before {
content: "\f502";
font-family: dashicons;
position: absolute;
left: 0;
top: 0;
}
.w-factory-clearfy-246-setup-content table.tax-rates .remove {
padding: 1em 0 0 1em;
line-height: 1;
font-size: 1em;
width: 0;
margin: 0;
height: 0;
overflow: hidden;
position: relative;
display: inline-block;
}
.w-factory-clearfy-246-setup-content table.tax-rates .remove::before {
content: "\f182";
font-family: dashicons;
position: absolute;
left: 0;
top: 0;
}
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-pages {
width: 100%;
border-top: 1px solid #eee;
}
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-pages thead th {
display: none;
}
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-pages .page-name {
width: 30%;
font-weight: 700;
}
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-pages td,
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-pages th {
padding: 14px 0;
border-bottom: 1px solid #eee;
}
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-pages td:first-child,
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-pages th:first-child {
padding-right: 9px;
}
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-pages th {
padding-top: 0;
}
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-pages .page-options p {
color: #777;
margin: 6px 0 0 24px;
line-height: 1.75;
}
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-pages .page-options p input {
vertical-align: middle;
margin: 1px 0 0;
height: 1.75em;
width: 1.75em;
line-height: 1.75;
}
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-pages .page-options p label {
line-height: 1;
}
@media screen and (max-width: 782px) {
.w-factory-clearfy-246-setup-content .form-table tbody th {
width: auto;
}
}
.w-factory-clearfy-246-setup-content .twitter-share-button {
float: right;
}
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-next-steps {
overflow: hidden;
margin: 0 0 24px;
padding-bottom: 2px;
}
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-next-steps h2 {
margin-bottom: 12px;
}
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-next-steps .w-factory-clearfy-246-setup-next-steps-first {
float: left;
width: 50%;
box-sizing: border-box;
}
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-next-steps .w-factory-clearfy-246-setup-next-steps-last {
float: right;
width: 50%;
box-sizing: border-box;
}
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-next-steps ul {
padding: 0 2em 0 0;
list-style: none outside;
margin: 0;
}
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-next-steps ul li a {
display: block;
padding: 0 0 0.75em;
}
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-next-steps ul .setup-product a.button {
background-color: #f7f7f7;
border-color: #ccc;
color: #23282d;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 0 #ccc;
text-shadow: 1px 0 1px #eee, 0 1px 1px #eee;
font-size: 1em;
height: auto;
line-height: 1.75;
margin: 0 0 0.75em;
opacity: 1;
padding: 1em;
text-align: center;
}
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-next-steps ul .setup-product a.button:active,
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-next-steps ul .setup-product a.button:focus,
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-next-steps ul .setup-product a.button:hover {
background: #f5f5f5;
border-color: #aaa;
}
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-next-steps ul .setup-product a.button-primary {
color: #fff;
background-color: #f19570;
border-color: #f77d50;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 0 #f77d50;
text-shadow: 0 -1px 1px #f77d50, 1px 0 1px #f77d50, 0 1px 1px #f77d50, -1px 0 1px #f77d50;
}
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-next-steps ul .setup-product a.button-primary:active,
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-next-steps ul .setup-product a.button-primary:focus,
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-next-steps ul .setup-product a.button-primary:hover {
color: #fff;
background: #f77d50;
border-color: #f77d50;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 0 #f77d50;
}
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-next-steps ul li a::before {
color: #82878c;
font: 400 20px/1 dashicons;
speak: none;
display: inline-block;
padding: 0 10px 0 0;
top: 1px;
position: relative;
text-decoration: none !important;
vertical-align: top;
}
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-next-steps ul .learn-more a::before {
content: "\f105";
}
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-next-steps ul .video-walkthrough a::before {
content: "\f126";
}
.w-factory-clearfy-246-setup-content .w-factory-clearfy-246-setup-next-steps ul .newsletter a::before {
content: "\f465";
}
.w-factory-clearfy-246-setup-content .updated,
.w-factory-clearfy-246-setup-content .woocommerce-newsletter {
padding: 24px 24px 0;
margin: 0 0 24px;
overflow: hidden;
background: #f5f5f5;
}
.w-factory-clearfy-246-setup-content .updated p,
.w-factory-clearfy-246-setup-content .woocommerce-newsletter p {
padding: 0;
margin: 0 0 12px;
}
.w-factory-clearfy-246-setup-content .updated form,
.w-factory-clearfy-246-setup-content .updated p:last-child,
.w-factory-clearfy-246-setup-content .woocommerce-newsletter form,
.w-factory-clearfy-246-setup-content .woocommerce-newsletter p:last-child {
margin: 0 0 24px;
}
.w-factory-clearfy-246-setup-content .checkbox input[type=checkbox] {
opacity: 0;
position: absolute;
left: -9999px;
}
.w-factory-clearfy-246-setup-content .checkbox label {
position: relative;
display: inline-block;
padding-left: 28px;
}
.w-factory-clearfy-246-setup-content .checkbox label::after,
.w-factory-clearfy-246-setup-content .checkbox label::before {
position: absolute;
content: "";
display: inline-block;
}
.w-factory-clearfy-246-setup-content .checkbox label::before {
height: 16px;
width: 16px;
left: 0;
top: 3px;
border: 1px solid #aaa;
background-color: #fff;
border-radius: 3px;
}
.w-factory-clearfy-246-setup-content .checkbox label::after {
height: 5px;
width: 9px;
border-left: 2px solid;
border-bottom: 2px solid;
-webkit-transform: rotate(-45deg);
-ms-transform: rotate(-45deg);
transform: rotate(-45deg);
left: 4px;
top: 7px;
color: #fff;
}
.w-factory-clearfy-246-setup-content .checkbox input[type=checkbox] + label::after {
content: none;
}
.w-factory-clearfy-246-setup-content .checkbox input[type=checkbox]:checked + label::after {
content: "";
}
.w-factory-clearfy-246-setup-content .checkbox input[type=checkbox]:focus + label::before {
outline: #3b99fc auto 5px;
}
.w-factory-clearfy-246-setup-content .checkbox input[type=checkbox]:checked + label::before {
background: #935687;
border-color: #935687;
}
/*# sourceMappingURL=page-setup.css.map */

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -0,0 +1,221 @@
/*!
* Глобальный JS файл, который регистрирует глобальные переменные с общими методами для всех компонентов Clearfy
* и самого Clearfy.
*
* $.wbcr_factory_clearfy_246.app - методы для работы с приложением. Скрыть, показать уведомления.
* $.wbcr_factory_clearfy_246.hooks - это иммитация хуков и фильтров аналогично тем, что используются в Wordpress
*
* Copyright 2018, Webcraftic, http://webcraftic.com
*
* @since 2.0.5
* @pacakge clearfy
*/
(function($) {
'use strict';
if( !$.wbcr_factory_clearfy_246 ) {
$.wbcr_factory_clearfy_246 = {};
}
//todo: Переопредление для совместимости со старыми версиями плагинов.
$.wbcr_factory_clearfy_246.filters = $.wbcr_factory_clearfy_246.filters || $.wfactory_480.filters;
//todo: Переопредление для совместимости со старыми версиями плагинов.
$.wbcr_factory_clearfy_246.hooks = $.wbcr_factory_clearfy_246.hooks || $.wfactory_480.hooks;
$.wbcr_factory_clearfy_246.app = $.wbcr_factory_clearfy_246.app || {
/**
* Создает и показывает уведомление внутри интерфейса Clearfy
*
* @param {string} message - сообщение об ошибке или предупреждение
* @param {string} type - тип уведомления (error, warning, success)
*/
showNotice: function(message, type) {
var noticeContanier = $('<div></div>'),
noticeInnerWrap = $('<p></p>'),
dashicon = $('<span></span>'),
dashiconClass,
noticeId = this.makeid();
if( !type ) {
type = 'warning';
}
noticeContanier.addClass('alert', 'wbcr-factory-warning-notice')
.addClass('alert-' + type).addClass('wbcr-factory-' + type + '-notice');
noticeContanier.append(noticeInnerWrap);
noticeContanier.attr('id', 'uq-' + noticeId);
if( 'success' === type ) {
dashiconClass = 'dashicons-plus';
} else if( 'error' === type ) {
dashiconClass = 'dashicons-no';
} else {
dashiconClass = 'dashicons-warning';
}
dashicon.addClass('dashicons').addClass(dashiconClass);
noticeInnerWrap.prepend(dashicon);
dashicon.after(message);
$([document.documentElement, document.body]).animate({
scrollTop: $('.wbcr-factory-content').offset().top - 100
}, 300, function() {
noticeContanier.hide();
$('.wbcr-factory-content').prepend(noticeContanier);
noticeContanier.fadeIn();
/**
* Хук выполняет проивольную функцию, после того как уведомление отображено
* Реализация системы фильтров и хуков в файле libs/clearfy/admin/assests/js/global.js
* Пример регистрации хука $.wfactory_480.hooks.add('wbcr/factory_clearfy_246/updated',
* function(noticeId) {});
* @param {string} noticeId - id уведомления
*/
$.wfactory_480.hooks.run('wbcr/factory_clearfy_246/showed_notice', [noticeId]);
$.wfactory_480.hooks.run('wbcr/clearfy/showed_notice', [noticeId]);
});
return noticeId;
},
/**
* Удаляет уведомление из интерфейса Clearfy
*
* @param {string} noticeId - id уведомления
*/
hideNotice: function(noticeId) {
var el;
if( !noticeId ) {
el = $('.wbcr-factory-content').find('.alert');
} else {
el = $('#uq-' + noticeId);
}
el.fadeOut(500, function(e) {
$(e).remove();
/**
* Хук выполняет проивольную функцию, после того как уведомление скрыто
* Реализация системы фильтров и хуков в файле libs/clearfy/admin/assests/js/global.js
* Пример регистрации хука $.wfactory_480.hooks.add('wbcr/factory_clearfy_246/updated',
* function(noticeId)
* {});
* @param {string} noticeId - id уведомления
*/
$.wfactory_480.hooks.run('wbcr/factory_clearfy_246/hidded_notice', [noticeId]);
$.wfactory_480.hooks.run('wbcr/clearfy/hidded_notice', [noticeId]);
});
},
makeid: function() {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for( var i = 0; i < 32; i++ ) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
}
};
$.wfactory_480.hooks.add('core/components/pre_activate', function(button) {
// Выполняем код ниже, только на страницах плагина с интерфейсом Clearfy
if( !$('#WBCR').length ) {
return false;
}
if( button.closest('.alert').length ) {
button.closest('.alert').remove();
}
if( button.closest('.plugin-card').length ) {
button.closest('.plugin-card').removeClass('plugin-status-deactive');
button.closest('.plugin-card').find('.delete-now').remove();
}
});
$.wfactory_480.hooks.add('core/components/deactivated', function(button, data, response) {
// Выполняем код ниже, только на страницах плагина с интерфейсом Clearfy
if( !$('#WBCR').length ) {
return false;
}
if( button.closest('.plugin-card').length ) {
button.closest('.plugin-card').addClass('plugin-status-deactive');
if( response.data['delete_button'] && response.data['delete_button'] !== '' ) {
button.before($(response.data['delete_button']).addClass('delete-now'));
}
}
if( button.closest('.wbcr-hide-after-action').length ) {
button.closest('.wbcr-hide-after-action').remove();
}
});
$.wfactory_480.hooks.add('core/components/deleted', function(button) {
// Выполняем код ниже, только на страницах плагина с интерфейсом Clearfy
if( !$('#WBCR').length ) {
return false;
}
let button_i18n = button.data('i18n');
button.closest('.plugin-card').find('.install-now').data('plugin-action', 'install');
button.closest('.plugin-card').find('.install-now').attr('data-plugin-action', 'install');
button.closest('.plugin-card').find('.install-now').removeClass('button-primary').addClass('button-default');
button.closest('.plugin-card').find('.install-now').text(button_i18n.install);
if( button.closest('.plugin-card').length ) {
button.closest('.plugin-card').addClass('plugin-status-deactive');
button.remove();
}
});
$.wfactory_480.hooks.add('core/components/activation_error', function(plugin, button, response) {
// Выполняем код ниже, только на страницах плагина с интерфейсом Clearfy
if( !($('#WBCR').length && $.wbcr_factory_clearfy_246) ) {
return false;
}
button.closest('.plugin-card').addClass('plugin-status-deactive');
if( response.data && response.data.error_message ) {
$.wbcr_factory_clearfy_246.app.showNotice(response.data.error_message, 'danger');
}
});
$.wfactory_480.hooks.add('core/components/update_error', function(button, data, response) {
// Выполняем код ниже, только на страницах плагина с интерфейсом Clearfy
if( !($('#WBCR').length && $.wbcr_factory_clearfy_246) ) {
return false;
}
if( response.data && response.data.error_message ) {
$.wbcr_factory_clearfy_246.app.showNotice(response.data.error_message, 'danger');
}
});
$.wfactory_480.hooks.add('core/components/activated', function(button, data, response) {
// Выполняем код ниже, только на страницах плагина с интерфейсом Clearfy
if( !$('#WBCR').length ) {
return false;
}
button.closest('.plugin-card').removeClass('plugin-status-deactive');
});
$.wfactory_480.hooks.add('core/components/ajax_error', function(xhr, ajaxOptions, thrownError) {
// Выполняем код ниже, только на страницах плагина с интерфейсом Clearfy
if( !($('#WBCR').length && $.wbcr_factory_clearfy_246) ) {
return false;
}
$.wbcr_factory_clearfy_246.app.showNotice('Error: [' + thrownError + '] Status: [' + xhr.status + '] Error massage: [' + xhr.responseText + ']', 'danger');
});
})(jQuery);

View File

@@ -0,0 +1,92 @@
/**
* Этот файл содержит скрипт исполняелся во время процедур с формой лицензирования.
* Его основная роль отправка ajax запросов на проверку, активацию, деактивацию лицензии
* и вывод уведомлений об ошибка или успешно выполнении проверок.
*
* @author Alex Kovalev <alex.kovalevv@gmail.com>, Github: https://github.com/alexkovalevv
* @copyright (c) 05.10.2018, Webcraftic
* @version 1.1
* @since 1.4.0
*/
jQuery(function($) {
var allNotices = [];
$(document).on('click', '.wcl-control-btn', function() {
var wrapper = $('#wcl-license-wrapper'),
loader = wrapper.data('loader'),
pluginName = wrapper.data('plugin-name'),
wpnonce = wrapper.data('nonce'),
licenseAction = $(this).data('action');
for( i = 0; i < allNotices.length; i++ ) {
$.wbcr_factory_clearfy_246.app.hideNotice(allNotices[i]);
}
$('.wcl-control-btn').hide();
$(this).after('<img class="wcl-loader" src="' + loader + '">');
var data = {
action: 'wbcr-clearfy-activate-license-for-' + pluginName,
_wpnonce: wpnonce,
plugin_name: pluginName,
license_action: licenseAction,
licensekey: ''
};
if( $(this).data('action').trim() === 'activate' ) {
data.licensekey = $('#license-key').val().trim();
}
$.ajax(ajaxurl, {
type: 'post',
dataType: 'json',
data: data,
success: function(response) {
var noticeId;
if( !response || !response.success ) {
$('.wcl-control-btn').show();
$('.wcl-loader').remove();
if( response.data ) {
console.log(response.data.error_message);
noticeId = $.wbcr_factory_clearfy_246.app.showNotice('Error: [' + response.data.error_message + ']', 'danger');
allNotices.push(noticeId);
} else {
console.log(response);
}
return;
}
if( response.data && response.data.message ) {
noticeId = $.wbcr_factory_clearfy_246.app.showNotice(response.data.message, 'success');
allNotices.push(noticeId);
// todo: доработать генерацию формы, вместо перезагрузки страницы
window.location.reload();
}
},
error: function(xhr, ajaxOptions, thrownError) {
$('.wcl-control-btn').show();
$('.wcl-loader').remove();
console.log(xhr.status);
console.log(xhr.responseText);
console.log(thrownError);
var noticeId = $.wbcr_factory_clearfy_246.app.showNotice('Error: [' + thrownError + '] Status: [' + xhr.status + '] Error massage: [' + xhr.responseText + ']', 'danger');
allNotices.push(noticeId);
}
});
return false;
});
});

View File

@@ -0,0 +1,51 @@
(function($) {
'use strict';
$(document).ready(function() {
if( '' !== window.location.hash && window.location.hash.indexOf('factory-control-') ) {
let controlClass = window.location.hash.replace('#', ''),
controlEl = $('.' + controlClass);
// If the option is hidden in a container that becomes visible only with certain logic of actions.
if( controlEl.closest('.factory-div').length && !controlEl.is(':visible') ) {
controlEl.closest('.factory-div').fadeIn();
}
// If the option is hidden in a container as an additional
if( controlEl.closest('.factory-more-link-content').length && !controlEl.is(':visible') ) {
controlEl.closest('.factory-more-link-content').fadeIn(100, function() {
controlEl.closest('.factory-more-link-content').find('.factory-more-link-hide').show();
});
$('a[href="#' + controlEl.closest('.factory-more-link-content').attr('id') + '"]').hide();
}
$([document.documentElement, document.body]).animate({
scrollTop: controlEl.offset().top - 150
}, 500, function() {
controlEl.find('.control-label').css({
color: '#ff5722',
fontWeight: 'bold'
});
controlEl.closest('.factory-more-link-content').find('.factory-more-link-hide').css('display', 'block');
history.pushState("", document.title, window.location.pathname
+ window.location.search);
});
}
if( undefined === window.wfactory_clearfy_search_options ) {
throw new Error('Global var {wfactory_clearfy_search_options} is not declared.');
}
$('#wbcr-factory-clearfy-246__autocomplete').wfactory_clearfy_autocomplete({
lookup: wfactory_clearfy_search_options,
onSelect: function(suggestion) {
$('#wbcr-factory-clearfy-246__autocomplete').prop("disabled", true);
window.location.href = suggestion.data.page_url;
}
});
});
})(jQuery);

View File

@@ -0,0 +1,62 @@
jQuery(function($) {
$('#wbcr-factory-subscribe-widget__subscribe-form').submit(function(e) {
e.preventDefault();
var agree = $(this).find('[name=agree_terms]:checked'),
pluginName = $('#wbcr-factory-subscribe-widget__plugin-name').val(),
email = $('#wbcr-factory-subscribe-widget__email').val(),
groupId = $('#wbcr-factory-subscribe-widget__group-id').val();
if( agree.length === 0 ) {
return;
}
$.ajax({
method: "POST",
url: ajaxurl,
dataType: 'json',
data: {
action: 'wbcr-clearfy-subscribe-for-' + pluginName,
email: email,
group_id: groupId,
plugin_name: pluginName,
_wpnonce: $(this).data('nonce')
},
success: function(response) {
if( !response || !response.success ) {
if( response.data ) {
console.log(response.data.error_message);
noticeId = $.wbcr_factory_clearfy_246.app.showNotice('Error: [' + response.data.error_message + ']', 'danger');
setTimeout(function() {
$.wbcr_factory_clearfy_246.app.hideNotice(noticeId);
}, 5000);
} else {
console.log(response);
}
return;
}
if( response.data ) {
$(".wbcr-factory-subscribe-widget__text").hide();
if( response.data.subscribed ) {
$(".wbcr-factory-subscribe-widget__text--success").show();
} else {
$(".wbcr-factory-subscribe-widget__text--success2").show();
}
}
},
error: function(xhr, ajaxOptions, thrownError) {
console.log(xhr.status);
console.log(xhr.responseText);
console.log(thrownError);
var noticeId = $.wbcr_factory_clearfy_246.app.showNotice('Error: [' + thrownError + '] Status: [' + xhr.status + '] Error massage: [' + xhr.responseText + ']', 'danger');
setTimeout(function() {
$.wbcr_factory_clearfy_246.app.hideNotice(noticeId);
}, 5000);
}
});
});
});

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,89 @@
<?php
/**
* Factory clearfy
*
* @author Alex Kovalev <alex.kovalevv@gmail.com>, Github: https://github.com/alexkovalevv
* @since 1.0.0
* @package clearfy
* @copyright (c) 2018, Webcraftic Ltd
*
*/
// Exit if accessed directly
if( !defined('ABSPATH') ) {
exit;
}
if( defined('FACTORY_CLEARFY_246_LOADED') ) {
return;
}
define('FACTORY_CLEARFY_246_LOADED', true);
define('FACTORY_CLEARFY_246', '2.4.6');
define('FACTORY_CLEARFY_246_DIR', dirname(__FILE__));
define('FACTORY_CLEARFY_246_URL', plugins_url(null, __FILE__));
load_plugin_textdomain('wbcr_factory_clearfy_246', false, dirname(plugin_basename(__FILE__)) . '/langs');
require(FACTORY_CLEARFY_246_DIR . '/includes/ajax-handlers.php');
require(FACTORY_CLEARFY_246_DIR . '/includes/class-helpers.php');
require(FACTORY_CLEARFY_246_DIR . '/includes/class-configurate.php');
// module provides function only for the admin area
if( is_admin() ) {
/**
* Подключаем скрипты для установки компонентов Clearfy
* на все страницы админпанели.
*/
add_action('admin_enqueue_scripts', function ($hook) {
wp_enqueue_script('wbcr-factory-clearfy-246-global', FACTORY_CLEARFY_246_URL . '/assets/js/clearfy-globals.js', [
'jquery',
'wfactory-480-core-general'
], FACTORY_CLEARFY_246);
require_once FACTORY_CLEARFY_246_DIR . '/includes/class-search-options.php';
$all_options = \WBCR\Factory_Clearfy_246\Search_Options::get_all_options();
if( empty($all_options) ) {
return;
}
$allow_print_data = false;
$formated_options = [];
foreach($all_options as $option) {
//if( !$allow_print_data && isset($_GET['page']) && $option['page_id'] === $_GET['page'] ) {
//$allow_print_data = true;
//}
$formated_options[] = [
'value' => $option['title'],
'data' => [
//'hint' => isset($option['hint']) ? $option['hint'] : '',
'page_url' => $option['page_url'],
'page_id' => $option['page_id']
]
];
}
//if( !$allow_print_data ) {
//return;
//}
wp_localize_script('wbcr-factory-clearfy-246-global', 'wfactory_clearfy_search_options', $formated_options);
});
if( defined('FACTORY_PAGES_480_LOADED') ) {
require(FACTORY_CLEARFY_246_DIR . '/pages/class-pages.php');
require(FACTORY_CLEARFY_246_DIR . '/pages/class-page-more-features.php');
require(FACTORY_CLEARFY_246_DIR . '/pages/class-page-license.php');
require(FACTORY_CLEARFY_246_DIR . '/pages/class-pages-components.php');
require(FACTORY_CLEARFY_246_DIR . '/pages/setup-parts/class-step.php');
require(FACTORY_CLEARFY_246_DIR . '/pages/setup-parts/class-step-form.php');
require(FACTORY_CLEARFY_246_DIR . '/pages/setup-parts/class-step-custom.php');
require(FACTORY_CLEARFY_246_DIR . '/pages/class-page-setup.php');
}
}

View File

@@ -0,0 +1,158 @@
<?php
/**
* Ajax handlers
*
* @author Alex Kovalev <alex.kovalevv@gmail.com>, Github: https://github.com/alexkovalevv
* @copyright (c) 2017 Webraftic Ltd
* @version 1.0
*/
// Exit if accessed directly
if( !defined('ABSPATH') ) {
exit;
}
/**
* Обработчик ajax запросов для виджета подписки на новости
*
* @param Wbcr_Factory480_Plugin $plugin_instance
*
* @since 2.3.0
*
*/
function wbcr_factory_clearfy_246_subscribe($plugin_instance)
{
$plugin_name = $plugin_instance->request->post('plugin_name', null, true);
if( ($plugin_instance->getPluginName() !== $plugin_name) || !$plugin_instance->current_user_can() ) {
wp_die(-1, 403);
}
$email = $plugin_instance->request->post('email', null, true);
$group_id = $plugin_instance->request->post('group_id', null, true);
check_admin_referer("clearfy_subscribe_for_{$plugin_name}");
if( empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL) ) {
wp_send_json_error(['error_message' => __('You did not send your email address or it is incorrect!', 'wbcr_factory_clearfy_246')]);
}
if( empty($group_id) ) {
wp_send_json_error(['error_message' => __('Group ID is empty!', 'wbcr_factory_clearfy_246')]);
}
$response = wp_remote_post('https://clearfy.pro/wp-json/mailerlite/v1/subscribe/', [
'body' => [
'email' => $email,
'group_id' => $group_id
]
]);
if( is_wp_error($response) ) {
wp_send_json_error(['error_message' => $response->get_error_message()]);
}
$data = @json_decode(wp_remote_retrieve_body($response), ARRAY_A);
if( isset($data['message']) ) {
wp_send_json_error(['error_message' => $data['message'], 'error_code' => $data['code']]);
}
if( isset($data['subscribed']) ) {
$plugin_instance->updatePopulateOption('factory_clearfy_user_subsribed', 1);
wp_send_json_success(['subscribed' => $data['subscribed']]);
}
wp_send_json_error(['error_message' => __('Unknown error while trying to subscribe to newsletter.', 'wbcr_factory_clearfy_246')]);
die();
}
/**
* Обработчик ajax запросов для проверки, активации, деактивации лицензионного ключа
*
* @param Wbcr_Factory480_Plugin $plugin_instance
*
* @since 2.0.7
*
*/
function wbcr_factory_clearfy_246_check_license($plugin_instance)
{
$plugin_name = $plugin_instance->request->post('plugin_name', null, true);
if( ($plugin_instance->getPluginName() !== $plugin_name) || !$plugin_instance->current_user_can() ) {
wp_die(-1, 403);
}
$action = $plugin_instance->request->post('license_action', false, true);
$license_key = $plugin_instance->request->post('licensekey', null);
check_admin_referer("clearfy_activate_license_for_{$plugin_name}");
if( empty($action) || !in_array($action, ['activate', 'deactivate', 'sync', 'unsubscribe']) ) {
wp_send_json_error(['error_message' => __('Licensing action not passed or this action is prohibited!', 'wbcr_factory_clearfy_246')]);
die();
}
$result = null;
$success_message = '';
try {
switch( $action ) {
case 'activate':
if( empty($license_key) || strlen($license_key) > 32 ) {
wp_send_json_error(['error_message' => __('License key is empty or license key too long (license key is 32 characters long)', 'wbcr_factory_clearfy_246')]);
} else {
$plugin_instance->premium->activate($license_key);
$success_message = __('Your license has been successfully activated', 'wbcr_factory_clearfy_246');
}
break;
case 'deactivate':
$plugin_instance->premium->deactivate();
$success_message = __('The license is deactivated', 'wbcr_factory_clearfy_246');
break;
case 'sync':
$plugin_instance->premium->sync();
$success_message = __('The license has been updated', 'wbcr_factory_clearfy_246');
break;
case 'unsubscribe':
$plugin_instance->premium->cancel_paid_subscription();
$success_message = __('Subscription success cancelled', 'wbcr_factory_clearfy_246');
break;
}
} catch( Exception $e ) {
/**
* Экшен выполняется, когда проверка лицензии вернула ошибку
*
* @param string $license_key
* @param string $error_message
*
* @param string $action
* @since 2.0.7
*
* @since 2.1.2 Переименован в {$plugin_name}/factory/clearfy/check_license_error
*/
do_action("{$plugin_name}/factory/clearfy/check_license_error", $action, $license_key, $e->getMessage());
wp_send_json_error(['error_message' => $e->getMessage()]);
die();
}
/**
* Экшен выполняется, когда проверка лицензии успешно завершена
*
* @param string $license_key
*
* @param string $action
* @since 2.1.2 Переименован в {$plugin_name}/factory/clearfy/check_license_success
* @since 2.0.7
*
*/
do_action("{$plugin_name}/factory/clearfy/check_license_success", $action, $license_key);
wp_send_json_success(['message' => $success_message]);
die();
}

View File

@@ -0,0 +1,116 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Configurate clearfy plugins
*
* @author Alex Kovalev <alex.kovalevv@gmail.com>, Github: https://github.com/alexkovalevv
* @since 1.0.0
* @package clearfy
* @copyright (c) 2018, Webcraftic Ltd
*
*/
abstract class Wbcr_FactoryClearfy246_Configurate {
/**
* @param Wbcr_Factory480_Plugin $plugin
*/
public function __construct( Wbcr_Factory480_Plugin $plugin ) {
$this->plugin = $plugin;
$this->registerActionsAndFilters();
}
/**
* Registers filters and actions
*
* @return mixed
*/
abstract protected function registerActionsAndFilters();
/**
* Get options with namespace
*
* @param $option_name
* @param bool $default
*
* @return mixed|void
*/
public function getPopulateOption( $option_name, $default = false ) {
return $this->plugin->getPopulateOption( $option_name, $default );
}
/**
* Get options with namespace
*
* @param $option_name
* @param bool $default
*
* @return mixed|void
*/
public function getOption( $option_name, $default = false ) {
return $this->plugin->getOption( $option_name, $default );
}
/**
* Get network options with namespace
*
* @param $option_name
* @param bool $default
*
* @return mixed|void
*/
public function getNetworkOption( $option_name, $default = false ) {
return $this->plugin->getNetworkOption( $option_name, $default );
}
/**
* @param $option_name
* @param $value
*
* @return bool
*/
public function updatePopulateOption( $option_name, $value ) {
$this->plugin->updatePopulateOption( $option_name, $value );
}
/**
* @param $option_name
* @param $value
*
* @return bool
*/
public function updateNetworkOption( $option_name, $value ) {
$this->plugin->updateNetworkOption( $option_name, $value );
}
/**
* @param $option_name
* @param $value
*
* @return bool
*/
public function updateOption( $option_name, $value ) {
$this->plugin->updateOption( $option_name, $value );
}
/**
* @param $option_name
*
* @return bool
*/
public function deletePopulateOption( $option_name ) {
$this->plugin->deletePopulateOption( $option_name );
}
/**
* @param $option_name
*
* @return bool
*/
public function deleteOption( $option_name ) {
$this->plugin->deleteOption( $option_name );
}
}

View File

@@ -0,0 +1,281 @@
<?php
// Exit if accessed directly
if( !defined('ABSPATH') ) {
exit;
}
/**
* Helpers functions
*
* @author Alex Kovalev <alex.kovalevv@gmail.com>, Github: https://github.com/alexkovalevv
* @since 1.0.0
* @package clearfy
* @copyright (c) 2018, Webcraftic Ltd
*
*/
class WbcrFactoryClearfy246_Helpers {
/**
* Recursive sanitation for an array
*
* @param $array
*
* @return mixed
* @since 2.0.5
*
*/
public static function recursiveSanitizeArray($array, $function)
{
foreach($array as $key => &$value) {
if( is_array($value) ) {
$value = self::recursiveSanitizeArray($value, $function);
} else {
if( function_exists($function) ) {
$value = $function($value);
}
}
}
return $array;
}
/**
* Is permalink enabled?
*
* @return bool
* @since 1.0.0
* @global WP_Rewrite $wp_rewrite
*/
public static function isPermalink()
{
global $wp_rewrite;
if( !isset($wp_rewrite) || !is_object($wp_rewrite) || !$wp_rewrite->using_permalinks() ) {
return false;
}
return true;
}
/**
* Display 404 page to bump bots and bad guys
*
* @param bool $simple If true force displaying basic 404 page
*/
public static function setError404()
{
global $wp_query;
if( function_exists('status_header') ) {
status_header('404');
nocache_headers();
}
if( $wp_query && is_object($wp_query) ) {
$wp_query->set_404();
get_template_part(404);
} else {
global $pagenow;
$pagenow = 'index.php';
if( !defined('WP_USE_THEMES') ) {
define('WP_USE_THEMES', true);
}
wp();
$_SERVER['REQUEST_URI'] = self::userTrailingslashit('/hmwp_404');
require_once(ABSPATH . WPINC . '/template-loader.php');
}
exit();
}
public static function useTrailingSlashes()
{
return ('/' === substr(get_option('permalink_structure'), -1, 1));
}
public static function userTrailingslashit($string)
{
return self::useTrailingSlashes() ? trailingslashit($string) : untrailingslashit($string);
}
/**
* Returns true if a needle can be found in a haystack
*
* @param string $string
* @param string $find
* @param bool $case_sensitive
*
* @return bool
*/
public static function strContains($string, $find, $case_sensitive = true)
{
if( empty($string) || empty($find) ) {
return false;
}
$pos = $case_sensitive ? strpos($string, $find) : stripos($string, $find);
return !($pos === false);
}
/**
* Tests if a text starts with an given string.
*
* @param string $string
* @param string $find
* @param bool $case_sensitive
*
* @return bool
*/
public static function strStartsWith($string, $find, $case_sensitive = true)
{
if( $case_sensitive ) {
return strpos($string, $find) === 0;
}
return stripos($string, $find) === 0;
}
/**
* Tests if a text ends with an given string.
*
* @param $string
* @param $find
* @param bool $case_sensitive
*
* @return bool
*/
public static function strEndsWith($string, $find, $case_sensitive = true)
{
$expected_position = strlen($string) - strlen($find);
if( $case_sensitive ) {
return strrpos($string, $find, 0) === $expected_position;
}
return strripos($string, $find, 0) === $expected_position;
}
public static function arrayMergeInsert(array $arr, array $inserted, $position = 'bottom', $key = null)
{
if( $position == 'top' ) {
return array_merge($inserted, $arr);
}
$key_position = ($key === null) ? false : array_search($key, array_keys($arr));
if( $key_position === false or ($position != 'before' and $position != 'after') ) {
return array_merge($arr, $inserted);
}
if( $position == 'after' ) {
$key_position++;
}
return array_merge(array_slice($arr, 0, $key_position, true), $inserted, array_slice($arr, $key_position, null, true));
}
public static function maybeGetPostJson($name)
{
if( isset($_POST[$name]) and is_string($_POST[$name]) ) {
$result = json_decode(stripslashes($_POST[$name]), true);
if( !is_array($result) ) {
$result = [];
}
return $result;
} else {
return [];
}
}
public static function getEscapeJson(array $data)
{
return htmlspecialchars(json_encode($data), ENT_QUOTES, 'UTF-8');
}
/**
* Replace url for multisite
*
* @param $string
*
* @return string
*/
public static function replaceMsUrl($string)
{
if( is_multisite() && BLOG_ID_CURRENT_SITE != get_current_blog_id() ) {
return str_replace(get_site_url(BLOG_ID_CURRENT_SITE), get_site_url(get_current_blog_id()), $string);
}
return $string;
}
/*
* Flushes as many page cache plugin's caches as possible.
*
* @return void
*/
public static function flushPageCache()
{
if( function_exists('wp_cache_clear_cache') ) {
if( is_multisite() ) {
$blog_id = get_current_blog_id();
wp_cache_clear_cache($blog_id);
} else {
wp_cache_clear_cache();
}
} else if( has_action('cachify_flush_cache') ) {
do_action('cachify_flush_cache');
} else if( function_exists('w3tc_pgcache_flush') ) {
w3tc_pgcache_flush();
} else if( function_exists('wp_fast_cache_bulk_delete_all') ) {
wp_fast_cache_bulk_delete_all();
} else if( class_exists('WpFastestCache') ) {
$wpfc = new WpFastestCache();
$wpfc->deleteCache();
} else if( class_exists('c_ws_plugin__qcache_purging_routines') ) {
c_ws_plugin__qcache_purging_routines::purge_cache_dir(); // quick cache
} else if( class_exists('zencache') ) {
zencache::clear();
} else if( class_exists('comet_cache') ) {
comet_cache::clear();
} else if( class_exists('WCL_Cache_Helpers') ) {
WCL_Cache_Helpers::deleteCache();
} else if( class_exists('WpeCommon') ) {
// WPEngine cache purge/flush methods to call by default
$wpe_methods = [
'purge_varnish_cache',
];
// More agressive clear/flush/purge behind a filter
if( apply_filters('wbcr/factory/flush_wpengine_aggressive', false) ) {
$wpe_methods = array_merge($wpe_methods, ['purge_memcached', 'clear_maxcdn_cache']);
}
// Filtering the entire list of WpeCommon methods to be called (for advanced usage + easier testing)
$wpe_methods = apply_filters('wbcr/factory/wpengine_methods', $wpe_methods);
foreach($wpe_methods as $wpe_method) {
if( method_exists('WpeCommon', $wpe_method) ) {
WpeCommon::$wpe_method();
}
}
} else if( function_exists('sg_cachepress_purge_cache') ) {
sg_cachepress_purge_cache();
} else if( file_exists(WP_CONTENT_DIR . '/wp-cache-config.php') && function_exists('prune_super_cache') ) {
// fallback for WP-Super-Cache
global $cache_path;
if( is_multisite() ) {
$blog_id = get_current_blog_id();
prune_super_cache(get_supercache_dir($blog_id), true);
prune_super_cache($cache_path . 'blogs/', true);
} else {
prune_super_cache($cache_path . 'supercache/', true);
prune_super_cache($cache_path, true);
}
}
}
}

View File

@@ -0,0 +1,87 @@
<?php
namespace WBCR\Factory_Clearfy_246;
/**
* Class Search options
*
* Allows you to collect all the options from the plugin pages, is a registry of options.
*
* @author Alex Kovlaev <alex.kovalevv@gmail.com>, https://github.com/alexkovalevv
*
* @since 2.2.0
*/
class Search_Options {
private static $_all_options;
/**
* Registers page options in the options registry
*
* This will allow the user to search all the plugin options.
*
* @param array $options
* @param string $page_url
* @param string $page_id
* @since 2.2.0
*
*/
public static function register_options($options, $page_url, $page_id)
{
if( empty($options) || !is_array($options) ) {
return;
}
$extracted_options = static::recursive_extraxt_options($options);
if( !empty($extracted_options) ) {
foreach((array)$extracted_options as $option) {
if( 'div' === $option['type'] || 'html' === $option['type'] || !isset($option['title']) ) {
continue;
}
$formated_option['title'] = $option['title'];
/*if( isset($option['hint']) ) {
$formated_option['hint'] = $option['hint'];
}*/
$formated_option['page_url'] = $page_url . '#factory-control-' . $option['name'];
$formated_option['page_id'] = $page_id;
static::$_all_options[] = $formated_option;
}
}
}
/**
* Extracted options from a nested array
* @param array $options
* @return array
* @since 2.2.0
*/
protected static function recursive_extraxt_options($options)
{
$extracted_options = [];
foreach($options as $option) {
if( isset($option['items']) ) {
$extracted_options = array_merge($extracted_options, static::recursive_extraxt_options($option['items']));
} else {
$extracted_options[] = $option;
}
}
return $extracted_options;
}
/**
* Get all plugin options
* @return mixed
* @since 2.2.0
*/
public static function get_all_options()
{
return static::$_all_options;
}
}

View File

@@ -0,0 +1,307 @@
msgid ""
msgstr ""
"Project-Id-Version: clearfy\n"
"POT-Creation-Date: 2018-10-16 22:37+0300\n"
"PO-Revision-Date: 2018-10-16 22:41+0300\n"
"Last-Translator: alex.kovalevv@gmail.com <alex.kovalevv@gmail.com>\n"
"Language-Team: Alex Kovalev <alex.kovalevv@gmail.com>\n"
"Language: ru_RU\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 2.1.1\n"
"X-Poedit-Basepath: ..\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c\n"
"X-Poedit-SearchPath-0: .\n"
#: includes/check-clearfy-compatibility.php:265
msgid "Clearfy warning"
msgstr "Clearfy предупреждение"
#: includes/check-clearfy-compatibility.php:266
#, php-format
msgid "The %s component"
msgstr "Работа компонента %s"
#: includes/check-clearfy-compatibility.php:268
msgid "warning"
msgstr "предупреждение"
#: includes/check-clearfy-compatibility.php:269
#, php-format
msgid "The %s plugin"
msgstr "Работа плагина %s"
#: includes/check-clearfy-compatibility.php:272
msgid "has stopped."
msgstr "была остановлена."
#: includes/check-clearfy-compatibility.php:273
msgid "Possible reasons:"
msgstr "Возможные причины:"
#: includes/check-clearfy-compatibility.php:279
#, php-format
msgid "You need to update the PHP version to %s or higher!"
msgstr "Вам нужно обновить версию PHP до %s или выше!"
#: includes/check-clearfy-compatibility.php:284
#, php-format
msgid "You need to update WordPress to %s or higher!"
msgstr "Вам нужно обновить WordPress до %s или выше!"
#: includes/check-clearfy-compatibility.php:289
#, php-format
msgid "You need to update the Clearfy plugin version to %s or higher!"
msgstr "Вам нужно обновить версию плагина Clearfy до %s или выше!"
#: includes/check-clearfy-compatibility.php:294
msgid "This plugin is already activated, you are trying to activate it again."
msgstr "Этот плагин уже активирован, вы пытаетесь активировать его снова."
#: includes/check-clearfy-compatibility.php:299
#, php-format
msgid ""
"Clearfy has the features of the %s plugin. Please, deactivate %s to avoid "
"conflicts of plugins!"
msgstr ""
"Плагин Clearfy уже включает в себя функции плагина %s. Пожалуйста, "
"деактивируйте плагин %s, чтобы не создавать конфликтов!"
#: pages/class.pages.php:212
msgid "Upgrade to Clearfy Business"
msgstr "Перейти на Clearfy Бизнес"
#: pages/class.pages.php:213
msgid "Oops... Sorry for the inconvenience caused!"
msgstr "Упс... Мы приносим свои извинения за неудобства!"
#: pages/class.pages.php:214
msgid ""
"Complete multisite support is available in Clearfy Business and Clearfy "
"Business Revolution packages only!"
msgstr ""
"Полная поддержка мультисайтов доступна только в пакете Clearfy Бизнес и "
"Clearfy Бизнес Революция!"
#: pages/class.pages.php:215
msgid ""
"You can activate the plugin on each website and use it with zero "
"limitations. But you cant save the plugins settings under the Super "
"Administrator role!"
msgstr ""
"Вы можете активировать плагин отдельно для каждого сайта и использовать его "
"без ограничений, но в режиме суперадминистратора, вы не можете сохранять "
"настройки плагина!"
#: pages/class.pages.php:217
msgid "Activate license "
msgstr "Активировать лицензию "
#: pages/class.pages.php:218
#, php-format
msgid "Upgrade to Clearfy Business for $%d"
msgstr "Обновить до Clearfy Бизнес за $%d"
#: pages/class.pages.php:273
msgid "MORE IN CLEARFY <span>BUSINESS</span>"
msgstr "ЛУЧШЕЕ В CLEARFY <span>БИЗНЕС</span>"
#: pages/class.pages.php:275
msgid "4 premium components now;"
msgstr "4 премиум компонента сейчас;"
#: pages/class.pages.php:276
msgid "40 new premium components within a year for the single price;"
msgstr "40 новых премиум компонентов в год по одной цене;"
#: pages/class.pages.php:277
msgid "Multisite support;"
msgstr "Поддержка мультисайтов;"
#: pages/class.pages.php:278
msgid "Advanced settings;"
msgstr "Дополнительные настройки;"
#: pages/class.pages.php:279
msgid "No ads;"
msgstr "Нет рекламы;"
#: pages/class.pages.php:280
msgid "Perfect support."
msgstr "Лучшая поддержка."
#: pages/class.pages.php:283
#, php-format
msgid "Upgrade for $%s"
msgstr "Обновиться за $%s"
#: pages/class.pages.php:299
msgid ""
"A neutral setting that can not harm your site, but you must be sure that you "
"need to use it."
msgstr ""
"Нейтральная настройка, которая не может нанести вред вашему сайту, но вы "
"должны быть уверены, что вам нужно ее использовать."
#: pages/class.pages.php:305
msgid ""
"When set this option, you must be careful. Plugins and themes may depend on "
"this function. You must be sure that you can disable this feature for the "
"site."
msgstr ""
"При включении этой настройки, вы должны быть осторожны. Некоторые плагины и "
"темы могут зависеть от этой функции. Вы должны быть уверены, что эту функцию "
"можно отключить для сайта."
#: pages/class.pages.php:311
msgid "Absolutely safe setting, We recommend to use."
msgstr "Абсолютно безопасная настройка, рекомендуем использовать."
#: pages/class.pages.php:316
msgid "Hover to the icon to get help for the feature you selected."
msgstr ""
"Наведите указатель мыши на значок, чтобы получить справку по выбранной "
"функции."
#: pages/class.pages.php:334
msgid "Do you want the plugin to improved and update?"
msgstr "Вы хотите, чтобы плагин улучшался и обновлялся?"
#: pages/class.pages.php:337
msgid ""
"Help the author, leave a review on wordpress.org. Thanks to feedback, I will "
"know that the plugin is really useful to you and is needed."
msgstr ""
"Помогите автору, оставьте отзыв на wordpress.org. Благодаря отзывам, я буду "
"знать, что плагин действительно полезен для вас и необходим."
#: pages/class.pages.php:339
msgid "And also write your ideas on how to extend or improve the plugin."
msgstr "А также напишите свои идеи о том, как расширить или улучшить плагин."
#: pages/class.pages.php:344
msgid "Go rate us and push ideas"
msgstr "Оставить отзыв или поделиться идеей"
#: pages/class.pages.php:356
msgid "Donation for plugin development"
msgstr "Пожертвования на развитие плагина"
#: pages/more-features.php:31
msgid "More features (<b>free</b>)"
msgstr "Дополнительно"
#: pages/more-features.php:40
msgid "install the ultimate version of the plugin for free!"
msgstr "установите полную версию плагина бесплатно!"
#: pages/more-features.php:51
msgid "Code cleaning"
msgstr "Очищает код"
#: pages/more-features.php:53
msgid "Clears the source code of the page from unused code."
msgstr "Очищает исходный код страницы от неиспользуемого кода."
#: pages/more-features.php:60
msgid "Improve SEO"
msgstr "Улучшает SEO"
#: pages/more-features.php:62
msgid ""
"Removes duplicate pages, closes external links, changes the headers of the "
"server."
msgstr ""
"Удаляет дубликаты страниц, закрывает внешние ссылки, изменяет заголовки "
"сервера."
#: pages/more-features.php:69
msgid "Site protection"
msgstr "Защита сайта"
#: pages/more-features.php:71
msgid "Enables and disables features that improve the protection of your site."
msgstr "Включает и отключает функции, которые улучшают защиту вашего сайта."
#: pages/more-features.php:78
msgid "Disable comments"
msgstr "Отключает комментарии"
#: pages/more-features.php:80
msgid "Disables comments on the entire site or on specific pages."
msgstr "Отключает комментарии на всем сайте или у определенных страниц."
#: pages/more-features.php:87
msgid "Manage updates"
msgstr "Менеджер обновлений"
#: pages/more-features.php:89
msgid ""
"Enables or disables automatically updates for plugins, themes and core. It "
"is also possible\n"
"\t\t\t\t\t\t\tto disable all updates."
msgstr ""
"Включает или отключает автоматические обновление плагинов, тем и ядра. Также "
"возможно\n"
"отключение всех обновлений."
#: pages/more-features.php:97
msgid "Manage widgets"
msgstr "Управление виджетами"
#: pages/more-features.php:99
msgid "Allows you to remove unused widgets."
msgstr "Позволяет удалить неиспользуемые виджеты."
#: pages/more-features.php:106
msgid "Speed Optimization"
msgstr "Оптимизация производительности"
#: pages/more-features.php:108
msgid ""
"Increases performance by disabling unused functions and reducing the number "
"of requests."
msgstr ""
"Повышает производительность, отключая неиспользуемые функции и уменьшая "
"количество запросов."
#: pages/more-features.php:115
msgid "Site privacy"
msgstr "Конфиденциальность сайта"
#: pages/more-features.php:117
msgid ""
"Allows you to hide the version of the site and plugins. Allows you to hide "
"your\n"
"\t\t\t\t\t\t\tWordPress."
msgstr ""
"Позволяет скрыть версию сайта и плагинов. Позволяет скрыть ваш\n"
"WordPress."
#: pages/more-features.php:125
msgid "Easy setup"
msgstr "Простая настройка"
#: pages/more-features.php:127
msgid ""
"In quick mode, you can easily configure the plugin according to your needs."
msgstr ""
"В быстром режиме вы можете легко настроить плагин в соответствии с вашими "
"потребностями."
#: pages/more-features.php:142
msgid "Get the ultimate plugin 100% FREE"
msgstr "Получить полную версию бесплатно на 100%."
#~ msgid "component"
#~ msgstr "компонент"
#~ msgid "plugin"
#~ msgstr "плагин"
#~ msgid "Site ptotection"
#~ msgstr "Защищает ваш сайт"

View File

@@ -0,0 +1,418 @@
<?php
// Exit if accessed directly
if( !defined('ABSPATH') ) {
exit;
}
/**
* Class Wbcr_FactoryLicense000_LicensePage is used as template to display form to active premium functionality.
*
* @author Alex Kovalev <alex.kovalevv@gmail.com>, Github: https://github.com/alexkovalevv
* @since 2.0.7
*/
class Wbcr_FactoryClearfy246_LicensePage extends Wbcr_FactoryClearfy246_PageBase {
/**
* {@inheritdoc}
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 2.1.2
* @var string
*/
public $type = "page";
/**
* {@inheritdoc}
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 2.1.2
* @var string
*/
public $page_menu_dashicon = 'dashicons-admin-network';
/**
* {@inheritdoc}
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 2.1.2
* @var bool
*/
public $show_right_sidebar_in_options = false;
/**
* {@inheritdoc}
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 2.1.2
* @var int
*/
public $page_menu_position = 0;
/**
* {@inheritdoc}
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 2.1.2
* @var bool
*/
public $available_for_multisite = true;
/**
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 2.1.2
* @var string
*/
public $plugin_name;
/**
* @var string Name of the paid plan.
*/
public $plan_name;
// PREMIUM SECTION
// ------------------------------------------------------------------
/**
* @since 2.0.7
* @var bool
*/
protected $is_premium;
/**
* @since 2.0.7
* @var \WBCR\Factory_480\Premium\Provider
*/
protected $premium;
/**
* @since 2.0.7
* @var bool
*/
protected $is_premium_active;
/**
* @since 2.0.7
* @var bool
*/
protected $premium_has_subscription;
/**
* @since 2.0.7
* @var \WBCR\Factory_480\Premium\Interfaces\License
*/
protected $premium_license;
// END PREMIUM SECTION
// ------------------------------------------------------------------
/**
* {@inheritdoc}
* @param Wbcr_Factory480_Plugin $plugin
*/
public function __construct(Wbcr_Factory480_Plugin $plugin)
{
$this->plugin = $plugin;
parent::__construct($plugin);
if( !$this->id ) {
$this->id = $this->plugin->getPrefix() . 'license';
}
$this->plugin_name = $this->plugin->getPluginName();
$this->premium = $plugin->premium;
$this->is_premium = $this->premium->is_activate();
$this->is_premium_active = $this->premium->is_active();
$this->premium_has_subscription = $this->premium->has_paid_subscription();
$this->premium_license = $this->premium->get_license();
add_action("wp_ajax_wbcr-clearfy-activate-license-for-{$this->plugin_name}", [$this, 'ajax_handler']);
}
/**
* [MAGIC] Magic method that configures assets for a page.
*/
public function assets($scripts, $styles)
{
parent::assets($scripts, $styles);
$this->styles->add(FACTORY_CLEARFY_246_URL . '/assets/css/license-manager.css');
$this->scripts->add(FACTORY_CLEARFY_246_URL . '/assets/js/clearfy-license-manager.js');
}
/**
* Регистрируем ajax обработчик для текущей страницы
*
* @since 2.0.7
*/
public function ajax_handler()
{
wbcr_factory_clearfy_246_check_license($this->plugin);
}
/**
* {@inheritdoc}
*/
public function showPageContent()
{
?>
<div id="wcl-license-wrapper"
data-loader="<?php echo FACTORY_CLEARFY_246_URL . '/assets/img/loader.gif'; ?>"
data-plugin-name="<?php echo esc_attr($this->plugin_name); ?>"
data-nonce="<?php echo wp_create_nonce("clearfy_activate_license_for_{$this->plugin_name}") ?>">
<?php $this->show_license_form(); ?>
</div>
<?php
}
/**
* Get before content.
*
* @return string Before content.
*/
protected function get_plan_description()
{
return '';
}
/**
* @return string
*/
protected function get_hidden_license_key()
{
if( !$this->is_premium ) {
return '';
}
return $this->premium_license->get_hidden_key();
}
/**
* @return string
*/
protected function get_plan()
{
if( !$this->is_premium ) {
return 'free';
}
return $this->premium->get_plan();
}
/**
* @return mixed
*/
protected function get_expiration_days()
{
if( !$this->is_premium ) {
return '';
}
return $this->premium_license->get_expiration_time('days');
}
/**
* @return string
*/
protected function get_billing_cycle_readable()
{
if( !$this->is_premium ) {
return '';
}
$billing_cycle = $this->premium->get_billing_cycle();
$billing = 'lifetime';
if( 1 == $billing_cycle ) {
$billing = 'month';
} else if( 12 == $billing_cycle ) {
$billing = 'year';
}
return $billing;
}
/**
* Тип лицензии, цветовое оформление для формы лицензирования
* free - бесплатная
* gift - пожизненная лицензия, лицензия на особых условиях
* trial - красный цвет, применяется для триалов, если лиценизия истекла или заблокирована
* paid - обычная оплаченная лицензия, в данный момент активна.
*
* @return string
*/
protected function get_license_type()
{
if( !$this->is_premium ) {
return 'free';
}
$license = $this->premium_license;
if( $license->is_lifetime() ) {
return 'gift';
} else if( $license->get_expiration_time('days') < 1 ) {
return 'trial';
}
return 'paid';
}
protected function render_learnmore_section()
{
if( $this->is_premium ):
?>
<p style="margin-top: 10px;">
<?php printf(__('<a href="%s" target="_blank" rel="noopener">Lean more</a> about the premium version and get the license key to activate it now!', 'wbcr_factory_clearfy_246'), $this->plugin->get_support()->get_pricing_url(true, 'license_page')); ?>
</p>
<?php else: ?>
<p style="margin-top: 10px;">
<?php printf(__('Cant find your key? Go to <a href="%s" target="_blank" rel="noopener">this page</a> and login using the e-mail address associated with your purchase.', 'wbcr_factory_clearfy_246'), $this->plugin->get_support()->get_contacts_url(true, 'license_page')) ?>
</p>
<?php endif;
}
/**
* @param bool|WP_Error $notice
*/
public function show_license_form($notice = false)
{
?>
<div id="license-manager"
class="factory-bootstrap-482 onp-page-wrap <?= $this->get_license_type() ?>-license-manager-content">
<div>
<h3><?php printf(__('Activate %s', 'wbcr_factory_clearfy_246'), $this->plan_name) ?></h3>
<?php echo $this->get_plan_description() ?>
</div>
<br>
<?php if( is_wp_error($notice) ) : ?>
<div class="license-message <?= $this->get_license_type() ?>-license-message">
<div class="alert <?php echo esc_attr($notice->get_error_code()); ?>">
<h4 class="alert-heading"><?php _e($notice->get_error_message(), 'wbcr_factory_clearfy_246') ?></h4>
</div>
</div>
<?php endif; ?>
<div class="onp-container">
<div class="license-details">
<?php if( $this->get_license_type() == 'free' ): ?>
<a href="<?php echo $this->plugin->get_support()->get_pricing_url(true, 'license_page'); ?>"
class="purchase-premium" target="_blank" rel="noopener">
<span class="btn btn-gold btn-inner-wrap">
<?php _e('Upgrade to Premium', 'wbcr_factory_clearfy_246') ?>
</span>
</a>
<p><?php printf(__('Your current license for %1$s:', 'wbcr_factory_clearfy_246'), $this->plugin->getPluginTitle()) ?></p>
<?php endif; ?>
<div class="license-details-block <?= $this->get_license_type() ?>-details-block">
<?php if( $this->is_premium ): ?>
<a data-action="deactivate" href="#"
class="btn btn-default btn-small license-delete-button wcl-control-btn">
<?php _e('Delete Key', 'wbcr_factory_clearfy_246') ?>
</a>
<a data-action="sync" href="#"
class="btn btn-default btn-small license-synchronization-button wcl-control-btn">
<?php _e('Synchronization', 'wbcr_factory_clearfy_246') ?>
</a>
<?php endif; ?>
<h3>
<?php echo ucfirst($this->get_plan()); ?>
<?php if( $this->is_premium && $this->premium_has_subscription ): ?>
<span style="font-size: 15px;">
(<?php printf(__('Automatic renewal, every %s', ''), esc_attr($this->get_billing_cycle_readable())); ?>)
</span>
<?php endif; ?>
</h3>
<?php if( $this->is_premium ): ?>
<div class="license-key-identity">
<code><?= esc_attr($this->get_hidden_license_key()) ?></code>
</div>
<?php endif; ?>
<div class="license-key-description">
<?php if( !$this->is_premium ): ?>
<p><?php _e('Public License is a GPLv3 compatible license allowing you to change and use this version of the plugin for free. Please keep in mind this license covers only free edition of the plugin. Premium versions are distributed with other type of a license.', 'wbcr_factory_clearfy_246') ?></p>
<?php else: ?>
<p><?php _e('Сommercial license, only to the premium add-on to this free plugin. You cannot distribute or modify the premium add-on. But free plugin is a GPLv3 compatible license allowing you to change and use this version of the plugin for free.', 'wbcr_factory_clearfy_246') ?></p>
<?php endif; ?>
<?php if( $this->is_premium && $this->premium_has_subscription ): ?>
<p class="activate-trial-hint">
<?php _e('You use a paid subscription for the plugin updates. In case you dont want to receive paid updates, please, click <a data-action="unsubscribe" class="wcl-control-btn" href="#">cancel subscription</a>', 'wbcr_factory_clearfy_246') ?>
</p>
<?php endif; ?>
<?php if( $this->get_license_type() == 'trial' ): ?>
<p class="activate-error-hint">
<?php printf(__('Your license has expired, please extend the license to get updates and support.', 'wbcr_factory_clearfy_246'), '') ?>
</p>
<?php endif; ?>
</div>
<table class="license-params" colspacing="0" colpadding="0">
<tr>
<!--<td class="license-param license-param-domain">
<span class="license-value"><?php echo esc_attr($_SERVER['SERVER_NAME']); ?></span>
<span class="license-value-name"><?php _e('domain', 'wbcr_factory_clearfy_246') ?></span>
</td>-->
<td class="license-param license-param-days">
<span class="license-value"><?= $this->get_plan() ?></span>
<span class="license-value-name"><?php _e('plan', 'wbcr_factory_clearfy_246') ?></span>
</td>
<?php if( $this->is_premium ) : ?>
<td class="license-param license-param-sites">
<span class="license-value">
<?php echo esc_attr($this->premium_license->get_count_active_sites()); ?>
<?php _e('of', 'wbcr_factory_clearfy_246') ?>
<?php echo esc_attr($this->premium_license->get_sites_quota()); ?></span>
<span class="license-value-name"><?php _e('active sites', 'wbcr_factory_clearfy_246') ?></span>
</td>
<?php endif; ?>
<td class="license-param license-param-version">
<span class="license-value"><?= $this->plugin->getPluginVersion() ?></span>
<span class="license-value-name"><span>version</span></span>
</td>
<?php if( $this->is_premium ): ?>
<td class="license-param license-param-days">
<?php if( $this->get_license_type() == 'trial' ): ?>
<span class="license-value"><?php _e('EXPIRED!', 'wbcr_factory_clearfy_246') ?></span>
<span class="license-value-name"><?php _e('please update the key', 'wbcr_factory_clearfy_246') ?></span>
<?php else: ?>
<span class="license-value">
<?php
if( $this->premium_license->is_lifetime() ) {
echo 'infiniate';
} else {
echo $this->get_expiration_days();
}
?>
<small> <?php _e('day(s)', 'wbcr_factory_clearfy_246') ?></small>
</span>
<span class="license-value-name"><?php _e('remained', 'wbcr_factory_clearfy_246') ?></span>
<?php endif; ?>
</td>
<?php endif; ?>
</tr>
</table>
</div>
</div>
<div class="license-input">
<form action="" method="post">
<?php if($this->is_premium): ?>
<p><?php _e('Have a key to activate the premium version? Paste it here:', 'wbcr_factory_clearfy_246') ?><p>
<?php else: ?>
<p><?php _e('Have a key to activate the plugin? Paste it here:', 'wbcr_factory_clearfy_246') ?>
<p>
<?php endif; ?>
<button data-action="activate" class="btn btn-default wcl-control-btn" type="button"
id="license-submit">
<?php _e('Submit Key', 'wbcr_factory_clearfy_246') ?>
</button>
<div class="license-key-wrap">
<input type="text" id="license-key" name="licensekey" value="" class="form-control"/>
</div>
<?php $this->render_learnmore_section(); ?>
</form>
</div>
</div>
</div>
<?php
}
}

View File

@@ -0,0 +1,170 @@
<?php
/**
* The page Settings.
*
* @author Alex Kovalev <alex.kovalevv@gmail.com>, Github: https://github.com/alexkovalevv
* @since 1.0.1
* @package clearfy
* @copyright (c) 2018, Webcraftic Ltd
*
*/
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class Wbcr_FactoryClearfy246_MoreFeaturesPage extends Wbcr_FactoryPages480_ImpressiveThemplate {
/**
* {@inheritDoc}
*
* @var string
*/
public $id = "more_features";
/**
* {@inheritDoc}
*
* @var string
*/
public $page_menu_dashicon = 'dashicons-star-filled wbcr-factory-orange-color';
/**
* {@inheritDoc}
*
* @var string
*/
public $page_menu_position = 5;
/**
* {@inheritDoc}
*
* @var string
*/
public $type = 'page';
/**
* {@inheritDoc}
*
* @var bool
*/
public $available_for_multisite = true;
/**
* {@inheritDoc}
*
* @since 2.0.6 - добавлен
* @var bool
*/
public $internal = true;
public function __construct( Wbcr_Factory480_Plugin $plugin ) {
$this->menu_title = __( 'More features (<b>free</b>)', 'wbcr_factory_clearfy_246' );
parent::__construct( $plugin );
$this->plugin = $plugin;
}
/**
* {@inheritDoc}
*
* @return string
*/
public function getPageTitle() {
return __( 'More features', 'wbcr_factory_clearfy_246' );
}
/**
* {@inheritDoc}
*
* @return void
*/
public function showPageContent() {
?>
<div class="row">
<div class="col-sm-4">
<div class="wbcr-factory-feature-box">
<span class="dashicons dashicons-yes"></span>
<h3><?php _e( 'Code cleaning', 'wbcr_factory_clearfy_246' ) ?></h3>
<p><?php _e( 'Clears the source code of the page from unused code.', 'wbcr_factory_clearfy_246' ) ?></p>
</div>
</div>
<div class="col-sm-4">
<div class="wbcr-factory-feature-box">
<span class="dashicons dashicons-chart-bar"></span>
<h3><?php _e( 'Improve SEO', 'wbcr_factory_clearfy_246' ) ?></h3>
<p><?php _e( 'Removes duplicate pages, closes external links, changes the headers of the server.', 'wbcr_factory_clearfy_246' ) ?></p>
</div>
</div>
<div class="col-sm-4">
<div class="wbcr-factory-feature-box">
<span class="dashicons dashicons-shield-alt"></span>
<h3><?php _e( 'Site protection', 'wbcr_factory_clearfy_246' ) ?></h3>
<p><?php _e( 'Enables and disables features that improve the protection of your site.', 'wbcr_factory_clearfy_246' ) ?></p>
</div>
</div>
<div class="col-sm-4">
<div class="wbcr-factory-feature-box">
<span class="dashicons dashicons-welcome-comments"></span>
<h3><?php _e( 'Disable comments', 'wbcr_factory_clearfy_246' ) ?></h3>
<p><?php _e( 'Disables comments on the entire site or on specific pages.', 'wbcr_factory_clearfy_246' ) ?></p>
</div>
</div>
<div class="col-sm-4">
<div class="wbcr-factory-feature-box">
<span class="dashicons dashicons-update"></span>
<h3><?php _e( 'Manage updates', 'wbcr_factory_clearfy_246' ) ?></h3>
<p><?php _e( 'Enables or disables automatically updates for plugins, themes and core. It is also possible
to disable all updates.', 'wbcr_factory_clearfy_246' ) ?></p>
</div>
</div>
<div class="col-sm-4">
<div class="wbcr-factory-feature-box">
<span class="dashicons dashicons-admin-plugins"></span>
<h3><?php _e( 'Manage widgets', 'wbcr_factory_clearfy_246' ) ?></h3>
<p><?php _e( 'Allows you to remove unused widgets.', 'wbcr_factory_clearfy_246' ) ?></p>
</div>
</div>
<div class="col-sm-4">
<div class="wbcr-factory-feature-box">
<span class="dashicons dashicons-dashboard"></span>
<h3><?php _e( 'Speed Optimization', 'wbcr_factory_clearfy_246' ) ?></h3>
<p><?php _e( 'Increases performance by disabling unused functions and reducing the number of requests.', 'wbcr_factory_clearfy_246' ) ?></p>
</div>
</div>
<div class="col-sm-4">
<div class="wbcr-factory-feature-box">
<span class="dashicons dashicons-visibility"></span>
<h3><?php _e( 'Site privacy', 'wbcr_factory_clearfy_246' ) ?></h3>
<p><?php _e( 'Allows you to hide the version of the site and plugins. Allows you to hide your
WordPress.', 'wbcr_factory_clearfy_246' ) ?></p>
</div>
</div>
<div class="col-sm-4">
<div class="wbcr-factory-feature-box">
<span class="dashicons dashicons-admin-settings"></span>
<h3><?php _e( 'Easy setup', 'wbcr_factory_clearfy_246' ) ?></h3>
<p><?php _e( 'In quick mode, you can easily configure the plugin according to your needs.', 'wbcr_factory_clearfy_246' ) ?></p>
</div>
</div>
</div>
<div class="wbcr-factory-buttons-wrap">
<?php
$url = 'https://clearfy.pro';
if ( get_locale() == 'ru_RU' ) {
$url = 'https://ru.clearfy.pro';
}
$url .= '?utm_source=wordpress.org&utm_campaign=' . $this->plugin->getPluginName();
?>
<a href="<?= $url ?>" class="wbcr-factory-premium-button" target="_blank">
<?php _e( 'Get the ultimate plugin 100% FREE', 'wbcr_factory_clearfy_246' ) ?>
</a>
</div>
<?php
}
}

View File

@@ -0,0 +1,185 @@
<?php
namespace WBCR\FactoryClearfy246\Pages;
// Exit if accessed directly
if( !defined('ABSPATH') ) {
exit;
}
/**
* Класс страницы, которая реализует функции мастера установки.
*
* Этот класс унаследован от стандартного шаблона страницы \Wbcr_FactoryPages480_ImpressiveThemplate,
* поэтому все его инструменты могут быть применены и в этом классе. Но вы должны учитывать, что
* поведение экшенов страницы было изменено. В данной реализации экшены используется для пагинации шагов.
*
* @package WBCR\FactoryClearfy246\Pages
* @author Alex Kovalev <alex.kovalevv@gmail.com>, Github: https://github.com/alexkovalevv
* @since 2.2.2
*/
class Setup extends \Wbcr_FactoryPages480_ImpressiveThemplate {
const DEFAULT_STEP = 'step0';
/**
* @var string
*/
public $type = 'page';
/**
* {@inheritDoc}
*
* @since 2.2.2 - добавлен
* @var bool
*/
public $page_parent_page = 'none';
/**
* @var string
*/
public $menu_target = 'options-general.php';
/**
* {@inheritDoc}
*
* @since 2.2.2 - добавлен
* @var bool
*/
public $show_right_sidebar_in_options = false;
/**
* {@inheritDoc}
*
* @since 2.2.2 - добавлен
* @var bool
*/
public $available_for_multisite = false;
/**
* {@inheritDoc}
*
* @since 2.2.2 - добавлен
* @var bool
*/
public $internal = true;
private $current_step = 'step0';
private $steps = [];
/**
* @param \Wbcr_Factory480_Plugin $plugin
*/
public function __construct(\Wbcr_Factory480_Plugin $plugin)
{
$this->id = 'setup';
$this->menu_title = __('Setup master', 'wbcr_factory_clearfy_246');
$this->page_menu_short_description = __('Setup master', 'wbcr_factory_clearfy_246');
parent::__construct($plugin);
}
public function getPageTitle()
{
return __('Setup', 'wbcr_factory_clearfy_246');
}
public function get_close_wizard_url()
{
return $this->plugin->getPluginPageUrl('quick_start');
}
/**
* Поведение экшенов страницы было изменено. В данной реализации экшены используется для пагинации шагов.
*
* @param string $action
*
* @throws \Exception
*/
public function executeByName($action)
{
$step = self::DEFAULT_STEP;
if( false !== strpos($action, 'step') && isset($this->steps[$action]) ) {
$step = $this->current_step = $action;
}
ob_start();
$this->steps[$step]->html();
$step_content = ob_get_clean();
$this->showPage($step_content);
}
/**
* Регистрируем класс обработчик шага
*
* Класс обработчик полностью отвечает за шаблон и функционально шага.
*
* @param string $path
* @param string $class_name
* @throws \Exception
*/
protected function register_step($path, $class_name)
{
require_once $path;
if( !class_exists($class_name) ) {
throw new \Exception("Class {$class_name} is not found!");
}
$step = new $class_name($this);
$this->steps[$step->get_id()] = $step;
}
/**
* Requests assets (js and css) for the page.
*
* @param \Wbcr_Factory480_ScriptList $scripts
* @param \Wbcr_Factory480_StyleList $styles
*
* @return void
* @see Wbcr_FactoryPages480_AdminPage
*
*/
public function assets($scripts, $styles)
{
parent::assets($scripts, $styles);
$this->styles->add(FACTORY_CLEARFY_246_URL . '/assets/css/page-setup.css');
// Require step assets
if( isset($_GET['action']) && false !== strpos($_GET['action'], 'step') && isset($this->steps[$_GET['action']]) ) {
$this->steps[$_GET['action']]->assets($scripts, $styles);
}
}
/**
* {@inheritDoc}
*
* @param string $content
* @since 2.2.2 - добавлен
*/
protected function showPage($content = null)
{
?>
<div class="w-factory-clearfy-246-setup">
<ol class="w-factory-clearfy-246-setup-steps">
<?php foreach($this->steps as $step): ?>
<?php if( self::DEFAULT_STEP === $step->get_id() ) {
continue;
} ?>
<li <?php if($this->current_step === $step->get_id()): ?>class="active"<?php endif; ?>><?php echo $step->get_title(); ?></li>
<?php endforeach; ?>
</ol>
<div class="w-factory-clearfy-246-setup-content">
<?php echo $content; ?>
</div>
<a class="w-factory-clearfy-246-setup-footer-links" href="<?php echo esc_url($this->get_close_wizard_url()); ?>">
<?php _e('Not now', 'wbcr_factory_clearfy_246') ?>
</a>
</div>
<?php
}
}
/*@mix:place*/

View File

@@ -0,0 +1,249 @@
<?php
namespace WBCR\FactoryClearfy246\Pages;
/**
* This file is the add-ons page.
*
* @author Alex Kovalev <alex@byonepress.com>
* @since 1.0.0
* @copyright (c) 2017, OnePress Ltd
*
*/
// Exit if accessed directly
if( !defined('ABSPATH') ) {
exit;
}
class Components extends \Wbcr_FactoryClearfy246_PageBase {
/**
* The id of the page in the admin menu.
*
* Mainly used to navigate between pages.
*
* @since 1.0.0
* @see FactoryPages480_AdminPage
*
* @var string
*/
public $id = "components";
public $page_menu_position = 0;
public $page_menu_dashicon = 'dashicons-admin-plugins';
public $type = 'page';
public $show_right_sidebar_in_options = false;
public $available_for_multisite = true;
/**
* @param \Wbcr_Factory480_Plugin $plugin
*/
public function __construct(\Wbcr_Factory480_Plugin $plugin)
{
$this->menu_title = __('Components', 'wbcr_factory_clearfy_246');
$this->page_menu_short_description = __('More features for plugin', 'wbcr_factory_clearfy_246');
parent::__construct($plugin);
$this->plugin = $plugin;
}
/**
* Requests assets (js and css) for the page.
*
* @return void
* @since 1.0.0
* @see FactoryPages480_AdminPage
*
*/
public function assets($scripts, $styles)
{
parent::assets($scripts, $styles);
$this->styles->add(FACTORY_CLEARFY_246_URL . '/assets/css/components.css');
/**
* @param \Wbcr_Factory480_StyleList $styles
* @param \Wbcr_Factory480_ScriptList $scripts
* @since 1.4.0
*
*/
do_action('wbcr/clearfy/components/page_assets', $scripts, $styles);
}
/**
* We register notifications for some actions
*
* @param $notices
* @param \Wbcr_Factory480_Plugin $plugin
*
* @return array
* @see libs\factory\pages\themplates\FactoryPages480_ImpressiveThemplate
*/
public function getActionNotices($notices)
{
$notices[] = [
'conditions' => [
'wbcr-force-update-components-success' => 1
],
'type' => 'success',
'message' => __('Components have been successfully updated to the latest version.', 'wbcr_factory_clearfy_246')
];
$notices[] = [
'conditions' => [
'wbcr-force-update-components-error' => 'inactive_licence'
],
'type' => 'danger',
'message' => __('To use premium components, you need activate a license!', 'wbcr_factory_clearfy_246') . '<a href="admin.php?page=license-wbcr_clearfy" class="btn btn-gold">' . __('Activate license', 'wbcr_factory_clearfy_246') . '</a>'
];
$notices[] = [
'conditions' => [
'wbcr-force-update-components-error' => 'unknown_error'
],
'type' => 'danger',
'message' => __('An unknown error occurred while updating plugin components. Please contact the plugin support team to resolve this issue.', 'hide_my_wp')
];
return $notices;
}
public function get_components()
{
return [];
}
/**
* This method simply sorts the list of components.
*
* @param $components
*
* @return array
*/
public function order($components)
{
$deactivate_components = $this->plugin->getPopulateOption('deactive_preinstall_components', []);
$ordered_components = [
'premium_active' => [],
'premium_deactive' => [],
'other' => []
];
foreach((array)$components as $component) {
if( ('premium' === $component['build'] || 'freemium' === $component['build']) && 'internal' === $component['type'] ) {
if( in_array($component['name'], $deactivate_components) ) {
// free component is deactivated
$order_key = 'premium_deactive';
} else {
// free component activated
$order_key = 'premium_active';
}
} else {
$order_key = 'other';
}
$ordered_components[$order_key][] = $component;
}
return array_merge($ordered_components['premium_active'], $ordered_components['premium_deactive'], $ordered_components['other']);
}
/**
* This method simply show contents of the component page.
*
* @throws \Exception
*/
public function showPageContent()
{
$components = $this->order($this->get_components());
/**
* @param array $components
* @since 1.4.0
*
*/
$components = apply_filters('wbcr/clearfy/components/items_list', $components);
?>
<div class="wbcr-factory-page-group-header"><?php _e('<strong>Plugin Components</strong>.', 'wbcr_factory_clearfy_246') ?>
<p>
<?php _e('These are components of the plugin bundle. When you activate the plugin, all the components turned on by default. If you dont need some function, you can easily turn it off on this page.', 'wbcr_factory_clearfy_246') ?>
</p>
</div>
<div class="wbc-factory-clearfy-246-components">
<?php
/**
* @since 1.4.0
*/
do_action('wbcr/clearfy/components/custom_plugins_card', $components);
?>
<?php foreach((array)$components as $component): ?>
<?php
$slug = $component['name'];
if( $component['type'] == 'wordpress' || $component['type'] == 'creativemotion' ) {
$slug = $component['base_path'];
}
$install_button = $this->plugin->get_install_component_button($component['type'], $slug);
$status_class = '';
if( !$install_button->is_plugin_activate() ) {
$status_class = ' plugin-status-deactive';
}
$install_button->add_class('install-now');
// Delete button
$delete_button = $this->plugin->get_delete_component_button($component['type'], $slug);
$delete_button->add_class('delete-now');
?>
<div class="plugin-card<?php echo esc_attr($status_class) ?>">
<?php if( isset($component['build']) ): ?>
<div class="plugin-card-<?php echo esc_attr($component['build']) ?>-ribbon"><?php echo ucfirst(esc_html($component['build'])) ?></div>
<?php endif; ?>
<div class="plugin-card-top">
<div class="name column-name">
<h3>
<a href="<?php echo esc_url($component['url']) ?>" class="thickbox open-plugin-details-modal">
<?php echo esc_html($component['title']) ?>
<img src="<?php echo esc_attr($component['icon']) ?>" class="plugin-icon" alt="<?php echo esc_attr($component['title']) ?>">
</a>
</h3>
</div>
<div class="desc column-description">
<p><?php echo esc_html($component['description']); ?></p>
</div>
</div>
<div class="plugin-card-bottom">
<?php if( !(isset($component['disable_button']) && $component['disable_button']) ): ?>
<?php if( 'premium' === $component['build'] && !($this->plugin->premium->is_activate() && $this->plugin->premium->is_install_package()) ): ?>
<a target="_blank" href="<?php echo esc_url($component['url']) ?>" class="button button-default install-now"><?php _e('Read more', 'wbcr_factory_clearfy_246'); ?></a>
<?php else: ?>
<?php $delete_button->render_button(); ?><?php $install_button->render_button(); ?>
<?php endif; ?>
<?php else: ?>
<?php echo(isset($component['disable_button_reason']) ? esc_html($component['disable_button_reason']) : ''); ?>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
<div class="clearfix"></div>
</div>
<?php
}
}

View File

@@ -0,0 +1,558 @@
<?php
/**
* Общий класс прослойка для страниц Clearfy и его компоннетов.
* В этом классе добавляются общие ресурсы и элементы, необходимые для всех связанных плагинов.
*
* @author Alex Kovalev <alex.kovalevv@gmail.com>, Github: https://github.com/alexkovalevv
* @since 2.0.5
*/
// Exit if accessed directly
if( !defined('ABSPATH') ) {
exit;
}
//global $ssssdfsfsdf;
/**
* Class Wbcr_FactoryPages480_ImpressiveThemplate
*
* @method string getInfoWidget() - get widget content information
* @method string getRatingWidget(array $args = []) - get widget content rating
* @method string getDonateWidget() - get widget content donate
* @method string getSubscribeWidget()
* @method string getBusinessSuggetionWidget()
* @method string getSupportWidget
*/
class Wbcr_FactoryClearfy246_PageBase extends Wbcr_FactoryPages480_ImpressiveThemplate {
/**
* {@inheritDoc}
*
* @since 2.0.5 - добавлен
* @var bool
*/
public $show_right_sidebar_in_options = true;
/**
* {@inheritDoc}
*
* @since 2.0.5 - добавлен
* @var bool
*/
public $available_for_multisite = true;
/**
* {@inheritDoc}
*
* @since 2.0.6 - добавлен
* @var bool
*/
public $internal = true;
/**
* Show on the page a search form for search options of plugin?
*
* @since 2.2.0 - Added
* @var bool - true show, false hide
*/
public $show_search_options_form;
/**
* @param Wbcr_Factory480_Plugin $plugin
*/
public function __construct(Wbcr_Factory480_Plugin $plugin)
{
parent::__construct($plugin);
if( is_null($this->show_search_options_form) ) {
$this->show_search_options_form = false;
if( "options" === $this->type ) {
$this->show_search_options_form = true;
}
}
if( "options" === $this->type && "hide_my_wp" !== $this->id ) {
$this->register_options_to_search();
}
add_action("wp_ajax_wbcr-clearfy-subscribe-for-{$this->plugin->getPluginName()}", [
$this,
'subsribe_widget_ajax_handler'
]);
}
/**
* @param $name
* @param $arguments
*
* @return null|string
*/
public function __call($name, $arguments)
{
if( substr($name, 0, 3) == 'get' ) {
$called_method_name = 'show' . substr($name, 3);
if( method_exists($this, $called_method_name) ) {
ob_start();
$this->$called_method_name($arguments);
$content = ob_get_contents();
ob_end_clean();
return $content;
}
}
return null;
}
/**
* Requests assets (js and css) for the page.
*
* @param Wbcr_Factory480_ScriptList $scripts
* @param Wbcr_Factory480_StyleList $styles
*
* @return void
* @see Wbcr_FactoryPages480_AdminPage
*
*/
public function assets($scripts, $styles)
{
parent::assets($scripts, $styles);
$this->styles->add(FACTORY_CLEARFY_246_URL . '/assets/css/clearfy-base.css');
// todo: вынести все общие скрипты и стили фреймворка, продумать совместимость с другими плагинами
if( defined('WCL_PLUGIN_URL') ) {
$this->styles->add(WCL_PLUGIN_URL . '/admin/assets/css/general.css');
}
if( !($this->plugin->has_premium() && $this->plugin->premium->is_active()) ) {
$this->scripts->add(FACTORY_CLEARFY_246_URL . '/assets/js/clearfy-widgets.js', [
'jquery',
'wfactory-480-core-general',
'wbcr-factory-clearfy-246-global'
], 'wbcr-factory-clearfy-246-widgets');
}
// Script for search form on plugin options
if( $this->show_search_options_form ) {
$this->styles->add(FACTORY_CLEARFY_246_URL . '/assets/css/libs/autocomplete.css');
$this->scripts->add(FACTORY_CLEARFY_246_URL . '/assets/js/libs/jquery.autocomplete.min.js');
$this->scripts->add(FACTORY_CLEARFY_246_URL . '/assets/js/clearfy-search-options.js');
}
/**
* Allows you to enqueue scripts to the internal pages of the plugin.
* $this->getResultId() - page id + plugin name = quick_start-wbcr_clearfy
*
* @since 2.0.5
*/
do_action('wbcr/clearfy/page_assets', $this->getResultId(), $scripts, $styles);
}
/**
* Регистрируем ajax обработчик для текущей страницы
*
* @since 2.0.7
*/
public function subsribe_widget_ajax_handler()
{
wbcr_factory_clearfy_246_subscribe($this->plugin);
}
/**
* @return Wbcr_Factory480_Request
*/
public function request()
{
return $this->plugin->request;
}
/**
* @param $option_name
* @param bool $default *
*
* @return mixed|void
* @since 2.0.5
*
*/
public function getPopulateOption($option_name, $default = false)
{
return $this->plugin->getPopulateOption($option_name, $default);
}
/**
* @param $option_name
* @param bool $default
*
* @return mixed|void
*/
public function getOption($option_name, $default = false)
{
return $this->plugin->getOption($option_name, $default);
}
/**
* @param $option_name
* @param $value
*
* @return void
*/
public function updatePopulateOption($option_name, $value)
{
$this->plugin->updatePopulateOption($option_name, $value);
}
/**
* @param $option_name
* @param $value
*
* @return void
*/
public function updateOption($option_name, $value)
{
$this->plugin->updateOption($option_name, $value);
}
/**
* @param $option_name
*
* @return void
*/
public function deletePopulateOption($option_name)
{
$this->plugin->deletePopulateOption($option_name);
}
/**
* @param $option_name
*
* @return void
*/
public function deleteOption($option_name)
{
$this->plugin->deleteOption($option_name);
}
/**
* @param string $position
*
* @return mixed|void
*/
protected function getPageWidgets($position = 'bottom')
{
$widgets = [];
if( $position == 'bottom' ) {
$widgets['info_widget'] = $this->getInfoWidget();
$widgets['rating_widget'] = $this->getRatingWidget();
$widgets['support_widget'] = $this->getSupportWidget();
//$widgets['donate_widget'] = $this->getDonateWidget();
} else if( $position == 'right' && !($this->plugin->has_premium() && $this->plugin->premium->is_activate()) ) {
$widgets['business_suggetion'] = $this->getBusinessSuggetionWidget();
if( $this->plugin->getPluginInfoAttr('subscribe_widget') && !$this->plugin->getPopulateOption('factory_clearfy_user_subsribed') ) {
$widgets['subscribe'] = $this->getSubscribeWidget();
}
$widgets['info_widget'] = $this->getInfoWidget();
$widgets['rating_widget'] = $this->getRatingWidget();
}
/**
* @since 4.0.9 - является устаревшим
*/
$widgets = wbcr_factory_480_apply_filters_deprecated('wbcr_factory_pages_480_imppage_get_widgets', [
$widgets,
$position,
$this->plugin,
$this
], '4.0.9', 'wbcr/factory/pages/impressive/widgets');
/**
* @since 4.0.1 - добавлен
* @since 4.0.9 - изменено имя
*/
$widgets = apply_filters('wbcr/factory/pages/impressive/widgets', $widgets, $position, $this->plugin, $this);
return $widgets;
}
/**
* Создает Html разметку виджета для рекламы премиум версии
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 2.0.2
*/
public function showBusinessSuggetionWidget()
{
$plugin_name = $this->plugin->getPluginName();
$upgrade_price = $this->plugin->has_premium() ? $this->plugin->premium->get_price() : 0;
$purchase_url = $this->plugin->get_support()->get_pricing_url(true, 'right_sidebar_ads');
$default_features = [
'4_premium' => __('4 premium components now;', 'wbcr_factory_clearfy_246'),
'40_premium' => __('40 new premium components within a year for the single price;', 'wbcr_factory_clearfy_246'),
'multisite_support' => __('Multisite support;', 'wbcr_factory_clearfy_246'),
'advance_settings' => __('Advanced settings;', 'wbcr_factory_clearfy_246'),
'no_ads' => __('No ads;', 'wbcr_factory_clearfy_246'),
'perfect_support' => __('Perfect support.', 'wbcr_factory_clearfy_246')
];
/**
* @since 2.0.8 - added
*/
$suggetion_title = __('MORE IN CLEARFY <span>BUSINESS</span>', 'wbcr_factory_clearfy_246');
$suggetion_title = apply_filters('wbcr/clearfy/pages/suggetion_title', $suggetion_title, $plugin_name, $this->id);
/**
* @since 2.0.8 - deprecated
*/
$suggetion_features = wbcr_factory_480_apply_filters_deprecated('wbcr/clearfy/page_bussines_suggetion_features', [
$default_features,
$this->plugin->getPluginName(),
$this->id
], '2.0.8', 'wbcr/clearfy/pages/suggetion_features');
/**
* @since 2.0.8 - renamed
* @since 2.0.6
*/
$suggetion_features = apply_filters('wbcr/clearfy/pages/suggetion_features', $suggetion_features, $plugin_name, $this->id);
if( empty($suggetion_features) ) {
$suggetion_features = $default_features;
}
?>
<div class="wbcr-factory-sidebar-widget wbcr-factory-clearfy-246-pro-suggettion">
<h3><?php echo $suggetion_title; ?></h3>
<ul>
<?php if( !empty($suggetion_features) ): ?>
<?php foreach($suggetion_features as $feature): ?>
<li><?php echo $feature; ?></li>
<?php endforeach; ?>
<?php endif; ?>
</ul>
<a href="<?php echo $purchase_url ?>" class="wbcr-factory-purchase-premium" target="_blank"
rel="noopener">
<?php printf(__('Upgrade for $%s', 'wbcr_factory_clearfy_246'), $upgrade_price) ?>
</a>
</div>
<?php
}
/**
* Создает html разметку виджета с информационными маркерами
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 2.0.0
*/
public function showInfoWidget()
{
?>
<div class="wbcr-factory-sidebar-widget">
<ul>
<li>
<span class="wbcr-factory-hint-icon-simple wbcr-factory-simple-red">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAQAAABKmM6bAAAAUUlEQVQIHU3BsQ1AQABA0X/komIrnQHYwyhqQ1hBo9KZRKL9CBfeAwy2ri42JA4mPQ9rJ6OVt0BisFM3Po7qbEliru7m/FkY+TN64ZVxEzh4ndrMN7+Z+jXCAAAAAElFTkSuQmCC"
alt=""/>
</span>
- <?php _e('A neutral setting that can not harm your site, but you must be sure that you need to use it.', 'wbcr_factory_clearfy_246'); ?>
</li>
<li>
<span class="wbcr-factory-hint-icon-simple wbcr-factory-simple-grey">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAQAAABKmM6bAAAAUUlEQVQIHU3BsQ1AQABA0X/komIrnQHYwyhqQ1hBo9KZRKL9CBfeAwy2ri42JA4mPQ9rJ6OVt0BisFM3Po7qbEliru7m/FkY+TN64ZVxEzh4ndrMN7+Z+jXCAAAAAElFTkSuQmCC"
alt=""/>
</span>
- <?php _e('When set this option, you must be careful. Plugins and themes may depend on this function. You must be sure that you can disable this feature for the site.', 'wbcr_factory_clearfy_246'); ?>
</li>
<li>
<span class="wbcr-factory-hint-icon-simple wbcr-factory-simple-green">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAQAAABKmM6bAAAAUUlEQVQIHU3BsQ1AQABA0X/komIrnQHYwyhqQ1hBo9KZRKL9CBfeAwy2ri42JA4mPQ9rJ6OVt0BisFM3Po7qbEliru7m/FkY+TN64ZVxEzh4ndrMN7+Z+jXCAAAAAElFTkSuQmCC"
alt=""/>
</span>
- <?php _e('Absolutely safe setting, We recommend to use.', 'wbcr_factory_clearfy_246'); ?>
</li>
</ul>
----------<br>
<p><?php _e('Hover to the icon to get help for the feature you selected.', 'wbcr_factory_clearfy_246'); ?></p>
</div>
<?php
}
/**
* Создает html разметку виджета рейтинга
*
* @param array $args
*
* @since 2.0.0
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
*/
public function showRatingWidget(array $args)
{
if( !isset($args[0]) || empty($args[0]) ) {
$page_url = "https://wordpress.org/support/plugin/clearfy/reviews";
} else {
$page_url = $args[0];
}
$page_url = apply_filters('wbcr_factory_pages_480_imppage_rating_widget_url', $page_url, $this->plugin->getPluginName(), $this->getResultId());
?>
<div class="wbcr-factory-sidebar-widget">
<p>
<strong><?php _e('Do you want the plugin to improved and update?', 'wbcr_factory_clearfy_246'); ?></strong>
</p>
<p><?php _e('Help the author, leave a review on wordpress.org. Thanks to feedback, I will know that the plugin is really useful to you and is needed.', 'wbcr_factory_clearfy_246'); ?></p>
<p><?php _e('And also write your ideas on how to extend or improve the plugin.', 'wbcr_factory_clearfy_246'); ?></p>
<p>
<i class="wbcr-factory-icon-5stars"></i>
<a href="<?php echo $page_url; ?>" title="Go rate us" target="_blank">
<strong><?php _e('Go rate us and push ideas', 'wbcr_factory_clearfy_246'); ?></strong>
</a>
</p>
</div>
<?php
}
/**
* Создает html размету виджета доната
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 2.0.0
*/
public function showDonateWidget()
{
?>
<div class="wbcr-factory-sidebar-widget">
<p>
<strong><?php _e('Donation for plugin development', 'wbcr_factory_clearfy_246'); ?></strong>
</p>
<?php if( get_locale() !== 'ru_RU' ): ?>
<form id="wbcr-factory-paypal-donation-form" action="https://www.paypal.com/cgi-bin/webscr"
method="post" target="_blank">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="hosted_button_id" value="VDX7JNTQPNPFW">
<div class="wbcr-factory-donation-price">5$</div>
<input type="image" src="<?php echo FACTORY_PAGES_480_URL ?>/templates/assets/img/paypal-donate.png"
border="0" name="submit" alt="PayPal The safer, easier way to pay online!">
</form>
<?php else: ?>
<iframe frameborder="0" allowtransparency="true" scrolling="no"
src="https://money.yandex.ru/embed/donate.xml?account=410011242846510&quickpay=donate&payment-type-choice=on&mobile-payment-type-choice=on&default-sum=300&targets=%D0%9D%D0%B0+%D0%BF%D0%BE%D0%B4%D0%B4%D0%B5%D1%80%D0%B6%D0%BA%D1%83+%D0%BF%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D0%B0+%D0%B8+%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D1%83+%D0%BD%D0%BE%D0%B2%D1%8B%D1%85+%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B9.+&target-visibility=on&project-name=Webcraftic&project-site=&button-text=05&comment=on&hint=%D0%9A%D0%B0%D0%BA%D1%83%D1%8E+%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8E+%D0%BD%D1%83%D0%B6%D0%BD%D0%BE+%D0%B4%D0%BE%D0%B1%D0%B0%D0%B2%D0%B8%D1%82%D1%8C+%D0%B2+%D0%BF%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%3F&mail=on&successURL="
width="508" height="187"></iframe>
<?php endif; ?>
</div>
<?php
}
/**
* Создает html разметку виджета поддержки
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 2.0.8
*/
public function showSupportWidget()
{
$free_support_url = $this->plugin->get_support()->get_contacts_url();
$hot_support_url = $this->plugin->get_support()->get_site_url() . '/other-questions-support';
?>
<div id="wbcr-clr-support-widget" class="wbcr-factory-sidebar-widget">
<p><strong><?php _e('Having Issues?', 'wbcr_factory_clearfy_246'); ?></strong></p>
<div class="wbcr-clr-support-widget-body">
<p>
<?php _e('We provide free support for this plugin. If you are pushed with a problem, just create a new ticket. We will definitely help you!', 'wbcr_factory_clearfy_246'); ?>
</p>
<ul>
<li><span class="dashicons dashicons-sos"></span>
<a href="<?php echo $free_support_url; ?>" target="_blank"
rel="noopener"><?php _e('Get starting free support', 'wbcr_factory_clearfy_246'); ?></a>
</li>
<li style="margin-top: 15px;background: #fff4f1;padding: 10px;color: #a58074;">
<span class="dashicons dashicons-warning"></span>
<?php printf(__('If you find a php error or a vulnerability in plugin, you can <a href="%s" target="_blank" rel="noopener">create ticket</a> in hot support that we responded instantly.', 'wbcr_factory_clearfy_246'), $hot_support_url); ?>
</li>
</ul>
</div>
</div>
<?php
}
public function showSubscribeWidget()
{
$widget_settings = $this->plugin->getPluginInfoAttr('subscribe_settings');
$group_id = isset($widget_settings['group_id']) ? $widget_settings['group_id'] : 0;
$terms = "https://themeisle.com/privacy-policy/";
?>
<div id="wbcr-clr-subscribe-widget" class="wbcr-factory-sidebar-widget wbcr-factory-subscribe-widget">
<p><strong><?php _e('Subscribe to plugins newsletter', 'wbcr_factory_clearfy_246'); ?></strong></p>
<div class="wbcr-clr-subscribe-widget-body">
<div class="wbcr-factory-subscribe-widget__message-contanier">
<div class="wbcr-factory-subscribe-widget__text wbcr-factory-subscribe-widget__text--success">
<?php _e("Thank you, you have successfully subscribed!", 'wbcr_factory_clearfy_246') ?>
</div>
<div class="wbcr-factory-subscribe-widget__text wbcr-factory-subscribe-widget__text--success2">
<?php _e("Thank you for your subscription.", 'wbcr_factory_clearfy_246'); ?>
</div>
</div>
<form id="wbcr-factory-subscribe-widget__subscribe-form" method="post" data-nonce="<?php echo wp_create_nonce('clearfy_subscribe_for_' . $this->plugin->getPluginName()) ?>">
<input id="wbcr-factory-subscribe-widget__email" class="wbcr-factory-subscribe-widget__field" type="email" name="email" placeholder="<?php _e('Enter your email address', 'wbcr_factory_clearfy_246'); ?>" required>
<label class="wbcr-factory-subscribe-widget__checkbox-label">
<input class="wbcr-factory-subscribe-widget__checkbox" type="checkbox" name="agree_terms" required>
<?php echo sprintf(__("I confirm to subscribe to the Themeisle newsletter to receive the latest news. You can find how we use your information on our %s Privacy Policy %s", 'wbcr_factory_clearfy_246'), '<a href="' . $terms . '" target="_blank">', '</a>'); ?>
</label>
<input type="hidden" id="wbcr-factory-subscribe-widget__group-id" value="<?php echo esc_attr($group_id); ?>">
<input type="hidden" id="wbcr-factory-subscribe-widget__plugin-name" value="<?php echo esc_attr($this->plugin->getPluginName()); ?>">
<input type="submit" class="btn wbcr-factory-subscribe-widget__button" value="<?php _e('Subscribe', 'wbcr_factory_clearfy_246'); ?>">
</form>
</div>
</div>
<?php
}
/**
* Registers page options in the options registry
*
* This will allow the user to search all the plugin options.
*/
public function register_options_to_search()
{
require_once FACTORY_CLEARFY_246_DIR . '/includes/class-search-options.php';
$options = $this->getPageOptions();
$page_url = $this->getBaseUrl();
$page_id = $this->getResultId();
\WBCR\Factory_Clearfy_246\Search_Options::register_options($options, $page_url, $page_id);
}
/**
* Add search plugin options form to each option page
*/
public function printAllNotices()
{
parent::printAllNotices(); // TODO: Change the autogenerated stub
if( !$this->show_search_options_form ) {
return;
}
?>
<div id="wbcr-factory-clearfy-246__search_options_form" class="wbcr-factory-clearfy-246__autocomplete-wrap">
<label for="autocomplete" class="wbcr-factory-clearfy-246__autocomplete-label">
<?php _e('Can\'t find the settings you need? Use the search by the plugin options:', 'wbcr_factory_clearfy_246'); ?>
</label>
<input type="text" placeholder="<?php _e('Enter the option name to search...', 'wbcr_factory_clearfy_246'); ?>" name="country" id="wbcr-factory-clearfy-246__autocomplete"/>
</div>
<?php
}
}
/*@mix:place*/

View File

@@ -0,0 +1,61 @@
<?php
namespace WBCR\FactoryClearfy246\Pages;
/**
* Step
* @author Webcraftic <wordpress.webraftic@gmail.com>
* @copyright (c) 23.07.2020, Webcraftic
* @version 1.0
*/
class Step_Custom extends Step {
public function get_title()
{
return 'Custom step';
}
public function render_button($continue = true, $skip = false, $custom_title = null, $align = 'right')
{
$this->set_button_handler();
$button_title = !empty($custom_title) ? $custom_title : __('Continue', 'wbcr_factory_clearfy_246');
if( !$this->get_next_id() ) {
$button_title = __('Finish', 'wbcr_factory_clearfy_246');
}
if( !in_array($align, ['center', 'left', 'right']) ) {
$align = 'right';
}
?>
<form method="post" id="w-factory-clearfy-246__setup-form-<?php echo $this->get_id() ?>" class="form-horizontal">
<div class="w-factory-clearfy-246__form-buttons" style="text-align: <?php echo esc_attr($align); ?>">
<?php if( $skip ): ?>
<input type="submit" name="skip_button_<?php echo $this->get_id() ?>" class="button-primary button button-large w-factory-clearfy-246__skip-button" value="<?php _e('Skip', 'wbcr_factory_clearfy_246') ?>">
<?php endif; ?>
<?php if( $continue ): ?>
<input type="submit" name="continue_button_<?php echo $this->get_id() ?>" class="button-primary button button-large w-factory-clearfy-246__continue-button" value="<?php echo $button_title; ?>">
<?php endif; ?>
</div>
</form>
<?php
}
protected function set_button_handler()
{
if( isset($_POST['continue_button_' . $this->get_id()]) ) {
$this->continue_step();
}
if( isset($_POST['skip_button_' . $this->get_id()]) ) {
$this->skip_step();
}
}
public function html()
{
/// nothing
}
}

View File

@@ -0,0 +1,137 @@
<?php
namespace WBCR\FactoryClearfy246\Pages;
/**
* Step
* @author Webcraftic <wordpress.webraftic@gmail.com>
* @copyright (c) 23.07.2020, Webcraftic
* @version 1.0
*/
class Step_Form extends Step {
public function __construct(\WBCR\FactoryClearfy246\Pages\Setup $page)
{
parent::__construct($page);
}
public function get_title()
{
return 'Default form';
}
public function get_form_description()
{
return 'This is a sample html form, please customize the form fields, add description and title.';
}
public function get_form_options()
{
return [];
}
protected function instance_form($options)
{
$form = new \Wbcr_FactoryForms480_Form([
'scope' => rtrim($this->plugin->getPrefix(), '_'),
'name' => $this->page->getResultId() . "-options-" . $this->get_id()
], $this->plugin);
$form->setProvider(new \Wbcr_FactoryForms480_OptionsValueProvider($this->plugin));
$form_options = [];
$form_options[] = [
'type' => 'form-group',
'items' => $options,
//'cssClass' => 'postbox'
];
if( isset($form_options[0]) && isset($form_options[0]['items']) && is_array($form_options[0]['items']) ) {
foreach($form_options[0]['items'] as $key => $value) {
if( $value['type'] == 'div' || $value['type'] == 'more-link' ) {
if( isset($form_options[0]['items'][$key]['items']) && !empty($form_options[0]['items'][$key]['items']) ) {
foreach($form_options[0]['items'][$key]['items'] as $group_key => $group_value) {
$form_options[0]['items'][$key]['items'][$group_key]['layout']['column-left'] = '8';
$form_options[0]['items'][$key]['items'][$group_key]['layout']['column-right'] = '4';
}
continue;
}
}
if( in_array($value['type'], [
'checkbox',
'textarea',
'integer',
'textbox',
'dropdown',
'list',
'wp-editor'
]) ) {
$form_options[0]['items'][$key]['layout']['column-left'] = '8';
$form_options[0]['items'][$key]['layout']['column-right'] = '4';
}
}
}
$form->add($form_options);
$this->set_form_handler($form);
return $form;
}
protected function render_form(\Wbcr_FactoryForms480_Form $form)
{
?>
<form method="post" id="w-factory-clearfy-246__setup-form-<?php echo $this->get_id() ?>" class="w-factory-clearfy-246__setup-form form-horizontal">
<?php $form->html(); ?>
<div class="w-factory-clearfy-246__form-buttons">
<!--<input type="submit" name="skip_button_<?php /*echo $this->get_id() */ ?>" class="button-primary button button-large w-factory-clearfy-246__skip-button" value="<?php /*_e('Skip', 'wbcr_factory_clearfy_246') */ ?>">-->
<input type="submit" name="continue_button_<?php echo $this->get_id() ?>" class="button-primary button button-large w-factory-clearfy-246__continue-button" value="<?php _e('Continue', 'wbcr_factory_clearfy_246') ?>">
</div>
</form>
<?php
}
protected function set_form_handler(\Wbcr_FactoryForms480_Form $form)
{
if( isset($_POST['continue_button_' . $this->get_id()]) ) {
$form->save();
do_action('wbcr/factory/clearfy/setup_wizard/saved_options');
$this->continue_step();
}
if( isset($_POST['skip_button_' . $this->get_id()]) ) {
$this->skip_step();
}
}
public function html()
{
$form_options = $this->get_form_options();
if( empty($form_options) ) {
echo 'Html form is not configured.';
return;
}
$form = $this->instance_form($this->get_form_options());
?>
<div id="WBCR" class="wrap">
<div class="wbcr-factory-pages-480-impressive-page-template factory-bootstrap-482 factory-fontawesome-000">
<div class="w-factory-clearfy-246-setup__inner-wrap">
<h3><?php echo $this->get_title(); ?></h3>
<p style="text-align: left;"><?php echo $this->get_form_description(); ?></p>
</div>
<?php $this->render_form($form); ?>
</div>
</div>
<?php
}
}

View File

@@ -0,0 +1,81 @@
<?php
namespace WBCR\FactoryClearfy246\Pages;
/**
* Step
* @author Webcraftic <wordpress.webraftic@gmail.com>
* @copyright (c) 23.07.2020, Webcraftic
* @version 1.0
*/
abstract class Step {
protected $id;
protected $prev_id = false;
protected $next_id = false;
/**
* @var \WBCR\FactoryClearfy246\Pages\Setup
*/
protected $page;
/**
* @var \Wbcr_Factory480_Plugin
*/
protected $plugin;
public function __construct(\WBCR\FactoryClearfy246\Pages\Setup $page)
{
$this->page = $page;
$this->plugin = $page->plugin;
//$this->form_handler();
}
public function get_id()
{
if( empty($this->id) ) {
throw new \Exception('Step ID setting is required for the {' . static::class . '} class!');
}
return $this->id;
}
public function get_next_id()
{
return $this->next_id;
}
/**
* Requests assets (js and css) for the page.
*
* @return void
* @since 1.0.0
* @see FactoryPages480_AdminPage
*
*/
public function assets($scripts, $styles)
{
// nothing
}
protected function continue_step($skip = false)
{
$next_id = $this->get_next_id();
if( !$next_id ) {
$next_id = $this->get_id();
}
wp_safe_redirect($this->page->getActionUrl($next_id));
die();
}
protected function skip_step()
{
$this->continue_step(true);
}
abstract public function get_title();
abstract public function html();
}

View File

@@ -0,0 +1,217 @@
<?php
/**
* Ajax plugin configuration
*
* @author Alex Kovalev <alex.kovalevv@gmail.com>
* @copyright (c) 2017 Webraftic Ltd
* @version 1.0
*/
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* This action allows you to process Ajax requests to activate external components Clearfy
*/
function wfactory_480_install_components( $plugin_instance ) {
check_ajax_referer( 'updates' );
$slug = $plugin_instance->request->post( 'plugin', null, true );
$action = $plugin_instance->request->post( 'plugin_action', null, true );
$storage = $plugin_instance->request->post( 'storage', null, true );
if ( ! current_user_can( 'update_plugins' ) ) {
wp_die( __( 'You don\'t have enough capability to edit this information.', 'wbcr_factory_480' ), __( 'Something went wrong.' ), 403 );
}
if ( empty( $slug ) || empty( $action ) ) {
wp_send_json_error( [ 'error_message' => __( 'Required attributes are not passed or empty.', 'wbcr_factory_480' ) ] );
}
$success = false;
$send_data = [];
if ( $storage == 'internal' ) {
if ( $action == 'activate' ) {
if ( $plugin_instance->activateComponent( $slug ) ) {
$success = true;
}
} else if ( $action == 'deactivate' ) {
if ( $plugin_instance->deactivateComponent( $slug ) ) {
$success = true;
}
} else {
wp_send_json_error( [ 'error_message' => __( 'You are trying to perform an invalid action.', 'wbcr_factory_480' ) ] );
}
} else if ( $storage == 'wordpress' || $storage == 'creativemotion' ) {
if ( ! empty( $slug ) ) {
$network_wide = $plugin_instance->isNetworkActive();
if ( $action == 'activate' ) {
$result = activate_plugin( $slug, '', $network_wide );
if ( is_wp_error( $result ) ) {
wp_send_json_error( [ 'error_message' => $result->get_error_message() ] );
}
} else if ( $action == 'deactivate' ) {
deactivate_plugins( $slug, false, $network_wide );
}
$success = true;
}
}
if ( $action == 'install' || $action == 'deactivate' ) {
try {
// Delete button
$delete_button = $plugin_instance->get_delete_component_button( $storage, $slug );
$send_data['delete_button'] = $delete_button->get_button();
} catch ( Exception $e ) {
wp_send_json_error( [ 'error_message' => $e->getMessage() ] );
}
}
// Если требуется обновить постоянные ссылки, даем сигнал, что пользователю, нужно показать
// всплывающее уведомление.
// todo: сделать более красивое решение с передачей текстовых сообщений
/*if ( $action == 'deactivate' ) {
$is_need_rewrite_rules = $plugin_instance->getPopulateOption( 'need_rewrite_rules' );
if ( $is_need_rewrite_rules ) {
$send_data['need_rewrite_rules'] = sprintf( '<span class="wbcr-clr-need-rewrite-rules-message">' . __( 'When you deactivate some components, permanent links may work incorrectly. If this happens, please, <a href="%s">update the permalinks</a>, so you could complete the deactivation.', 'wbcr_factory_480' ), admin_url( 'options-permalink.php' ) . '</span>' );
}
}*/
if ( $success ) {
// todo: для совместимости с плагином Clearfy
if ( "wbcr_clearfy" === $plugin_instance->getPluginName() ) {
do_action( 'wbcr_clearfy_update_component', $slug, $action, $storage );
}
do_action( "wfactory/updated_{$plugin_instance->getPluginName()}_component", $slug, $action, $storage );
wp_send_json_success( $send_data );
}
wp_send_json_error( [ 'error_message' => __( 'An unknown error occurred during the activation of the component.', 'wbcr_factory_480' ) ] );
}
/**
* Ajax event that calls the wbcr/clearfy/activated_component action,
* to get the component to work. Usually this is a call to the installation functions,
* but in some cases, overwriting permanent references or compatibility checks.
*/
function wfactory_480_prepare_component( $plugin_instance ) {
check_ajax_referer( 'updates' );
$component_name = $plugin_instance->request->post( 'plugin', null, true );
if ( ! current_user_can( 'update_plugins' ) ) {
wp_send_json_error( [ 'error_message' => __( 'You don\'t have enough capability to edit this information.', 'wbcr_factory_480' ) ], 403 );
}
if ( empty( $component_name ) ) {
wp_send_json_error( [ 'error_message' => __( 'Required attribute [component_name] is empty.', 'wbcr_factory_480' ) ] );
}
// todo: для совместимости с плагином Clearfy
if ( "wbcr_clearfy" === $plugin_instance->getPluginName() ) {
do_action( 'wbcr/clearfy/activated_component', $component_name );
}
do_action( "wfactory/activated_{$plugin_instance->getPluginName()}_component", $component_name );
wp_send_json_success();
}
/**
* Ajax handler for installing a plugin from GitHub repository.
*
* @since 4.6.0
*
* @see Plugin_Upgrader
*
* @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
*/
function wfactory_480_creativemotion_install_plugin( $plugin_instance ) {
check_ajax_referer( 'updates' );
if ( empty( $_POST['slug'] ) ) {
wp_send_json_error( [
'errorCode' => 'no_plugin_specified',
'errorMessage' => __( 'No plugin specified.' ),
] );
}
$slug = sanitize_key( wp_unslash( $_POST['slug'] ) );
$status = [
'install' => 'plugin',
'slug' => $slug,
];
if ( ! current_user_can( 'install_plugins' ) ) {
wp_send_json_error( [
'errorCode' => 'insufficient_permissions',
'errorMessage' => __( 'Sorry, you are not allowed to install plugins on this site.' ),
] );
}
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
include_once ABSPATH . 'wp-admin/includes/plugin-install.php';
$github_settings = [
'github_username' => 'Creative-Motion-Development',
'github_repository' => 'wp-plugin-' . $slug,
'slug' => $slug,
];
try {
$github_repo = new \WBCR\Factory_480\Updates\Github_Repository( $plugin_instance, $github_settings );
$download_url = $github_repo->get_download_url();
if ( empty( $download_url ) ) {
throw new \Exception( 'Failed to get download URL from GitHub.' );
}
$skin = new WP_Ajax_Upgrader_Skin();
$upgrader = new Plugin_Upgrader( $skin );
$result = $upgrader->install( $download_url );
if ( is_wp_error( $result ) ) {
wp_send_json_error( [
'errorCode' => $result->get_error_code(),
'errorMessage' => $result->get_error_message(),
] );
}
if ( $skin->get_errors()->has_errors() ) {
wp_send_json_error( [
'errorMessage' => $skin->get_error_messages(),
] );
}
$install_status = install_plugin_install_status( (object) [ 'slug' => $slug ] );
$pagenow = isset( $_POST['pagenow'] ) ? sanitize_key( $_POST['pagenow'] ) : '';
// If installation request is coming from import page, do not return network activation link.
$plugins_url = ( 'import' === $pagenow ) ? admin_url( 'plugins.php' ) : network_admin_url( 'plugins.php' );
if ( current_user_can( 'activate_plugin', $install_status['file'] ) && is_plugin_inactive( $install_status['file'] ) ) {
$status['activateUrl'] = add_query_arg( [
'_wpnonce' => wp_create_nonce( 'activate-plugin_' . $install_status['file'] ),
'action' => 'activate',
'plugin' => $install_status['file'],
], $plugins_url );
}
if ( is_multisite() && current_user_can( 'manage_network_plugins' ) && 'import' !== $pagenow ) {
$status['activateUrl'] = add_query_arg( [ 'networkwide' => 1 ], $status['activateUrl'] );
}
wp_send_json_success( $status );
} catch ( \Exception $e ) {
wp_send_json_error( [
'errorCode' => 'github_error',
'errorMessage' => $e->getMessage(),
] );
}
}

View File

@@ -0,0 +1,227 @@
/**
* This code provides tools for downloading, installing external add-ons for the Clearfy plugin
*
* @author Alex Kovalev <alex.kovalevv@gmail.com>
* @copyright (c) 10.09.2017, Webcraftic
* @version 1.0
*/
(function($) {
'use strict';
var externalAddon = {
init: function() {
this.events();
},
events: function() {
var self = this;
/**
* This event is intended for installation, removal, activation, deactivation of external add-ons
*/
$(document).on('click', '.wfactory-480-process-button', function() {
var $this = $(this),
button_i18n = $(this).data('i18n'),
plugin_slug = $(this).data('slug'),
plugin_action = $(this).data('plugin-action'),
plugin = $(this).data('plugin'),
storage = $(this).data('storage'),
wpnonce = $(this).data('wpnonce');
var action = ('creativemotion' === storage)
? 'wfactory-480-creativemotion-install-plugin'
: 'install-plugin';
if( storage === 'freemius' || ((storage === 'wordpress' || storage === 'creativemotion' || storage === 'internal') && (plugin_action === 'activate' || plugin_action === 'deactivate')) ) {
action = 'wfactory-480-intall-component';
} else if( storage === 'wordpress' && plugin_action === 'delete' ) {
action = 'delete-plugin';
}
var data = {
action: action,
slug: plugin_slug,
storage: storage,
plugin: plugin,
plugin_action: plugin_action,
_wpnonce: wpnonce
};
if( plugin_action === 'install' ) {
$this.addClass('updating-message');
}
$this.addClass('disabled').text(button_i18n.loading);
$.wfactory_480.hooks.run('core/components/pre_update', [$this, data]);
self.sendRequest(data, function(response) {
if( !response || !response.success ) {
$.wfactory_480.hooks.run('core/components/update_error', [
$this,
data,
response
]);
return;
}
if( response.success ) {
$this.removeClass('disabled').removeClass('updating-message');
if( plugin_action === 'install' ) {
plugin_action = 'activate';
$this.data('plugin-action', 'activate');
$this.attr('data-plugin-action', 'activate');
if( $this.hasClass('button') ) {
$this.removeClass('button-default').addClass('button-primary');
}
$.wfactory_480.hooks.run('core/components/installed', [
$this,
data,
response
]);
} else if( plugin_action === 'activate' ) {
plugin_action = 'deactivate';
$this.data('plugin-action', 'deactivate');
$this.attr('data-plugin-action', 'deactivate');
if( $this.hasClass('button') ) {
$this.removeClass('button-primary').addClass('button-default');
}
$.wfactory_480.hooks.run('core/components/pre_activate', [
$this,
data,
response
]);
/**
* Send an additional request for activation of the component, during activation
* perform the action wbcr/clearfy/activated_component.
*
* Basically, this is necessary to prepare the plugin to work, write the necessary rows and
* tables in the database, rewriting permalinks, checking conflicts, etc.
*/
if( storage === 'freemius' || storage === 'internal' ) {
self.sendRequestToComponentActivationPrepare($this, data, button_i18n);
return;
}
} else if( plugin_action === 'deactivate' ) {
plugin_action = 'activate';
$this.data('plugin-action', 'activate');
$this.attr('data-plugin-action', 'activate');
if( $this.hasClass('button') ) {
$this.removeClass('button-default').addClass('button-primary');
}
$.wfactory_480.hooks.run('core/components/deactivated', [
$this,
data,
response
]);
} else if( plugin_action === 'delete' ) {
plugin_action = 'install';
$.wfactory_480.hooks.run('core/components/deleted', [$this, data, response]);
}
} else {
if( plugin_action === 'install' ) {
$this.removeClass('updating-message');
}
}
$this.text(button_i18n[plugin_action]);
$.wfactory_480.hooks.run('core/components/updated', [$this, data, response]);
});
return false;
});
},
/**
* Отправляет дополнительный запрос на активацию компонента, во время активации
* выполняет хук wbcr/clearfy/activated_component.
*
* В принципе, это необходимо для подготовки плагина к работе, записи необходимых строк и таблиц в
* базу данных, перепись постоянных ссылок, проверка конфликтов и т.д.
*
* @param {object} componentButton
* @param {object} sendData
* @param {object} button_i18n
*/
sendRequestToComponentActivationPrepare: function(componentButton, sendData, button_i18n) {
var self = this;
componentButton.addClass('button-primary')
.addClass('disabled')
.text(button_i18n.preparation);
sendData.action = 'wfactory-480-prepare-component';
this.sendRequest(sendData, function(response) {
componentButton.removeClass('disabled');
if( !response || !response.success ) {
componentButton.text(button_i18n['activate']);
$.wfactory_480.hooks.run('core/components/activation_error', [
componentButton,
sendData,
response
]);
return;
}
componentButton.removeClass('button-primary').text(button_i18n['deactivate']);
$.wfactory_480.hooks.run('core/components/activated', [
componentButton,
sendData,
response
]);
});
},
sendRequest: function(data, callback) {
var self = this;
$.ajax(ajaxurl, {
type: 'post',
dataType: 'json',
data: data,
success: function(data, textStatus, jqXHR) {
callback && callback(data);
},
error: function(xhr, ajaxOptions, thrownError) {
console.log(xhr.status);
console.log(xhr.responseText);
console.log(thrownError);
$.wfactory_480.hooks.run('core/components/ajax_error', [
xhr,
ajaxOptions,
thrownError
]);
}
});
}
};
$(document).ready(function() {
externalAddon.init();
});
})(jQuery);

View File

@@ -0,0 +1,99 @@
/**
*
* @author Webcraftic <wordpress.webraftic@gmail.com>
* @copyright (c) 02.09.2020, Webcraftic
* @version 1.0
*/
(function($) {
'use strict';
if( !$.wfactory_480 ) {
$.wfactory_480 = {};
}
$.wfactory_480.filters = $.wfactory_480.filters || {
/**
* A set of registered filters.
*/
_items: {},
/**
* A set of priorities of registered filters.
*/
_priorities: {},
/**
* Applies filters to a given input value.
*/
run: function(filterName, args) {
var input = args && args.length > 0 ? args[0] : null;
if( !this._items[filterName] ) {
return input;
}
for( var i in this._priorities[filterName] ) {
if( !this._priorities[filterName].hasOwnProperty(i) ) {
continue;
}
var priority = this._priorities[filterName][i];
for( var k = 0; k < this._items[filterName][priority].length; k++ ) {
var f = this._items[filterName][priority][k];
input = f.apply(f, args);
}
}
return input;
},
/**
* Registers a new filter.
*/
add: function(filterName, callback, priority) {
if( !priority ) {
priority = 10;
}
if( !this._items[filterName] ) {
this._items[filterName] = {};
}
if( !this._items[filterName][priority] ) {
this._items[filterName][priority] = [];
}
this._items[filterName][priority].push(callback);
if( !this._priorities[filterName] ) {
this._priorities[filterName] = [];
}
if( $.inArray(priority, this._priorities[filterName]) === -1 ) {
this._priorities[filterName].push(priority);
}
this._priorities[filterName].sort(function(a, b) {
return a - b;
});
}
};
$.wfactory_480.hooks = $.wfactory_480.hooks || {
/**
* Applies filters to a given input value.
*/
run: function(filterName, args) {
$.wfactory_480.filters.run(filterName, args);
},
/**
* Registers a new filter.
*/
add: function(filterName, callback, priority) {
$.wfactory_480.filters.add(filterName, callback, priority);
}
};
})(jQuery);

View File

@@ -0,0 +1,75 @@
<?php
/**
* Factory Plugin
*
* @author @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
* @since 1.0.0
* @package core
* @copyright (c) 2018, Webcraftic Ltd
*
*/
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( defined( 'FACTORY_480_LOADED' ) ) {
return;
}
define( 'FACTORY_480_LOADED', true );
define( 'FACTORY_480_VERSION', '4.8.3' );
define( 'FACTORY_480_DIR', dirname( __FILE__ ) );
define( 'FACTORY_480_URL', plugins_url( '', __FILE__ ) );
add_action( 'init', function () {
load_plugin_textdomain( 'wbcr_factory_480', false, dirname( plugin_basename( __FILE__ ) ) . '/langs' );
} );
#comp merge
require_once( FACTORY_480_DIR . '/includes/functions.php' );
require_once( FACTORY_480_DIR . '/includes/entities/class-factory-paths.php' );
require_once( FACTORY_480_DIR . '/includes/entities/class-factory-support.php' );
require_once( FACTORY_480_DIR . '/includes/class-factory-requests.php' );
require_once( FACTORY_480_DIR . '/includes/class-factory-options.php' );
require_once( FACTORY_480_DIR . '/includes/class-factory-plugin-base.php' );
require_once( FACTORY_480_DIR . '/includes/class-factory-migrations.php' );
require_once( FACTORY_480_DIR . '/includes/class-factory-notices.php' );
// ASSETS
require_once( FACTORY_480_DIR . '/includes/assets-managment/class-factory-assets-list.php' );
require_once( FACTORY_480_DIR . '/includes/assets-managment/class-factory-script-list.php' );
require_once( FACTORY_480_DIR . '/includes/assets-managment/class-factory-style-list.php' );
// PREMIUM
require_once( FACTORY_480_DIR . '/includes/premium/class-factory-license-interface.php' );
require_once( FACTORY_480_DIR . '/includes/premium/class-factory-provider-abstract.php' );
require_once( FACTORY_480_DIR . '/includes/premium/class-factory-manager.php' );
// UPDATES
require_once( FACTORY_480_DIR . '/includes/updates/repositories/class-factory-repository-abstract.php' );
require_once( FACTORY_480_DIR . '/includes/updates/repositories/class-factory-wordpress.php' );
require_once( FACTORY_480_DIR . '/includes/updates/repositories/class-factory-github.php' );
require_once( FACTORY_480_DIR . '/includes/updates/class-factory-upgrader.php' );
require_once( FACTORY_480_DIR . '/includes/updates/class-factory-premium-upgrader.php' );
require_once( FACTORY_480_DIR . '/includes/class-factory-plugin-abstract.php' );
require_once( FACTORY_480_DIR . '/includes/activation/class-factory-activator.php' );
require_once( FACTORY_480_DIR . '/includes/activation/class-factory-update.php' );
#endcomp
add_action( 'admin_enqueue_scripts', function () {
wp_enqueue_script( 'wfactory-480-core-general', FACTORY_480_URL . '/assets/js/core-general.js', [
'jquery'
], FACTORY_480_VERSION );
wp_enqueue_script( 'wfactory-480-core-components', FACTORY_480_URL . '/assets/js/core-components.js', [
'jquery',
'wfactory-480-core-general'
], FACTORY_480_VERSION );
} );

View File

@@ -0,0 +1,43 @@
<?php
/**
* The file contains a base class for plugin activators.
*
* @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
* @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
*
* @package factory-core
* @since 1.0.0
*/
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Plugin Activator
*
* @since 1.0.0
*/
abstract class Wbcr_Factory480_Activator {
/**
* Curent plugin.
*
* @var Wbcr_Factory480_Plugin
*/
public $plugin;
public function __construct( Wbcr_Factory480_Plugin $plugin ) {
$this->plugin = $plugin;
}
public function activate() {
}
public function deactivate() {
}
public function update() {
}
}

View File

@@ -0,0 +1,39 @@
<?php
/**
* The file contains a base class for update items of plugins.
*
* @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
* @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
*
* @package factory-core
* @since 1.0.0
*/
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Plugin Activator
*
* @since 1.0.0
*/
abstract class Wbcr_Factory480_Update {
/**
* Current plugin
*
* @var Wbcr_Factory480_Plugin
*/
var $plugin;
public function __construct( Wbcr_Factory480_Plugin $plugin ) {
$this->plugin = $plugin;
}
abstract function install();
//abstract function rollback();
}

View File

@@ -0,0 +1,2 @@
<?php
// Silence is golden.

View File

@@ -0,0 +1,126 @@
<?php
/**
* The class contains a base class for all lists of assets.
*
* @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
* @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
*
* @package factory-core
* @since 1.0.0
*/
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Assets List
*
* @since 1.0.0
*/
class Wbcr_Factory480_AssetsList {
protected $all = [];
public $header_place = [];
public $footer_place = [];
public $required = [];
protected $default_place;
/**
* @var Wbcr_Factory480_Plugin
*/
protected $plugin;
/**
* @param Wbcr_Factory480_Plugin $plugin
* @param bool $defaultIsFooter
*/
public function __construct( Wbcr_Factory480_Plugin $plugin, $defaultIsFooter = true ) {
$this->plugin = $plugin;
if ( $defaultIsFooter ) {
$this->default_place = &$this->footer_place;
}
if ( ! $defaultIsFooter ) {
$this->default_place = &$this->header_place;
}
}
/**
* Remove items from the collection
*
* @return $this
*/
public function deregister() {
foreach ( func_get_args() as $item ) {
if ( ! is_string( $item ) ) {
return $this;
}
$key_in_all = array_search( $item, $this->all );
$key_in_default_place = array_search( $item, $this->default_place );
$key_in_header_place = array_search( $item, $this->header_place );
$key_inFooterPlace = array_search( $item, $this->footer_place );
if ( $key_in_all ) {
unset( $this->all[ $key_in_all ] );
}
if ( $key_in_default_place ) {
unset( $this->default_place[ $key_in_default_place ] );
}
if ( $key_in_header_place ) {
unset( $this->header_place[ $key_in_header_place ] );
}
if ( $key_inFooterPlace ) {
unset( $this->footer_place[ $key_inFooterPlace ] );
}
}
return $this;
}
/**
* Checks whether the collection is empty.
*
* @param string $source if the 'bootstrap' specified, checks only whether the bootstrap assets were required.
*
* @return boolean
*/
public function isEmpty( $source = 'wordpress' ) {
if ( 'bootstrap' === $source ) {
return empty( $this->required[ $source ] );
}
return empty( $this->all ) && empty( $this->required );
}
public function IsHeaderEmpty() {
return empty( $this->header_place );
}
public function IsFooterEmpty() {
return empty( $this->footer_place );
}
/**
* Adds new items to the requried collection.
*
* @param mixed
*/
public function request( $items, $source = 'wordpress' ) {
if ( is_array( $items ) ) {
foreach ( $items as $item ) {
$this->required[ $source ][] = $item;
}
} else {
$this->required[ $source ][] = $items;
}
return $this;
}
}

View File

@@ -0,0 +1,167 @@
<?php
/**
* The file contains a class to manage script assets.
*
* @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
* @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
*
* @package factory-core
* @since 1.0.0
*/
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Script List
*
* @since 1.0.0
*/
class Wbcr_Factory480_ScriptList extends Wbcr_Factory480_AssetsList {
public $localize_data = [];
public $use_ajax = false;
/**
* Adds new items to the collection (default place).
*
* @param mixed
*
* @version 2.0
*/
public function add( $file_url, $deps = [ 'jquery' ], $handle = null, $version = false, $place = 'default' ) {
if ( empty( $file_url ) ) {
return $this;
}
$resource = [];
$resource['file_url'] = $file_url;
$resource['deps'] = $deps;
$resource['handle'] = $handle;
$resource['version'] = $version;
$this->all[] = $resource;
switch ( $place ) {
case 'header':
$this->header_place[] = $resource;
break;
case 'footer':
$this->footer_place[] = $resource;
break;
default:
$this->default_place[] = $resource;
break;
}
return $this;
}
/**
* Adds new items to the collection (header).
*
* @param mixed
*/
public function addToHeader( $file_url, $deps = [ 'jquery' ], $handle = null ) {
return $this->add( $file_url, $deps, $handle, 'header' );
}
/**
* Adds new items to the collection (footer).
*
* @param mixed
*/
public function addToFooter( $file_url, $deps = [ 'jquery' ], $handle = null ) {
return $this->add( $file_url, $deps, $handle, 'footer' );
}
/**
* Осуществляет подключение всех зарегистрированных скриптов
*
* @param string $source
*/
public function connect( $source = 'wordpress' ) {
// register all global required scripts
if ( ! empty( $this->required[ $source ] ) ) {
foreach ( $this->required[ $source ] as $script ) {
if ( 'wordpress' === $source ) {
wp_enqueue_script( $script );
} else if ( 'bootstrap' === $source ) {
$this->plugin->bootstrap->enqueueScript( $script );
}
}
}
if ( $source == 'bootstrap' ) {
return;
}
$is_first_script = true;
$is_footer = false;
// register all other scripts
foreach ( [ $this->header_place, $this->footer_place ] as $script_place ) {
foreach ( $script_place as $script ) {
if ( empty( $script['file_url'] ) ) {
continue;
}
$handle = ! empty( $script['handle'] ) ? $script['handle'] : $script['file_url'];
$deps = ! is_array( $script['deps'] ) ? [] : $script['deps'];
$version = ! empty( $script['version'] ) ? $script['version'] : $this->plugin->getPluginVersion();
wp_register_script( $handle, $script['file_url'], $deps, $version, $is_footer );
if ( $is_first_script && $this->use_ajax ) {
wp_localize_script( $handle, 'factory', [ 'ajaxurl' => admin_url( 'admin-ajax.php' ) ] );
}
if ( ! empty( $this->localize_data[ $handle ] ) ) {
wp_localize_script( $handle, $this->localize_data[ $handle ][0], $this->localize_data[ $handle ][1] );
}
wp_enqueue_script( $handle );
$is_first_script = false;
}
$is_footer = true;
}
}
/**
* Если вызвать этот метод, на странице будет обязательно добавлена
* глобальная JS переменная с ссылкой на ajax обработчик
*/
public function useAjax() {
$this->use_ajax = true;
}
/**
* Регистрирует глобальную JS переменную с пользовательскими данными
*
* @param string $varname
* @param array $data
*
* @return Wbcr_Factory480_ScriptList $this
*/
public function localize( $varname, $data ) {
$bindTo = count( $this->all ) == 0 ? null : end( $this->all );
if ( ! $bindTo ) {
return $this;
}
$handle = ! empty( $bindTo['handle'] ) ? $bindTo['handle'] : $bindTo['file_url'];
$this->localize_data[ $handle ] = [ $varname, $data ];
return $this;
}
}

View File

@@ -0,0 +1,86 @@
<?php
/**
* The file contains a class to manage style assets.
*
* @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
* @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
*
* @package factory-core
* @since 1.0.0
*/
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Style List
*
* @since 1.0.0
*/
class Wbcr_Factory480_StyleList extends Wbcr_Factory480_AssetsList {
/**
* Adds new items to the collection (default place).
*
* @param mixed
*
* @version 2.0
*/
public function add( $file_url, $deps = [], $handle = null, $version = false, $media = 'all' ) {
if ( empty( $file_url ) ) {
return $this;
}
$resource = [];
$resource['file_url'] = $file_url;
$resource['deps'] = $deps;
$resource['handle'] = $handle;
$resource['version'] = $version;
$resource['media'] = $media;
$this->all[] = $resource;
return $this;
}
public function connect( $source = 'wordpress' ) {
// register all global required scripts
if ( ! empty( $this->required[ $source ] ) ) {
foreach ( $this->required[ $source ] as $style ) {
if ( 'wordpress' === $source ) {
wp_enqueue_style( $style );
} else if ( 'bootstrap' === $source ) {
$this->plugin->bootstrap->enqueueStyle( $style );
}
}
}
if ( $source == 'bootstrap' ) {
return;
}
if ( empty( $this->all ) ) {
return;
}
// register all other styles
foreach ( $this->all as $style ) {
if ( empty( $style['file_url'] ) ) {
continue;
}
$handle = ! empty( $style['handle'] ) ? $style['handle'] : md5( $style['file_url'] );
$deps = ! is_array( $style['deps'] ) ? [] : $style['deps'];
$version = ! empty( $style['version'] ) ? $style['version'] : $this->plugin->getPluginVersion();
wp_enqueue_style( $handle, $style['file_url'], $deps, $version );
}
}
}

View File

@@ -0,0 +1,2 @@
<?php
// Silence is golden.

View File

@@ -0,0 +1,122 @@
<?php
/**
* Проверяет совместимость с плагинами Webcraftic, с версиями php, с версиями Wordpress
*
* @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
* @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
*
* @version 1.0.0
* @since 4.0.8
*/
if ( ! class_exists( 'Wbcr_Factory_Compatibility' ) ) {
class Wbcr_Factory_Compatibility {
protected $plugin_prefix;
protected $plugin_class_prefix;
protected $plugin_name;
protected $plugin_title = "(no title)";
protected $required_php_version = '5.3';
protected $required_wp_version = '4.2.0';
function __construct( array $plugin_info ) {
foreach ( (array) $plugin_info as $property => $value ) {
$this->$property = $value;
}
add_action( 'admin_init', [ $this, 'registerNotices' ] );
}
/**
* Метод проверяет совместимость плагина с php и wordpress версией
*
* @return bool
*/
public function check() {
if ( ! $this->isPhpCompatibility() ) {
return false;
}
if ( ! $this->isWpCompatibility() ) {
return false;
}
return true;
}
/**
* Метод проверяет совместимость плагина с php версией сервера
*
* @return mixed
*/
public function isPhpCompatibility() {
return version_compare( PHP_VERSION, $this->required_php_version, '>=' );
}
/**
* Метод проверяет совместимость плагина с Wordpress версией сайта
*
* @return mixed
*/
public function isWpCompatibility() {
// Get the WP Version global.
global $wp_version;
return version_compare( $wp_version, $this->required_wp_version, '>=' );
}
/**
* Метод возвращает текст уведомления
*
* @return string
*/
public function getNoticeText() {
$notice_text = $notice_default_text = '';
$notice_default_text .= '<b>' . $this->plugin_title . ' ' . __( 'warning', '' ) . ':</b>' . '<br>';
$notice_default_text .= sprintf( __( 'The %s plugin has stopped.', 'wbcr_factory_templates_134' ), $this->plugin_title ) . ' ';
$notice_default_text .= __( 'Possible reasons:', '' ) . ' <br>';
$has_one = false;
if ( ! $this->isPhpCompatibility() ) {
$has_one = true;
$notice_text .= '- ' . sprintf( __( 'You need to update the PHP version to %s or higher!', 'wbcr_factory_480' ), $this->required_php_version ) . '<br>';
}
if ( ! $this->isWpCompatibility() ) {
$has_one = true;
$notice_text .= '- ' . sprintf( __( 'You need to update WordPress to %s or higher!', 'wbcr_factory_480' ), $this->required_wp_version ) . '<br>';
}
if ( $has_one ) {
$notice_text = $notice_default_text . $notice_text;
}
return $notice_text;
}
public function registerNotices() {
if ( current_user_can( 'activate_plugins' ) && current_user_can( 'edit_plugins' ) && current_user_can( 'install_plugins' ) ) {
if ( is_multisite() ) {
add_action( 'network_admin_notices', [ $this, 'showNotice' ] );
}
add_action( 'admin_notices', [ $this, 'showNotice' ] );
}
}
public function showNotice() {
$notice_text = $this->getNoticeText();
if ( empty( $notice_text ) ) {
return;
}
$notice_text = '<p>' . $this->getNoticeText() . '</p>';
echo '<div class="notice notice-error">' . esc_html(apply_filters( 'wbcr/factory/check_compatibility/notice_text', $notice_text, $this->plugin_name )) . '</div>';
}
}
}

View File

@@ -0,0 +1,541 @@
<?php
namespace WBCR\Factory_480;
use Exception;
use Wbcr_Factory480_Plugin;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Often when updating plugins, you need to make some changes to the database.
* This class automatically checks for plugin migrations and executes them when
* updating.
*
* The class has a debug mode, to enable the debug mode add constants to your plugin:
* define ('FACTORY_MIGRATIONS_DEBUG', true) - enables/disables debugging mode
* define ('FACTORY_MIGRATIONS_FORCE_OLD_VERSION', '1.1.9') - sets previous version
* for the plugin, if constant isn't set, then the previous version is taken from
* the database.
*
* todo: get_option and get_site_option are used because some caching plugins caching options, which causes problems
*
*
* @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
* @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
*
* @since 4.1.1
*/
class Migrations {
protected $plugin;
/**
* Migrations constructor.
*
* @param Wbcr_Factory480_Plugin $plugin
*
* @throws Exception
*/
public function __construct( Wbcr_Factory480_Plugin $plugin ) {
$this->plugin = $plugin;
$plugin_name = $plugin->getPluginName();
if ( ! file_exists( $this->plugin->get_paths()->migrations ) ) {
throw new Exception( 'Starting with version 4.1.1 of the Core for Factory framework module, you must create a "migrations" folder in the root of your plugin to store the migration of the plugin.' );
}
if ( is_admin() ) {
add_action( "admin_init", [ $this, "check_migrations" ] );
add_action( "wbcr/factory/plugin_{$plugin_name}_activated", [ $this, 'activation_hook' ] );
add_action( "wbcr/factory/admin_notices", [ $this, "debug_bar_notice" ], 10, 2 );
add_action( "wbcr/factory/admin_notices", [ $this, "migration_error_notice" ], 10, 2 );
}
}
/**
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 4.1.1
* @return mixed|void
*/
public function get_plugin_activated_time() {
if ( $this->plugin->isNetworkActive() ) {
return get_site_option( $this->plugin->getOptionName( 'plugin_activated' ), 0 );
}
return get_option( $this->plugin->getOptionName( 'plugin_activated' ), 0 );
}
/**
* Check if migration is necessary for plugin and if there are errors from previous migrations.
* In debug mode, migrations are not performed automatically.
*/
public function check_migrations() {
if ( $this->is_migration_error() && isset( $_GET['wbcr_factory_fix_migration_error'] ) ) {
$this->fix_migration_error();
wp_safe_redirect( esc_url_raw(remove_query_arg( 'wbcr_factory_fix_migration_error' )) );
die();
}
if ( $this->is_debug() && isset( $_GET['wbcr_factory_test_migration'] ) ) {
$this->make_migration();
wp_safe_redirect( esc_url_raw(remove_query_arg( 'wbcr_factory_test_migration' )) );
die();
}
if ( $this->need_migration() && ! $this->is_debug() ) {
$this->make_migration();
}
}
/**
* Notification displays the errors of outstanding migrations to fix errors
* you need to follow the instructions in the notification and click
* "I fixed, confirm migration".
*
* What is it for. Migrations are performed in background and on some sites,
* due to php errors or for some other reason, migration may be
* interrupted, because of what plugin will work incorrectly, you may lose settings.
*
* When creating new migrations, developer will add error handlers,
* and framework will intercept them safely for user and display them
* in this notice.
*
* @param array $notices
* @param static $plugin_name
*
* @return array
*/
public function migration_error_notice( $notices, $plugin_name ) {
if ( $this->plugin->getPluginName() !== $plugin_name ) {
return $notices;
}
if ( ! $this->is_migration_error() || ! current_user_can( 'update_plugins' ) ) {
return $notices;
}
if ( $this->plugin->isNetworkActive() ) {
$migration_error_text = get_site_option( $this->plugin->getOptionName( 'plugin_migration_error' ), '' );
} else {
$migration_error_text = get_option( $this->plugin->getOptionName( 'plugin_migration_error' ), '' );
}
$fix_migration_error_url = esc_url(add_query_arg( 'wbcr_factory_fix_migration_error', 1 ));
$notice_text = $migration_error_text;
$notice_text .= "<br><br><a href='{$fix_migration_error_url}' class='button button-default'>" . __( 'I fixed, confirm migration', 'wbcr_factory_480' ) . "</a>";
$notices[] = [
'id' => 'migration_debug_bar',
'type' => 'error',
'dismissible' => false,
'dismiss_expires' => 0,
'text' => '<p><b>' . $this->plugin->getPluginTitle() . ' ' . __( 'migration error', 'wbcr_factory_480' ) . '</b><br>' . $notice_text . '</p>'
];
return $notices;
}
/**
* Debug panel, display some information from the database. Also allows
* perform manual migrations to test new migrations.
*
* @param array $notices
* @param string $plugin_name
*
* @return array
*/
public function debug_bar_notice( $notices, $plugin_name ) {
if ( $this->plugin->getPluginName() !== $plugin_name ) {
return $notices;
}
if ( ! $this->is_debug() || ! current_user_can( 'update_plugins' ) ) {
return $notices;
}
$migrate_url = esc_url(add_query_arg( 'wbcr_factory_test_migration', 1 ));
$notice_text = __( "Plugin activated:", "wbcr_factory_480" ) . ' ' . date( "Y-m-d H:i:s", $this->get_plugin_activated_time() ) . "<br>";
$notice_text .= __( "Old plugin version (debug):", "wbcr_factory_480" ) . ' ' . $this->get_old_plugin_version() . "<br>";
$notice_text .= __( "Current plugin version:", "wbcr_factory_480" ) . ' ' . $this->get_current_plugin_version() . "<br>";
$notice_text .= __( "Need migration:", "wbcr_factory_480" ) . ' ' . ( $this->need_migration() ? "true" : "false" ) . "<br><br>";
$notice_text .= "<a href='{$migrate_url}' class='button button-default'>" . __( "Migrate now", "wbcr_factory_480" ) . "</a><br>";
$notices[] = [
'id' => 'migration_debug_bar',
'type' => 'warning',
'dismissible' => false,
'dismiss_expires' => 0,
'text' => '<p><b style="color:red;">' . $this->plugin->getPluginTitle() . ' ' . __( 'migrations DEBUG bar', 'wbcr_factory_480' ) . '</b><br>' . $notice_text . '</p>'
];
return $notices;
}
/**
* Runs when plugin is activated. Checks if you need to migrate
* and if necessary it does it. Also adds a option when the plugin
* was activated for the first time.
*/
public function activation_hook() {
/*if ( $this->need_migration() && ! $this->is_debug() ) {
$this->make_migration();
}*/
// just time to know when the plugin was activated the first time
$activated = $this->get_plugin_activated_time();
if ( ! $activated ) {
if ( $this->plugin->isNetworkActive() ) {
update_site_option( $this->plugin->getOptionName( 'plugin_activated' ), time() );
update_site_option( $this->plugin->getOptionName( 'plugin_version' ), $this->get_current_plugin_version() );
} else {
update_option( $this->plugin->getOptionName( 'plugin_activated' ), time() );
update_option( $this->plugin->getOptionName( 'plugin_version' ), $this->get_current_plugin_version() );
}
}
}
/**
* Checks if debug mode of migrations from version x.x.x to x.x.y is enabled.
*
* @return bool
*/
protected function is_debug() {
return defined( 'FACTORY_MIGRATIONS_DEBUG' ) && FACTORY_MIGRATIONS_DEBUG;
}
/**
* Gets previous version of plugin that plugin had before updating to the new version.
*
* @return string|null
*/
protected function get_old_plugin_version() {
if ( $this->is_debug() && defined( 'FACTORY_MIGRATIONS_FORCE_OLD_VERSION' ) ) {
return FACTORY_MIGRATIONS_FORCE_OLD_VERSION;
}
if ( $this->plugin->isNetworkActive() ) {
$plugin_version = get_site_option( $this->plugin->getOptionName( 'plugin_version' ), null );
} else {
$plugin_version = get_option( $this->plugin->getOptionName( 'plugin_version' ), null );
}
if ( ! empty( $plugin_version ) ) {
return $plugin_version;
}
# TODO: Remove after few releases
# This block for compatibility code with old version of framework < 4.1.1
#-------------------------------------------
if ( $this->plugin->isNetworkActive() ) {
$plugin_versions = get_site_option( 'factory_plugin_versions', [] );
} else {
$plugin_versions = get_option( 'factory_plugin_versions', [] );
}
$plugin_version = isset( $plugin_versions[ $this->plugin->getPluginName() ] ) ? $plugin_versions[ $this->plugin->getPluginName() ] : null;
if ( ! empty( $plugin_version ) ) {
$plugin_version = str_replace( [ 'free-', 'premium-', 'offline-' ], '', $plugin_version );
}
#-------------------------------------------
return $plugin_version;
}
/**
* Gets the current version of plugin.
*
* @return string
*/
protected function get_current_plugin_version() {
return $this->plugin->getPluginVersion();
}
/**
* Do I need migration for plugin? If previous migration was with a error, then
* method will always return false to prevent looping.
*
* @return mixed
*/
protected function need_migration() {
if ( $this->is_migration_error() ) {
return false;
}
return version_compare( $this->get_old_plugin_version(), $this->get_current_plugin_version(), '<' );
}
/**
* Are there errors from previous migrations?
*
* @return bool
*/
protected function is_migration_error() {
if ( $this->plugin->isNetworkActive() ) {
$error = get_site_option( $this->plugin->getOptionName( 'plugin_migration_error' ), false );
} else {
$error = get_option( $this->plugin->getOptionName( 'plugin_migration_error' ), false );
}
return $error !== false;
}
/**
* Remove an option in database, thereby fix errors of the previous migration.
*/
protected function fix_migration_error() {
if ( $this->plugin->isNetworkActive() ) {
delete_site_option( $this->plugin->getOptionName( 'plugin_migration_error' ) );
return;
}
delete_option( $this->plugin->getOptionName( 'plugin_migration_error' ) );
}
/**
* Migrates the plugin from version x.x.x to x.x.y. Automatically searches for files
* migrations to the plugin's root directory and executes them. Default files
* migrations are stored in wp-content/plugins/plugin-name/migrations and have names
* 0x0x0x.php, which corresponds to the version x.x.x. Method executes those migration files
* versions of which are between the previous version of plugin and current one.
*
*/
protected function make_migration() {
if ( ! current_user_can( 'update_plugins' ) ) {
return;
}
$old_plugin_version = $this->get_old_plugin_version();
$new_plugin_version = $this->get_current_plugin_version();
if ( empty( $old_plugin_version ) ) {
$this->update_plugin_version_in_db();
}
// converts versions like 0.0.0 to 000000
$old_number = $this->get_version_number( $old_plugin_version );
$new_number = $this->get_version_number( $new_plugin_version );
try {
$update_files = $this->plugin->get_paths()->migrations;
$files = $this->find_files( $update_files );
if ( empty( $files ) ) {
$this->update_plugin_version_in_db();
return;
}
// finds updates that has intermediate version
foreach ( (array) $files as $item ) {
if ( ! preg_match( '/^\d+$/', $item['name'] ) ) {
continue;
}
$item_number = intval( $item['name'] );
if ( $item_number > $old_number && $item_number <= $new_number ) {
$classes = $this->get_classes( $item['path'] );
if ( count( $classes ) == 0 ) {
continue;
}
foreach ( $classes as $path => $class_data ) {
include_once( $path );
$update_class = $class_data['name'];
$update = new $update_class( $this->plugin );
$update->install();
}
}
}
$this->update_plugin_version_in_db();
} catch( Exception $e ) {
if ( $this->plugin->isNetworkActive() ) {
update_site_option( $this->plugin->getOptionName( 'plugin_migration_error' ), $e->getMessage() );
return;
}
update_option( $this->plugin->getOptionName( 'plugin_migration_error' ), $e->getMessage() );
}
}
/**
* Updates version of plugin in database. So that we can track which
* previous version of plugin was at the user, before he updated
* plugin.
*/
protected function update_plugin_version_in_db() {
# TODO: Delete after few releases
# This block for compatibility code with the old version of framework.
# Cleans up old data, after the transition to new version of framework.
#-------------------------------------------
if ( $this->plugin->isNetworkActive() ) {
$plugin_versions = get_site_option( 'factory_plugin_versions', [] );
} else {
$plugin_versions = get_option( 'factory_plugin_versions', [] );
}
if ( isset( $plugin_versions[ $this->plugin->getPluginName() ] ) ) {
unset( $plugin_versions[ $this->plugin->getPluginName() ] );
}
if ( $this->plugin->isNetworkActive() ) {
if ( empty( $plugin_versions ) ) {
delete_site_option( 'factory_plugin_versions' );
}
update_site_option( 'factory_plugin_versions', $plugin_versions );
update_site_option( $this->plugin->getOptionName( 'plugin_version' ), $this->get_current_plugin_version() );
return;
}
if ( empty( $plugin_versions ) ) {
delete_option( 'factory_plugin_versions' );
}
update_option( 'factory_plugin_versions', $plugin_versions );
update_option( $this->plugin->getOptionName( 'plugin_version' ), $this->get_current_plugin_version() );
}
/**
* Converts string representation of the version to the numeric.
*
* @since 1.0.0
*
* @param string $version A string version to convert.
*
* @return integer
*/
protected function get_version_number( $version ) {
preg_match( '/(\d+)\.(\d+)\.(\d+)/', $version, $matches );
if ( count( $matches ) == 0 ) {
return false;
}
$number = '';
$number .= ( strlen( $matches[1] ) == 1 ) ? '0' . $matches[1] : $matches[1];
$number .= ( strlen( $matches[2] ) == 1 ) ? '0' . $matches[2] : $matches[2];
$number .= ( strlen( $matches[3] ) == 1 ) ? '0' . $matches[3] : $matches[3];
return intval( $number );
}
/**
* Returns a list of files at a given path.
*
* @param string $path path for search
*/
private function find_files( $path ) {
return $this->find_file_or_folders( $path, true );
}
/**
* Returns a list of folders at a given path.
*
* @param string $path path for search
*/
/*private function find_folders( $path ) {
return $this->find_file_or_folders( $path, false );
}*/
/**
* Returns a list of files or folders at a given path.
*
* @param string $path path for search
* @param bool $files files or folders?
*/
private function find_file_or_folders( $path, $areFiles = true ) {
if ( ! is_dir( $path ) ) {
return [];
}
$entries = scandir( $path );
if ( empty( $entries ) ) {
return [];
}
$files = [];
foreach ( $entries as $entryName ) {
if ( $entryName == '.' || $entryName == '..' ) {
continue;
}
$filename = $path . '/' . $entryName;
if ( ( $areFiles && is_file( $filename ) ) || ( ! $areFiles && is_dir( $filename ) ) ) {
$files[] = [
'path' => str_replace( "\\", "/", $filename ),
'name' => $areFiles ? str_replace( '.php', '', $entryName ) : $entryName
];
}
}
return $files;
}
/**
* Gets php classes defined in a specified file.
*
* @param string $path
*
* @throws Exception
*/
private function get_classes( $path ) {
$phpCode = file_get_contents( $path );
$classes = [];
if ( ! function_exists( 'token_get_all' ) ) {
throw new Exception( __( 'There is no PHP Tokenizer extension installed on your server, you cannot use the token_get_all function.', 'wbcr_factory_480' ) );
}
$tokens = token_get_all( $phpCode );
$count = count( $tokens );
for ( $i = 2; $i < $count; $i ++ ) {
if ( is_array( $tokens ) && $tokens[ $i - 2 ][0] == T_CLASS && $tokens[ $i - 1 ][0] == T_WHITESPACE && $tokens[ $i ][0] == T_STRING ) {
$extends = null;
if ( $tokens[ $i + 2 ][0] == T_EXTENDS && $tokens[ $i + 4 ][0] == T_STRING ) {
$extends = $tokens[ $i + 4 ][1];
}
$class_name = $tokens[ $i ][1];
$classes[ $path ] = [
'name' => $class_name,
'extends' => $extends
];
}
}
/**
* result example:
*
* $classes['/plugin/items/filename.php'] = array(
* 'name' => 'PluginNameItem',
* 'extendes' => 'PluginNameItemBase'
* )
*/
return $classes;
}
}

View File

@@ -0,0 +1,296 @@
<?php
namespace WBCR\Factory_480;
use Wbcr_Factory480_Plugin;
// Exit if accessed directly
if( !defined('ABSPATH') ) {
exit;
}
/**
* A class to manage notices.
*
* @since 1.0.0
*/
/**
* A group of classes and methods to create and manage notices.
*
* @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
* @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
*
* @package factory-notices
* @since 1.0.0
*/
class Notices {
/**
* @var Wbcr_Factory480_Plugin
*/
protected $plugin;
/**
* @var array
*/
protected $notices = [];
/**
* @var array
*/
protected $default_where = [
'plugins',
'themes',
'dashboard',
'edit',
'settings',
'dashboard-network',
'plugins-network',
'themes-network',
'settings-network',
];
/**
* @var array
*/
private $dissmised_notices;
/**
* Инициализируем уведомлений сразу после загрузки модуля уведомлений
*
* @param Wbcr_Factory480_Plugin $plugin
*/
public function __construct($plugin)
{
//default notices
//---
$this->plugin = $plugin;
$this->dissmised_notices = $this->plugin->getPopulateOption('factory_dismissed_notices', []);
add_action('current_screen', [$this, 'currentScreenAction']);
if( defined('DOING_AJAX') && DOING_AJAX ) {
add_action('wp_ajax_' . $this->plugin->getPluginName() . '_dismiss_notice', [
$this,
'dismiss_notice'
]);
}
}
/**
* Регистрирует экшены для работы с уведомлениями на текущем экране странице.
* Уведомления собираются через фильтр wbcr_factory_admin_notices, если в массиве уведомлений,
* хотя бы одно, соответствует условиям в параметре $notice['where'], то метод печает вспомогательные скрипты и уведомления.
*/
public function currentScreenAction()
{
/**
* @since 2.1.2 - Добавлен, модуль factory_notices_000 был удален. Поэтому в этому хуке мы заменили префикс на factory_480
*/
$this->notices = apply_filters('wbcr/factory/admin_notices', $this->notices, $this->plugin->getPluginName());
if( count($this->notices) == 0 ) {
return;
}
$screen = get_current_screen();
$has_notices = false;
foreach((array)$this->notices as $notice) {
if( !isset($notice['id']) ) {
continue;
}
$where = !isset($notice['where']) || empty($notice['where']) ? $this->default_where : $notice['where'];
if( in_array($screen->base, $where) && !$this->is_dissmissed($notice['id']) ) {
$has_notices = true;
break;
};
}
if( $has_notices ) {
add_action('admin_footer', [$this, 'print_js_code']);
$this->show_notices();
}
}
/**
* Показывает все зарегистрированные уведомления для текущего плагина.
* Уведомления показываются только на определенных страницах через параметр $notice['where'],
* если уведомление ранее было скрыто или не соотвествует правилам $notice['where'], оно не будет показано!
*/
public function show_notices()
{
if( count($this->notices) == 0 ) {
return;
}
if( !current_user_can('activate_plugins') || !current_user_can('edit_plugins') || !current_user_can('install_plugins') ) {
return;
}
$screen = get_current_screen();
foreach($this->notices as $notice) {
if( !isset($notice['id']) ) {
continue;
}
$where = !isset($notice['where']) || empty($notice['where']) ? $this->default_where : $notice['where'];
if( in_array($screen->base, $where) && !$this->is_dissmissed($notice['id']) ) {
if( $this->plugin->isNetworkActive() ) {
if( current_user_can('manage_network') ) {
add_action('network_admin_notices', function () use ($notice) {
$this->show_notice($notice);
});
add_action('admin_notices', function () use ($notice) {
$this->show_notice($notice);
});
}
} else {
add_action('admin_notices', function () use ($notice) {
$this->show_notice($notice);
});
}
};
}
}
/**
* Показывает уведомление, по переданным параметрам
*
* @param array $data - Параметры уведомления
* $data['id'] - Индентификатор уведомления
* $data['type'] - Тип уведомления (error, warning, success)
* $notice['where'] - На каких страницах показывать уведомление ('plugins', 'dashboard', 'edit')
* $data['text'] - Текст уведомления
* $data['dismissible'] - Если true, уведомление будет с кнопкой закрыть
* $data['dismiss_expires'] - Когда снова показать уведомление, нужно указывать время в unix timestamp.
* Пример time() + 3600 (1ч), уведомление будет скрыто на 1 час.
* $data['classes'] - Произвольный классы для контейнера уведомления.
*/
public function show_notice($data)
{
$settings = wp_parse_args($data, [
'id' => null,
'text' => null,
'type' => 'error',
'dismissible' => false,
'dismiss_expires' => 0,
'classes' => []
]);
if( empty($settings['id']) || empty($settings['text']) ) {
return;
}
$plugin_name = str_replace('_', '-', $this->plugin->getPluginName());
$classes = array_merge([
'notice',
'notice-' . $settings['type'],
$plugin_name . '-factory-notice'
], $settings['classes']);
if( $settings['dismissible'] ) {
$classes[] = 'is-dismissible';
$classes[] = $plugin_name . '-factory-notice-dismiss';
}
?>
<div data-name="wbcr_factory_notice_<?php echo esc_attr($data['id']) ?>" data-expires="<?php echo esc_attr($settings['dismiss_expires']) ?>" data-nonce="<?php echo wp_create_nonce($this->plugin->getPluginName() . '_factory_dismiss_notice'); ?>" class="<?php echo esc_attr(implode(' ', $classes)) ?>">
<?php echo $data['text'] ?>
</div>
<?php
}
/**
* Когда пользователь нажимает кнопку закрыть уведомление,
* отправляется ajax запрос с вызовом текущего метода
*/
public function dismiss_notice()
{
if( !current_user_can('activate_plugins') || !current_user_can('edit_plugins') || !current_user_can('install_plugins') ) {
wp_die(-1, 403);
}
check_admin_referer($this->plugin->getPluginName() . '_factory_dismiss_notice', 'nonce');
// Имя уведомления (идентификатор)
$name = $this->plugin->request->post('name', null, true);
// Время в Unix timestamp, по истечению, которого уведомление снова будет показано
// Если передан 0, то уведомление будет скрыто навсегда
$expires = $this->plugin->request->post('expires', 0, 'intval');
if( empty($name) ) {
wp_send_json_error(['error_message' => 'You must pass the notification "Name"! Action was rejected.']);
}
$notices = $this->plugin->getPopulateOption("factory_dismissed_notices", []);
if( !empty($notices) ) {
foreach((array)$notices as $notice_id => $notice_expires) {
if( $notice_expires !== 0 && $notice_expires < time() ) {
unset($notices[$notice_id]);
}
}
}
$notices[$name] = $expires;
$this->plugin->updatePopulateOption('factory_dismissed_notices', $notices);
wp_send_json_success();
}
/**
* Javascript code
* Печает в подвале страницы код, для взаимодействия с сервером через ajax,
* код используется при нажатии на кнопку закрыть уведомление. *
*/
public function print_js_code()
{
$plugin_name = str_replace('_', '-', $this->plugin->getPluginName());
?>
<script type="text/javascript">
jQuery(function($) {
$(document).on('click', '.<?php echo $plugin_name; ?>-factory-notice-dismiss .notice-dismiss', function() {
$.post(ajaxurl, {
'action': '<?php echo $this->plugin->getPluginName(); ?>_dismiss_notice',
'name': $(this).parent().data('name'),
'expires': $(this).parent().data('expires'),
'nonce': $(this).parent().attr('data-nonce')
});
});
});
</script>
<?php
}
/**
* Проверяет скрыто уведоление или нет
*
* @param string $notice_id - имя уведомления
*
* @return bool
*/
protected function is_dissmissed($notice_id)
{
if( !empty($this->dissmised_notices) && isset($this->dissmised_notices['wbcr_factory_notice_' . $notice_id]) ) {
$expires = (int)$this->dissmised_notices['wbcr_factory_notice_' . $notice_id];
return $expires === 0 || $expires > time();
}
return false;
}
}

View File

@@ -0,0 +1,432 @@
<?php
namespace WBCR\Factory_480;
// Exit if accessed directly
use Exception;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Трейт используется для расширения базового класса плагина Wbcr_Factory480_Base, позволяя работать с опциями плагина.
*
* Этот трейт является оберткой для Wordpress функций get_option, get_site_option, update_option, update_site_option,
* delete_option, delete_site_option. Основная задача была получать, обновлять, удалять опции без использования префиксов,
* чтобы класс выполнял эту работу за программиста. В дополнение, трейт содержит методы для полной выгрузки всех опций
* плагина, что позволяет при инициализации плагина автоматически выгрузить все существующие опции плагина в объектный
* кеш. Все опции, с которыми работает плагин, могут быть отфильтрованы.
*
* Документация по трейту: https://webcraftic.atlassian.net/wiki/spaces/FFD/pages/393805831/
* Документация по созданию плагина: https://webcraftic.atlassian.net/wiki/spaces/CNCFC/pages/327828
* Репозиторий: https://github.com/alexkovalevv
*
* @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
* @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
*
* @since 4.0.8 - Добавлен
* @package factory-core
*/
trait Options {
/**
* Абстрактный метод, должен быть реализован в классе использующем этот трейт. Метод позволяет получить префикс
* плагина для формирования имен опций в базе данных Wordpress. У опций должно быть свое пространство имен,
* иначе может быть конфликт с другими плагинами или с сами ядром Wordpress.
*
* @since 4.0.8 - Добавлен
* @return string Возвращает префикс плагина. Пример: wbcr_clearfy_
*/
abstract public function getPrefix();
/**
* Выгружает все опции плагина в объектный кеш. Плагин может получить любую свою опцию без запроса к базе данных.
* Метод ускоряет работу плагина, если опций очень много.
*
* Используется только один раз при инициализации плагина.
*
* @since 4.0.8 - Добавлен
*/
public function loadAllOptions() {
global $wpdb;
$is_option_loaded = wp_cache_get( $this->getPrefix() . 'all_options_loaded', $this->getPrefix() . 'options' );
if ( false === $is_option_loaded ) {
$result = $wpdb->get_results( "SELECT option_name, option_value FROM {$wpdb->options} WHERE option_name LIKE '{$this->getPrefix()}%'" );
$options = [];
if ( ! empty( $result ) ) {
wp_cache_add( $this->getPrefix() . 'all_options_loaded', 1, $this->getPrefix() . 'options' );
foreach ( $result as $option ) {
$value = maybe_unserialize( $option->option_value );
$value = $this->normalizeValue( $value );
wp_cache_add( $option->option_name, $value, $this->getPrefix() . 'options' );
$options[ $option->option_name ] = $value;
}
/**
* Действие, которое будет выполнено, когда все опции плагина будут выгружены.
*
* @since 4.0.9 - Добавлен
*
* @param string $plugin_name Имя плагина
* @param array $options Ассоциативный массив опций плагина
*/
do_action( 'wbcr/factory/all_options_loaded', $options, $this->plugin_name );
}
}
}
/**
* Выгружает все сетевые опции плагина в объектный кеш. Плагин может получить любую свою опцию без запроса к базе
* данных. Метод ускоряет работу плагина, если опций очень много.
*
* Используется и работает только в режиме мультисайтов, один раз при инициализации плагина.!
*
* @since 4.0.8 - Добавлен
* @return void
*/
public function loadAllNetworkOptions() {
global $wpdb;
$network_id = (int) get_current_network_id();
$is_option_loaded = wp_cache_get( $network_id . ":" . $this->getPrefix() . 'all_options_loaded', $this->getPrefix() . 'network_options' );
if ( false === $is_option_loaded ) {
wp_cache_add_global_groups( [ $this->getPrefix() . 'network_options' ] );
$result = $wpdb->get_results( "SELECT meta_key, meta_value FROM {$wpdb->sitemeta} WHERE site_id='{$network_id}' AND meta_key LIKE '{$this->getPrefix()}%'" );
$options = [];
if ( ! empty( $result ) ) {
wp_cache_add( $network_id . ":" . $this->getPrefix() . 'all_options_loaded', 1, $this->getPrefix() . 'network_options' );
foreach ( $result as $option ) {
$value = maybe_unserialize( $option->meta_value );
$value = $this->normalizeValue( $value );
$cache_key = $network_id . ":" . $option->meta_key;
wp_cache_add( $cache_key, $value, $this->getPrefix() . 'network_options' );
$options[ $option->meta_key ] = $value;
}
/**
*
* Действие, которое будет выполнено, когда все сетевые опции плагина будут выгружены.
*
* @since 4.0.9 - Добавлен
*
* @param array $options Ассоциативный массив опций плагина
* @param string $plugin_name Имя плагина
*/
do_action( 'wbcr/factory/all_network_options_loaded', $options, $this->plugin_name );
}
}
}
/**
* Позволяет получить популярную опцию. В случае если плагин установлен для сети (в режиме мультисайтов),
* то метод возвращает опции только для сети, иначе метод возвращает опцию для текущего сайта. Работает
* на основе self::getOption и self::getNetworkOption, смотрите полную реализацию в этих методах.
*
* @since 4.0.8 - Добавлен
*
* @param string $option_name Имя опции без префикса.
* @param mixed $default Значение по умолчанию. Если опции нет в базе данных, будет возвращено это значение. По умолчанию false
*
* @return mixed Возвращает значение опции, если это сериализованная строка, то автоматически распаковывает ее.
*/
public function getPopulateOption( $option_name, $default = false ) {
if ( $this->isNetworkActive() ) {
$option_value = $this->getNetworkOption( $option_name, $default );
} else {
$option_value = $this->getOption( $option_name, $default );
}
/**
* Фильтр позволяет отфильтровать возвращаемое значение популярной опции.
*
* @since 4.0.9 - Добавлен
*
* @param mixed $option_value Значение опции
* @param string $option_name Имя опции
* @param mixed $default Значение опции по умолчанию
*/
return apply_filters( "wbcr/factory/populate_option_{$option_name}", $option_value, $option_name, $default );
}
/**
* Позволяет получить сетевые опции. Если плагин установлен для сети (в режиме мультисайтов), то
* метод возвращает опции только для сети, иначе метод возвращает опцию для текущего сайта.
*
* Опция вытаскивается из объектного кеша, после выполнения метода self:loadAllNetworkOptions,
* а не напрямую из базы данных, из-за чего при работе с некоторыми кеширующими плагинами,
* может быть странное поведение в работе плагина.
*
* @since 4.0.8 - Добавлен
*
* @param string $option_name Имя опции без префикса.
* @param mixed $default Значение по умолчанию. Если опции нет в базе данных, будет возвращено это значение. По умолчанию false
*
* @return mixed Возвращает значение опции, если это сериализованная строка, то автоматически распаковывает ее.
*/
public function getNetworkOption( $option_name, $default = false ) {
if ( empty( $option_name ) || ! is_string( $option_name ) ) {
throw new Exception( 'Option name must be a string and must not be empty.' );
}
if ( ! is_multisite() ) {
return $this->getOption( $option_name, $default );
}
$this->loadAllNetworkOptions();
$network_id = (int) get_current_network_id();
$cache_key = $network_id . ':' . $this->getPrefix() . $option_name;
$option_value = wp_cache_get( $cache_key, $this->getPrefix() . 'network_options' );
if ( false === $option_value ) {
$option_value = $default;
}
/**
* Фильтр позволяет отфильтровать возвращаемое значение сетевой опции.
*
* @since 4.0.9 - Добавлен
*
* @param mixed $option_value Значение опции
* @param string $option_name Имя опции
* @param mixed $default Значение опции по умолчанию
* @param int $network_id ID сети
*/
return apply_filters( "wbcr/factory/network_option_{$option_name}", $option_value, $option_name, $default, $network_id );
}
/**
* Метод позволяет получить опцию для текущего сайта. Опция вытаскивается из объектного кеша, после выполнения метода
* self:loadAllOptions, а не напрямую из базы данных, из-за чего при работе с некоторыми кеширующими плагинами,
* может быть странное поведение в работе плагина.
*
* @since 4.0.0 - Добавлен
* @since 4.0.8 - Полностью переделан
*
* @param string $option_name Имя опции без префикса.
* @param mixed $default Значение по умолчанию. Если опции нет в базе данных, будет возвращено это значение. По умолчанию false
*
* @return mixed
*/
public function getOption( $option_name, $default = false ) {
if ( empty( $option_name ) || ! is_string( $option_name ) ) {
throw new Exception( 'Option name must be a string and must not be empty.' );
}
$this->loadAllOptions();
$option_value = wp_cache_get( $this->getPrefix() . $option_name, $this->getPrefix() . 'options' );
if ( false === $option_value ) {
$option_value = $default;
}
/**
* Фильтр позволяет отфильтровать возвращаемое значение опции сайта.
*
* @since 4.0.9 - Добавлен
*
* @param mixed $option_value Значение опции
* @param string $option_name Имя опции
* @param mixed $default Значение опции по умолчанию
*/
return apply_filters( "wbcr/factory/option_{$option_name}", $option_value, $option_name, $default );
}
/**
* Позволяет обновить популярную опцию в базе данных. Если плагин установлен для сети (в режиме мультисайтов), то метод обновляет опцию
* только в таблице sitemeta, иначе в таблице options для текущего сайта.
*
* @param string $option_name Имя опции без префикса.
* @param mixed $option_value Значение опции. Может принимать массив или объект.
*/
public function updatePopulateOption( $option_name, $option_value ) {
if ( $this->isNetworkActive() ) {
$this->updateNetworkOption( $option_name, $option_value );
} else {
$this->updateOption( $option_name, $option_value );
}
}
/**
* Обновляет сетевую опцию в БД таблица sitemeta. После успешного обновления опции в базе данных, метод добавляет опцию в объектный кеш,
* чтобы плагин мог приступить к работе с этой опцией незамедлительно.
*
* @since 4.0.8 - Добавлен
*
* @param string $option_name Имя опции без префикса.
* @param mixed $option_value Значение опции. Может принимать массив или объект.
*/
public function updateNetworkOption( $option_name, $option_value ) {
$network_id = (int) get_current_network_id();
$cache_key = $network_id . ':' . $this->getPrefix() . $option_name;
wp_cache_set( $cache_key, $option_value, $this->getPrefix() . 'network_options' );
update_site_option( $this->getPrefix() . $option_name, $option_value );
/**
* Действие будет выполнено, когда сетевая опция будет обновлена.
*
* @since 4.0.8 - Добавлен
*
* @param string $option_name Имя опции без префикса.
* @param mixed $option_value Значение опции. Может принимать массив или объект.
*/
do_action( "wbcr/factory/update_network_option", $option_name, $option_value );
}
/**
* Обновляет опцию сайта в БД таблица options. После успешного обновления опции в базе данных, метод добавляет опцию в объектный кеш,
* чтобы плагин мог приступить к работе с этой опцией незамедлительно.
*
* @since 4.0.0 - Добавлен
* @since 4.0.8 - Полностью переделан
*
* @param string $option_name Имя опции без префикса.
* @param mixed $option_value Значение опции. Может принимать массив или объект.
*
* @return bool
*/
public function updateOption( $option_name, $option_value ) {
wp_cache_set( $this->getPrefix() . $option_name, $option_value, $this->getPrefix() . 'options' );
$result = update_option( $this->getPrefix() . $option_name, $option_value );
/**
* @since 4.0.8
*
* @param string $option_name
*
* @param mixed $option_value
*/
do_action( "wbcr/factory/update_option", $option_name, $option_value );
return $result;
}
/**
* Позволяет удалять популярную опцию в базе данных. Если плагин установлен для сети (в режиме мультисайтов), то метод удаляет опцию
* только в таблице sitemeta, иначе в таблице options для текущего сайта.
*
* @since 4.0.0 - Добавлен
*
* @param string $option_name Имя опции без префикса.
*/
public function deletePopulateOption( $option_name ) {
if ( $this->isNetworkActive() ) {
$this->deleteNetworkOption( $option_name );
} else {
$this->deleteOption( $option_name );
}
}
/**
* Удаляет сетевую.опцию в БД таблица sitemeta, а если опция есть в кеше, индивидуально удаляет опцию из кеша.
*
* @since 4.0.0 - Добавлен
*
* @param string $option_name Имя опции без префикса.
*
* @return bool Возвращает true, если опция удалена успешно, false в случае ошибки.
*/
public function deleteNetworkOption( $option_name ) {
$network_id = (int) get_current_network_id();
$cache_key = $network_id . ':' . $this->getPrefix() . $option_name;
$delete_cache = wp_cache_delete( $cache_key, $this->getPrefix() . 'network_options' );
$delete_opt1 = delete_site_option( $this->getPrefix() . $option_name );
return $delete_cache && $delete_opt1;
}
/**
* Удаляет опцию сайта в БД таблица options, а если опция есть в кеше, индивидуально удаляет опцию из кеша.
*
* @since 4.0.0 - Добавлен
*
* @param string $option_name Имя опции без префикса.
*
* @return bool Возвращает true, если опция удалена успешно, false в случае ошибки.
*/
public function deleteOption( $option_name ) {
$delete_cache = wp_cache_delete( $this->getPrefix() . $option_name, $this->getPrefix() . 'options' );
// todo: удалить, когда большая часть пользователей обновятся до современных релизов
$delete_opt1 = delete_option( $this->getPrefix() . $option_name . '_is_active' );
$delete_opt2 = delete_option( $this->getPrefix() . $option_name );
return $delete_cache && $delete_opt1 && $delete_opt2;
}
/**
* Сбрасывает объектный кеш. Может использоваться для перезагрузки опций плагина и Wordpress в целом.
*
* @since 4.0.0 - Добавлен
* @return bool Возвращает true, если кеш сброшен успешно, false в случае ошибки.
*/
public function flushOptionsCache() {
return wp_cache_flush();
}
/**
* Позволяет получить полное имя опции с префиксом. Может быть использовано в тех случаях, где нужно получить
* полное имя опции.
*
* @since 4.0.0 - Добавлен
*
* @param string $option_name Имя опции без префикса.
*
* @return null|string Возвращает имя опции с префиксом. Например wbcr_clearfy_{options_name}
*/
public function getOptionName( $option_name ) {
$option_name = trim( rtrim( $option_name ) );
if ( empty( $option_name ) || ! is_string( $option_name ) ) {
return null;
}
return $this->getPrefix() . $option_name;
}
/**
* Позволяет нормализовать данные. В некоторых методах этого трейта, ожидаются данные определенного типа, чтобы
* выполнить различные логические операции. Как раз в этом случае этот метод можно использовать, чтобы привести
* все сырые данные в строгий тип. Такое решение позволит избежать ошибок в работе программиста.
*
* @since 4.0.0 - Добавлен
*
* @param mixed $data Данные, которые нужно нормализовать.
*
* @return mixed Возвращает нормализованное значение.
* - Если передана строка "true" или "false" вернет булево значение.
* - Если передана строка "1" или "0" вернет число.
*/
public function normalizeValue( $data ) {
if ( is_string( $data ) ) {
$check_string = rtrim( trim( $data ) );
if ( $check_string == "1" || $check_string == "0" ) {
return intval( $data );
} else if ( $check_string === 'false' ) {
return false;
} else if ( $check_string === 'true' ) {
return true;
}
}
return $data;
}
}

View File

@@ -0,0 +1,907 @@
<?php
// Exit if accessed directly
if( !defined('ABSPATH') ) {
exit;
}
/**
* Основной класс для создания плагина.
*
* Это основной класс плагина. который отвечает за подключение модулей фреймворка, линзирование, обновление,
* миграции разрабатываемого плагина. При создании нового плагина, вы должны создать основной класс реализующий
* функции плагина, этот класс будет наследовать текущий.
*
* Смотрите подробную инструкцию по созданию плагина и экземпляра основного класса в документации по созданию
* плагина для Wordpress.
*
* Документация по классу: https://webcraftic.atlassian.net/wiki/spaces/FFD/pages/393052164
* Документация по созданию плагина: https://webcraftic.atlassian.net/wiki/spaces/CNCFC/pages/327828
*
* @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
* @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
*
* @since 1.0.0
* @package factory-core
*
*/
abstract class Wbcr_Factory480_Plugin extends Wbcr_Factory480_Base {
/**
* Instance class Wbcr_Factory480_Request, required manages http requests
*
* @see https://webcraftic.atlassian.net/wiki/spaces/FFD/pages/390561806
* @var Wbcr_Factory480_Request
*/
public $request;
/**
* @see https://webcraftic.atlassian.net/wiki/spaces/FFD/pages/393936924
* @var \WBCR\Factory_480\Premium\Provider
*/
public $premium;
/**
* The Bootstrap Manager class
*
* @var Wbcr_FactoryBootstrap482_Manager
*/
public $bootstrap;
/**
* The Bootstrap Manager class
*
* @var Wbcr_FactoryForms480_Manager
*/
public $forms;
/**
* Простой массив со списком зарегистрированных классов унаследованных от Wbcr_Factory480_Activator.
* Классы активации используются для упаковки набора функций, которые нужно выполнить во время
* активации плагина.
*
* @var array[] Wbcr_Factory480_Activator
*/
protected $activator_class = [];
/**
* Ассоциативный массив со списком уже загруженных модулей фреймворка. Используется для того, чтобы
* проверить, каких модули уже были загружены, а какие еще нет.
*
* @var array
*/
private $loaded_factory_modules = [];
/**
* Ассоциативный массив со списком аддонов плагина. Аддоны плагина являются частью одного проекта,
* но не как отдельный плагин.
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 4.2.0
* @var array
*/
private $loaded_plugin_components = [];
/**
* The Adverts Manager class
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 4.1.9
* @var WBCR\Factory_Adverts_159\Base
*/
private $adverts;
/**
* The Logger class
*
* @author Artem Prihodko <webtemyk@yandex.ru>
* @since 4.3.7
* @var WBCR\Factory_Logger_149\Logger
*/
public $logger;
/**
* Инициализирует компоненты фреймворка и плагина.
*
* @param array $data A set of plugin data.
*
* @param string $plugin_path A full path to the main plugin file.
*
* @throws Exception
* @since 1.0.0
*
*/
public function __construct($plugin_path, $data)
{
parent::__construct($plugin_path, $data);
$this->request = new Wbcr_Factory480_Request();
//$this->route = new Wbcr_Factory480_Route();
// INIT PLUGIN FRAMEWORK MODULES
// Framework modules should always be loaded first,
// since all other functions depend on them.
$this->init_framework_modules();
// INIT PLUGIN MIGRATIONS
$this->init_plugin_migrations();
// INIT PLUGIN NOTICES
$this->init_plugin_notices();
// INIT PLUGIN PREMIUM FEATURES
// License manager should be installed earlier
// so that other modules can access it.
$this->init_plugin_premium_features();
// INIT PLUGIN UPDATES
$this->init_plugin_updates();
// init actions
$this->register_plugin_hooks();
// INIT PLUGIN COMPONENTS
$this->init_plugin_components();
if( wp_doing_ajax() && isset($_REQUEST['action']) ) {
if( "wfactory-480-intall-component" == $_REQUEST['action'] ) {
add_action('wp_ajax_wfactory-480-intall-component', [$this, 'ajax_handler_install_components']);
}
if( "wfactory-480-prepare-component" == $_REQUEST['action'] ) {
add_action('wp_ajax_wfactory-480-prepare-component', [$this, 'ajax_handler_prepare_component']);
}
if( "wfactory-480-creativemotion-install-plugin" == $_REQUEST['action'] ) {
add_action('wp_ajax_wfactory-480-creativemotion-install-plugin', [
$this,
'ajax_handler_install_creativemotion_plugins'
]);
}
}
}
// Ajax Handlers
// --------------------------------------------------------
public function ajax_handler_install_components()
{
require_once FACTORY_480_DIR . '/ajax/install-addons.php';
wfactory_480_install_components($this);
}
public function ajax_handler_prepare_component()
{
require_once FACTORY_480_DIR . '/ajax/install-addons.php';
wfactory_480_prepare_component($this);
}
public function ajax_handler_install_creativemotion_plugins()
{
require_once FACTORY_480_DIR . '/ajax/install-addons.php';
wfactory_480_creativemotion_install_plugin($this);
}
// --------------------------------------------------------
/**
* Устанавливает класс менеджер, которому плагин будет делегировать подключение ресурсов (картинок,
* скриптов, стилей) фреймворка.
*
* @param Wbcr_FactoryBootstrap482_Manager $bootstrap
*/
public function setBootstap(Wbcr_FactoryBootstrap482_Manager $bootstrap)
{
$this->bootstrap = $bootstrap;
}
/**
* Устанавливает класс менеджер, которому будет делегирована работа с html формами фреймворка.
*
* @param Wbcr_FactoryForms480_Manager $forms
*/
public function setForms(Wbcr_FactoryForms480_Manager $forms)
{
$this->forms = $forms;
}
/**
* Устанавливает класс менеджер, которому будет делегирована работа с объявлениями в Wordpress
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 4.1.9
*/
public function set_adverts_manager($class_name)
{
if( empty($this->adverts) && $this->render_adverts ) {
$this->adverts = new $class_name($this, $this->adverts_settings);
}
}
/**
* Устанавливает класс менеджер, которому будет делегирована работа с объявлениями в Wordpress
*
* @param string $class_name Logger class name
* @param array $settings Logger settings
*
* @author Artem Prihodko <webtemyk@yandex.ru>
* @since 4.3.7
*/
public function set_logger($class_name, $settings = [])
{
if( empty($this->logger) ) {
$this->logger = new $class_name($this, $settings);
}
}
/**
* Устанавливает класс провайдера лицензий
*
* С помощью этого класса, мы проверяем валидность лицензий и получаем дополнительную информацию
* о лицензии и ее покупателе. Класс используется в премиум менеджере.
*
* @param string $name Имя провайдер
* @param string $class_name Имя класса провайдера
*
* @since 4.1.6 - Добавлен
*
*/
public function set_license_provider($name, $class_name)
{
if( !isset(WBCR\Factory_480\Premium\Manager::$providers[$name]) ) {
WBCR\Factory_480\Premium\Manager::$providers[$name] = $class_name;
}
}
/**
* Регистрируем класс репозитория
*
* С помощью этого класса мы реализиуем доставку и откат обновлений плагина, на сайт пользователя.
* Скачиваение премиум версий происходит по защенному каналу. Класс используется в менеджере обновлений.
*
* @param string $name Имя репозитория
* @param string $class_name Имя класса репозитория
*
* @since 4.1.7 - Добавлен
*
*/
public function set_update_repository($name, $class_name)
{
if( !isset(WBCR\Factory_480\Updates\Upgrader::$repositories[$name]) ) {
WBCR\Factory_480\Updates\Upgrader::$repositories[$name] = $class_name;
}
}
/**
* Позволяет получить экземпляр менеджера объявления
*
* Доступен глобально через метод app(), чаще всего используется для создания точек для ротации
* рекламных объявлений.
*
* @return \WBCR\Factory_Adverts_159\Base
* @since 1.1
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
*/
public function get_adverts_manager()
{
return $this->adverts;
}
/**
* Устанавливает текстовый домен для плагина. Текстовый домен берется из заголовка входного
* файла плагина.
*
* @since 4.2.5 - Добавлены 2 аргумента $text_domain, $plugin_dir. Теперь protected
* @since 4.0.8 - Добавлен
*
* @see https://codex.wordpress.org/I18n_for_WordPress_Developers
* @see https://webcraftic.atlassian.net/wiki/spaces/CNCFC/pages/327828 - документация по входному файлу
*/
protected function set_text_domain($text_domain, $plugin_dir)
{
if( empty($text_domain) || empty($plugin_dir) ) {
return;
}
$locale = apply_filters('plugin_locale', is_admin() ? get_user_locale() : get_locale(), $text_domain);
$mofile = $text_domain . '-' . $locale . '.mo';
if( !load_textdomain($text_domain, $plugin_dir . '/languages/' . $mofile) ) {
load_muplugin_textdomain($text_domain);
}
}
public function newScriptList()
{
return new Wbcr_Factory480_ScriptList($this);
}
public function newStyleList()
{
return new Wbcr_Factory480_StyleList($this);
}
/**
* Все страницы плагина создаются через специальную обертку, за которую отвечает модуль
* фреймворка pages. Разработчик создает собственный класс, унаследованный от
* Wbcr_FactoryPages480_AdminPage, а затем регистрирует его через этот метод.
* Метод выполняет подключение класса страницы и регистрирует его в модуле фреймворка
* pages.
*
* Больше информации о создании и регистрации страниц, вы можете узнать из документации по созданию
* страниц плагина.
*
* @see https://webcraftic.atlassian.net/wiki/spaces/CNCFC/pages/222887949 - документация по созданию страниц
*
* @param string $class_name Имя регистрируемого класса страницы. Пример: WCL_Page_Name.
* Регистрируемый класс должен быть унаследован от класса Wbcr_FactoryPages480_AdminPage.
* @param string $file_path Абсолютный путь к файлу с классом страницы.
*
* @throws Exception
*/
public function registerPage($class_name, $file_path)
{
// todo: https://webcraftic.atlassian.net/projects/PCS/issues/PCS-88
// if ( $this->isNetworkActive() && ! is_network_admin() ) {
// return;
// }
if( !file_exists($file_path) ) {
throw new Exception('The page file was not found by the path {' . $file_path . '} you set.');
}
require_once($file_path);
if( !class_exists($class_name) ) {
throw new Exception('A class with this name {' . $class_name . '} does not exist.');
}
if( !class_exists('Wbcr_FactoryPages480') ) {
throw new Exception('The factory_pages_480 module is not included.');
}
Wbcr_FactoryPages480::register($this, $class_name);
}
/**
* Произвольные типы записей в плагине, создаются через специальную обертку, за которую отвечает
* модуль фреймворка types. Разработчик создает собственный класс, унаследованный от
* Wbcr_FactoryTypes000_Type, а затем регистрирует его через этот метод. Метод выполняет
* подключение класса с новым типом записи и регистрирует его в модуле фреймворка types. *
*
* @param string $class_name Имя регистрируемого класса страницы. Пример: WCL_Type_Name.
* Регистрируемый класс должен быть унаследован от класса Wbcr_FactoryTypes000_Type.
* @param string $file_path Абсолютный путь к файлу с классом страницы.
*
* @throws Exception
* @deprecated 4.1.7 You cannot use it!
*/
public function registerType($class_name, $file_path)
{
throw new Exception('As of factory core module 4.1.7, the "registerType" method is deprecated. You cannot use it!');
}
/**
* Registers a class to activate the plugin.
*
* @param string $className class name of the plugin activator.
*
* @return void
* @since 1.0.0
*
*/
public function registerActivation($className)
{
$this->activator_class[] = $className;
}
/* end services region
/* -------------------------------------------------------------*/
/**
* It's invoked on plugin activation. Don't excite it directly.
*
* @return void
* @since 1.0.0
*/
public function activation_hook()
{
/**
* @since 4.1.1 - change hook name
*/
if( apply_filters("wbcr/factory_480/cancel_plugin_activation_{$this->plugin_name}", false) ) {
return;
}
/**
* wbcr_factory_480_plugin_activation
*
* @since 4.1.1 - deprecated
*/
wbcr_factory_480_do_action_deprecated('wbcr_factory_480_plugin_activation', [
$this
], '4.1.1', "wbcr/factory/plugin_activation");
/**
* wbcr/factory/plugin_activation
*
* @since 4.1.2 - deprecated
*/
wbcr_factory_480_do_action_deprecated('wbcr/factory/plugin_activation', [
$this
], '4.1.2', "wbcr/factory/before_plugin_activation");
/**
* wbcr/factory/before_plugin_activation
*
* @since 4.1.2 - added
*/
do_action('wbcr/factory/before_plugin_activation', $this);
/**
* # wbcr/factory/plugin_{$this->plugin_name}_activation
*
* @since 4.1.2 - deprecated
*/
wbcr_factory_480_do_action_deprecated("wbcr/factory/plugin_{$this->plugin_name}_activation", [
$this
], '4.1.2', "wbcr/factory/before_plugin_{$this->plugin_name}_activation");
/**
* wbcr_factory_480_plugin_activation_' . $this->plugin_name
*
* @since 4.1.1 - deprecated
*/
wbcr_factory_480_do_action_deprecated('wbcr_factory_480_plugin_activation_' . $this->plugin_name, [
$this
], '4.1.1', "wbcr/factory/before_plugin_{$this->plugin_name}_activation");
/**
* wbcr/factory/plugin_{$this->plugin_name}_activation
*
* @since 4.1.2 - added
*/
do_action("wbcr/factory/plugin_{$this->plugin_name}_activation", $this);
if( !empty($this->activator_class) ) {
foreach((array)$this->activator_class as $activator_class) {
$activator = new $activator_class($this);
$activator->activate();
}
}
/**
* @since 4.1.2 - added
*/
do_action('wbcr/factory/plugin_activated', $this);
/**
* @since 4.1.2 - added
*/
do_action("wbcr/factory/plugin_{$this->plugin_name}_activated", $this);
}
/**
* It's invoked on plugin deactionvation. Don't excite it directly.
*
* @return void
* @since 1.0.0
*/
public function deactivation_hook()
{
/**
* @since 4.1.1 - change hook name
*/
if( apply_filters("wbcr/factory_480/cancel_plugin_deactivation_{$this->plugin_name}", false) ) {
return;
}
/**
* wbcr_factory_480_plugin_deactivation
*
* @since 4.1.1 - deprecated
*/
wbcr_factory_480_do_action_deprecated('wbcr_factory_480_plugin_deactivation', [
$this
], '4.1.1', "wbcr/factory/plugin_deactivation");
/**
* wbcr/factory/plugin_deactivation
*
* @since 4.1.2 - deprecated
*/
wbcr_factory_480_do_action_deprecated('wbcr/factory/plugin_deactivation', [
$this
], '4.1.2', "wbcr/factory/before_plugin_deactivation");
/**
* wbcr/factory/plugin_deactivation
*
* @since 4.1.2 - added
*/
do_action('wbcr/factory/plugin_deactivation', $this);
/**
* wbcr_factory_480_plugin_deactivation_ . $this->plugin_name
*
* @since 4.1.1 - deprecated
*/
wbcr_factory_480_do_action_deprecated('wbcr_factory_480_plugin_deactivation_' . $this->plugin_name, [
$this
], '4.1.1', "wbcr/factory/before_plugin_{$this->plugin_name}_deactivation");
/**
* wbcr/factory/plugin_{$this->plugin_name}_deactivation
*
* @since 4.1.2 - deprecated
*/
wbcr_factory_480_do_action_deprecated("wbcr/factory/plugin_{$this->plugin_name}_deactivation", [
$this
], '4.1.2', "wbcr/factory/before_plugin_{$this->plugin_name}_deactivation");
/**
* @since 4.1.2 - added
*/
do_action("wbcr/factory/before_plugin_{$this->plugin_name}_deactivation");
if( !empty($this->activator_class) ) {
foreach((array)$this->activator_class as $activator_class) {
$activator = new $activator_class($this);
$activator->deactivate();
}
}
/**
* @since 4.1.2 - added
*/
do_action('wbcr/factory/plugin_deactivated', $this);
/**
* @since 4.1.2 - added
*/
do_action("wbcr/factory/plugin_{$this->plugin_name}_deactivated", $this);
}
/**
* Возвращает ссылку на внутреннюю страницу плагина
*
* @param string $page_id
*
* @sicne: 4.0.8
* @return string|void
* @throws Exception
*/
public function getPluginPageUrl($page_id, $args = [])
{
if( !class_exists('Wbcr_FactoryPages480') ) {
throw new Exception('The factory_pages_480 module is not included.');
}
if( !is_admin() ) {
_doing_it_wrong(__METHOD__, __('You cannot use this feature on the frontend.'), '4.0.8');
return null;
}
return Wbcr_FactoryPages480::getPageUrl($this, $page_id, $args);
}
/**
* Allows you to get a button to install the plugin component
*
* @param $component_type
* @param $slug
* param $premium
*
* @return \WBCR\Factory_480\Components\Install_Button
*/
public function get_install_component_button($component_type, $slug)
{
require_once FACTORY_480_DIR . '/includes/components/class-install-component-button.php';
return new \WBCR\Factory_480\Components\Install_Button($this, $component_type, $slug);
}
/**
* Allows you to get a button to delete the plugin component
*
* @param $component_type
* @param $slug
*
* @return \WBCR\Factory_480\Components\Delete_Button
*/
public function get_delete_component_button($component_type, $slug)
{
require_once FACTORY_480_DIR . '/includes/components/class-delete-component-button.php';
return new WBCR\Factory_480\Components\Delete_Button($this, $component_type, $slug);
}
/**
* @param string $component_name
*
* @return bool
*/
public function is_activate_component($component_name)
{
if( !is_string($component_name) ) {
return false;
}
$deactivate_components = $this->getPopulateOption('deactive_preinstall_components', []);
if( !is_array($deactivate_components) ) {
$deactivate_components = [];
}
if( $deactivate_components && in_array($component_name, $deactivate_components) ) {
return false;
}
return true;
}
/**
* @param string $component_name
*
* @return bool
*/
public function activate_component($component_name)
{
if( $this->is_activate_component($component_name) ) {
return true;
}
do_action('wfactory/pre_activate_component', $component_name);
$deactivate_components = $this->getPopulateOption('deactive_preinstall_components', []);
if( !empty($deactivate_components) && is_array($deactivate_components) ) {
$index = array_search($component_name, $deactivate_components);
unset($deactivate_components[$index]);
}
if( empty($deactivate_components) ) {
$this->deletePopulateOption('deactive_preinstall_components');
} else {
$this->updatePopulateOption('deactive_preinstall_components', $deactivate_components);
}
return true;
}
/**
* @param string $component_name
*
* @return bool
*/
public function deactivate_component($component_name)
{
if( !$this->is_activate_component($component_name) ) {
return true;
}
do_action('wfactory/pre_deactivate_component', $component_name);
$deactivate_components = $this->getPopulateOption('deactive_preinstall_components', []);
if( !empty($deactivate_components) && is_array($deactivate_components) ) {
$deactivate_components[] = $component_name;
} else {
$deactivate_components = [];
$deactivate_components[] = $component_name;
}
$this->updatePopulateOption('deactive_preinstall_components', $deactivate_components);
do_action('wfactory/deactivated_component', $component_name);
return true;
}
/**
* Загружает аддоны для плагина, как часть проекта, а не как отдельный плагин
*
* @throws \Exception
*/
private function init_plugin_components()
{
$load_plugin_components = $this->get_load_plugin_components();
if( empty($load_plugin_components) || !is_array($load_plugin_components) ) {
return;
}
foreach($load_plugin_components as $component_ID => $component) {
if( !isset($this->loaded_plugin_components[$component_ID]) ) {
if( !isset($component['autoload']) || !isset($component['plugin_prefix']) ) {
throw new Exception(sprintf("Component %s cannot be loaded, you must specify the path to the component autoload file and plugin prefix!", $component_ID));
}
$prefix = rtrim($component['plugin_prefix'], '_') . '_';
if( defined($prefix . 'PLUGIN_ACTIVE') ) {
continue;
}
$autoload_file = trailingslashit($this->get_paths()->absolute) . $component['autoload'];
if( !file_exists($autoload_file) ) {
throw new Exception(sprintf("Component %s autoload file not found!", $component_ID));
}
$plugin_var_name = strtolower($prefix . 'plugin');
global $$plugin_var_name;
$$plugin_var_name = $this;
require_once($autoload_file);
if( defined($prefix . 'PLUGIN_ACTIVE') ) {
$this->loaded_plugin_components[$component_ID] = [
'plugin_dir' => constant($prefix . 'PLUGIN_DIR'),
'plugin_url' => constant($prefix . 'PLUGIN_URL'),
'plugin_base' => constant($prefix . 'PLUGIN_BASE'),
'text_domain' => constant($prefix . 'TEXT_DOMAIN'),
'plugin_version' => constant($prefix . 'PLUGIN_VERSION')
];
/**
* Оповещает внешние приложения, что компонент плагина был загружен
*
* @param array $load_plugin_components Информация о загруженном компоненте
* @param string $plugin_name Имя плагина
*/
do_action("wbcr/factory/component_{$component_ID}_loaded", $this->loaded_plugin_components[$component_ID], $this->getPluginName());
} else {
throw new Exception(sprintf("Сomponent %s does not meet development standards!", $component_ID));
}
}
}
}
/**
* Загружает специальные модули для расширения Factory фреймворка.
* Разработчик плагина сам выбирает, какие модули ему нужны для
* создания плагина.
*
* Модули фреймворка хранятся в libs/factory/framework
*
* @return void
* @throws Exception
*/
private function init_framework_modules()
{
if( !empty($this->load_factory_modules) ) {
foreach((array)$this->load_factory_modules as $module) {
$scope = isset($module[2]) ? $module[2] : 'all';
if( $scope == 'all' || (is_admin() && $scope == 'admin') || (!is_admin() && $scope == 'public') ) {
if( !file_exists($this->get_paths()->absolute . '/' . $module[0] . '/boot.php') ) {
throw new Exception('Module ' . $module[1] . ' is not included.');
}
$module_boot_file = $this->get_paths()->absolute . '/' . $module[0] . '/boot.php';
require_once $module_boot_file;
$this->loaded_factory_modules[$module[1]] = $module_boot_file;
do_action('wbcr_' . $module[1] . '_plugin_created', $this);
}
}
}
/**
* @since 4.1.1 - deprecated
*/
wbcr_factory_480_do_action_deprecated('wbcr_factory_480_core_modules_loaded-' . $this->plugin_name, [], '4.1.1', "wbcr/factory_480/modules_loaded-" . $this->plugin_name);
/**
* @since 4.1.1 - add
*/
do_action('wbcr/factory_480/modules_loaded-' . $this->plugin_name);
}
/**
* Setups actions related with the Factory Plugin.
*
* @since 1.0.0
*/
private function register_plugin_hooks()
{
add_action('plugins_loaded', function () {
$this->set_text_domain($this->plugin_text_domain, $this->paths->absolute);
if( !empty($this->loaded_plugin_components) ) {
foreach($this->loaded_plugin_components as $component) {
if( empty($component['text_domain']) ) {
continue;
}
$this->set_text_domain($component['text_domain'], $component['plugin_dir']);
}
}
});
if( is_admin() ) {
add_filter('wbcr_factory_480_core_admin_allow_multisite', '__return_true');
register_activation_hook($this->get_paths()->main_file, [$this, 'activation_hook']);
register_deactivation_hook($this->get_paths()->main_file, [$this, 'deactivation_hook']);
}
}
/**
* Инициализируем миграции плагина
*
* @return void
* @throws Exception
* @since 4.1.1
*/
protected function init_plugin_migrations()
{
new WBCR\Factory_480\Migrations($this);
}
/**
* Инициализируем уведомления плагина
*
* @return void
* @since 4.1.1
*/
protected function init_plugin_notices()
{
new Wbcr\Factory_480\Notices($this);
}
/**
* Создает нового рабочего для проверки обновлений и апгрейда текущего плагина.
*
* @param array $data
*
* @return void
* @throws Exception
* @since 4.1.1
*
*/
protected function init_plugin_updates()
{
if( $this->has_updates ) {
new WBCR\Factory_480\Updates\Upgrader($this);
}
}
/**
* Начинает инициализацию лицензирования текущего плагина. Доступ к менеджеру лицензий можно
* получить через свойство license_manager.
*
* Дополнительно создает рабочего, чтобы совершить апгрейд до премиум версии
* и запустить проверку обновлений для этого модуля.
*
* @throws Exception
* @since 4.1.1
*/
protected function init_plugin_premium_features()
{
if( !$this->has_premium || !$this->license_settings ) {
$this->premium = null;
return;
}
// Создаем экземляр премиум менеджера, мы сможем к нему обращаться глобально.
$this->premium = WBCR\Factory_480\Premium\Manager::instance($this, $this->license_settings);
// Подключаем премиум апгрейдер
if( isset($this->license_settings['has_updates']) && $this->license_settings['has_updates'] ) {
new WBCR\Factory_480\Updates\Premium_Upgrader($this);
}
}
}

View File

@@ -0,0 +1,592 @@
<?php
// Exit if accessed directly
if( !defined('ABSPATH') ) {
exit;
}
/**
* Базовый класс для создания нового плагина. Полную реализацию класса смотрите в Wbcr_Factory480_Plugin
*
* Документация по классу: https://webcraftic.atlassian.net/wiki/spaces/FFD/pages/392724484
* Документация по созданию плагина: https://webcraftic.atlassian.net/wiki/spaces/CNCFC/pages/327828
* Репозиторий: https://github.com/alexkovalevv
*
* @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
* @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
*
* @since 1.0.0
* @package factory-core
*/
class Wbcr_Factory480_Base {
use WBCR\Factory_480\Options;
/**
* Обязательное свойство. Префикс, используется для создания пространство имен.
* Чаще всего используется на именования опций в базе данных. Также может быть
* использован для именования полей html форм, создания уникальных имен, хуков.
* Пример: wrio_
*
* Для префикса всегда используете нижнее подчеркивание справа!
*
* @var string
*/
protected $prefix;
/**
* Обязательное свойство. Заголовок плагина. Используете в интерфейсе плагина,
* может быть использован в уведомлениях для администратора, чтобы пользователь
* мог понять, с каким плагином он ведет коммуникацию. Пример: Robin image optimizer
*
* @var string
*/
protected $plugin_title;
/**
* Обязательное свойство. Имя плагина. Используется аналогично префиксу, но с небольшим
* отличием. Имя плагина имеет человеку понятную строку, которую можно использовать в
* именовании хуков, созданию условной логики. Допустимые символы [A-z0-9_].
* Пример: wbcr_clearfy
*
* @var string
*/
protected $plugin_name;
protected $plugin_slug;
/**
* Обязательное свойство. Версия плагина в формате 0.0.0. Допустимые символы [0-9.]
*
* @var string
*/
protected $plugin_version;
/**
* Обязательное свойство. Текстовый домен плагина, используется для подключения файлов
* переводов. Рекомендуется использовать slug плагина, идентичный slug в репозитории
* Wordpress.org
*
* @since 4.1.1
* @var string
*/
protected $plugin_text_domain;
/**
* Обязательное свойство. Информация для поддержки клиента. Для начала работы плагина,
* достаточно только указать адрес лендинга в атрибут url. На лендинге должны быть
* созданы страницы features, pricing, support, docs. Если страницы (features, pricing,
* support, docs) не могут иметь такие же адреса, вы можете наложить карту адресов в
* атрибуте pages_map. К примеру: я создал страницу "Pro Features" и она имеет адрес
* {site}/premium-features, для pages_map в атрибуте features, я указал, что адрес
* страницы со списком функций имеет слаг premium-features. Теперь плагин будет понимать,
* что адрес страницы со списком функций будет таким:
* https://robin-image-optimizer.webcraftic.com/premium-features.
*
* Это свойство заполняется для того, чтобы в процессе разработки вы могли использовать
* экземпляр класса \WBCR\Factory_480\Entities\Support, для получения информации о сайте плагина.
* Тем самым вы избавляете себя от жесткого прописывания ссылок на лендинг плагина и
* можете изменить все ссылки в одном месте.
*
* @var array
*/
protected $support_details;
/**
* Включение/отключение обновлений для бесплатного плагина. Если вашего плагина нет в репозитори
* Wordpress.org, вы можете включить собственный режим обновлений, например через GitHub или
* собственный репозиторий. Если установлено true, плагин будет проверять наличие обновлений
* для этого плагина.
*
* @var bool
*/
protected $has_updates = false;
/**
* Настройка обновлений для бесплатного плагина. Если вы хотите настроить обновления для
* бесплатного плагина через собственный репозиторий (например: github), вам нужно указать имя
* репозитория и slug плагина. Slug может быть идентичен имени репозитория в github. Для Wordpress.org
* эти настройки не обязательны, так как в wordpress ядре есть встроенные функции для обновлений
* плагинов и тем.
*
* @var array
*/
protected $updates_settings = [];
/**
* Включение/отключение премиум версии для плагина. Если вы создаете бесплатный плагин и хотите
* реализовать для него премиум версию, вам нужно начать с этого свойства. Если свойство установлено,
* как true, при инициализации плагина будут подключены функции лицензирования, проверки обновлений
* для премиум версии.
*
* @var bool
*/
protected $has_premium = false;
/**
* Настройки лицензирования
*
* Лицензирование плагина может быть реализовано для любого провайдера,
* к примеру: freemius, codecanyon, templatemonster, вам нужно указать только настройки для
* взаимодействия с выбранным вами провайдером. Каждая реализация провайдера лицензий может иметь
* индивидуальный настройки, в этом примере приведены настройки для freemius провайдера
* WBCR\Factory_480\Premium\Provider > WBCR\Factory_Freemius_170\Premium\Provider
*
* На текущий момент существует только реализация для freemius провайдера.
*
* Для премиум плагина вы должны также указать настройки обновлений. Атрибут has_updates
* включает/отключает обновления для премиум плагина, в атрибуте updates_settings вы указываете
* дополнительные настройки обновлений.
*
* @var array
*/
protected $license_settings = [];
/**
* Переключатель внутренней рекламы в плагине
*
* Если установить true, то плагин будет показывать рекламу компании в интерфейсе Wordpress.
* Рекламный модуль может отображать рекламу внутри инрефейса плагина, на странице dashboard
* и создавать сквозные уведомления на всех страницах админ панели Wordpress.
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 4.1.9
* @var bool
*/
protected $render_adverts = false;
/**
* Настройки внутренней рекламы компании
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 4.1.9
* @var array
*/
protected $adverts_settings = [];
/**
* Обязательное свойство. Подключаемые модули фреймворка.
*
* Модули фреймворка позволяют расширять его функциональность.
*
* @var array {
* Array with information about the loadable module
* {type} string $module [0] Relative path to the module directory
* {type} string $module [1] Module name with prefix 000
* {type} string $module [2] Scope:
* admin - Module will be loaded only in the admin panel,
* public - Module will be loaded only on the frontend
* all - Module will be loaded everywhere
* }
*/
protected $load_factory_modules = [
['libs/factory/bootstrap', 'factory_bootstrap_482', 'admin'],
['libs/factory/forms', 'factory_forms_480', 'admin'],
['libs/factory/pages', 'factory_pages_480', 'admin'],
];
/**
* Не обязательное свойство. Список подключаемых компонентов плагина.
*
* Компоненты плагина, это независимые плагины, которые расширяют возможности текущего плагина.
* Вы должны указать файл для автозагрузки компонента и префикс плагина, чтобы фреймворк
* мог обращаться к классам и константам компонентов.
*
*
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 4.2.0 Добавлен
* @var array Пример данных
* array(
* 'component_ID' => array(
* 'autoload' => 'relative_path/autoload_filename.php',
* 'plugin_prefix' => 'WPRFX_'
* ),
* // Реальный пример
* 'cyrlitera' => array(
* 'autoload' => 'components/cyrlitera/clearfy.php',
* 'plugin_prefix' => 'WCTR_'
* ),
* )
*/
protected $load_plugin_components = [];
/**
* Экземпляр класса \WBCR\Factory_480\Entities\Support используется для получения информации
* о сайте плагина. Чаще всего используется для получения ссылки на страницу с тарифами или
* ссылки на форму обратной связи. Встроен механизм отслеживания по utm меткам.
*
* @var \WBCR\Factory_480\Entities\Support
*/
protected $support;
/**
* Экземпляр класса \WBCR\Factory_480\Entities\Paths используется для получения информации о
* путях плагина. Часто используется для получения путей или ссылок на место хранения плагина
* или его входного файла.
*
* @var \WBCR\Factory_480\Entities\Paths
*/
protected $paths;
/**
* Абсолютный путь к входному файлу плагина: C://server/site.dev/wp-content/plugins/plugin_name/plugin_name.php
*
* @var string
*/
private $plugin_file;
/**
* Свойство хранит сырые настройки плагина, а также дополнительные настройки, которые не описаны
* в интерфейсе класса.
*
* @var array
*/
private $plugin_data;
/**
* Конструктор:
* - Заполняет свойства класса из сырых данных плагина
* - Выполняет проверку на обязательные настройки
* - Инициализирует сущности support и paths
*
* @param string $plugin_file
* @param array $data
*
* @throws Exception
* @since 4.0.8 - добавлена дополнительная логика
*
* @since 4.1.1 - добавил две сущности support, paths. Удалил свойства, plugin_build
* plugin_assembly, main_file, plugin_root, relative_path, plugin_url
*/
public function __construct($plugin_file, $data)
{
$this->plugin_file = $plugin_file;
$this->plugin_data = $data;
foreach((array)$data as $option_name => $option_value) {
if( property_exists($this, $option_name) ) {
$this->$option_name = $option_value;
}
}
if( empty($this->prefix) || empty($this->plugin_name) || empty($this->plugin_title) || empty($this->plugin_version) || empty($this->plugin_text_domain) ) {
throw new Exception('One of the required attributes has not been passed (prefix, plugin_title, plugin_name, plugin_version, plugin_text_domain).');
}
$this->support = new \WBCR\Factory_480\Entities\Support($this->support_details);
$this->paths = new \WBCR\Factory_480\Entities\Paths($plugin_file);
// used only in the module 'updates'
$this->plugin_slug = !empty($this->plugin_name) ? $this->plugin_name : basename($plugin_file);
}
/**
* При обновлении фреймворка, некоторые свойства класса были удалены. Однако плагины на старом
* фреймворке по прежнему используют удаленные свойства. С помощью этого магического метода мы
* добавляем совместимость со старыми плагинами, но при этом выводим предупреждение, что нужно
* обновить некоторые свойства.
*
* @param string $name Имя свойства класса.
*
* @return mixed
*/
public function __get($name)
{
$deprecated_props = [
'plugin_build',
'plugin_assembly',
'main_file',
'plugin_root',
'relative_path',
'plugin_url'
];
if( in_array($name, $deprecated_props) ) {
$deprecated_message = 'In version 4.1.1 of the Factory framework, the class properties ';
$deprecated_message .= '(' . implode(',', $deprecated_props) . ')';
$deprecated_message .= 'have been removed. To get plugin paths, use the new paths property.' . PHP_EOL;
$backtrace = debug_backtrace();
if( !empty($backtrace) && isset($backtrace[1]) ) {
$deprecated_message .= 'BACKTRACE:(';
$deprecated_message .= 'File: ' . $backtrace[1]['file'];
$deprecated_message .= 'Function: ' . $backtrace[1]['function'];
$deprecated_message .= 'Line: ' . $backtrace[1]['line'];
$deprecated_message .= ')';
}
_deprecated_argument(__METHOD__, '4.1.1', $deprecated_message);
switch( $name ) {
case 'plugin_build':
return null;
break;
case 'plugin_assembly':
return null;
break;
case 'main_file':
return $this->get_paths()->main_file;
break;
case 'plugin_root':
return $this->get_paths()->absolute;
break;
case 'relative_path':
return $this->get_paths()->basename;
break;
case 'plugin_url':
return $this->get_paths()->url;
break;
}
}
return null;
}
/**
* При обновлении фреймворка, некоторые методы класса были удалены. Однако плагины на старом фреймворке
* по прежнему используют удаленные методы. С помощью этого магического метода мы добавляем совместимость
* со старыми плагинами, но при этом выводим предупреждение, что нужно обновить некоторые методы.
*
* @param string $name Имя метода класса.
* @param array $arguments Массив аргументов метода класса.
*
* @return stdClass|null
* @throws Exception
*/
public function __call($name, $arguments)
{
$deprecated_methods = [
'getPluginBuild',
'getPluginAssembly',
'getPluginPathInfo'
];
if( in_array($name, $deprecated_methods) ) {
$deprecated_message = 'In version 4.1.1 of the Factory framework, methods (' . implode(',', $deprecated_methods) . ') have been removed.';
$backtrace = debug_backtrace();
if( !empty($backtrace) && isset($backtrace[1]) ) {
$deprecated_message .= 'BACKTRACE:(';
$deprecated_message .= 'File: ' . $backtrace[1]['file'];
$deprecated_message .= 'Function: ' . $backtrace[1]['function'];
$deprecated_message .= 'Line: ' . $backtrace[1]['line'];
$deprecated_message .= ')';
}
_deprecated_argument(__METHOD__, '4.1.1', $deprecated_message);
if( 'getPluginPathInfo' == $name ) {
$object = new stdClass;
$object->main_file = $this->get_paths()->main_file;
$object->plugin_root = $this->get_paths()->absolute;
$object->relative_path = $this->get_paths()->basename;
$object->plugin_url = $this->get_paths()->url;
return $object;
}
}
throw new Exception("Method {$name} does not exist");
}
/**
* Проверяет, включен ли премиум для этого плагина или нет.
*
* @return bool Возвращает true, если премиум пакет включен для этого плагина.
* См. Wbcr_Factory480_Base::has_premium
*/
public function has_premium()
{
return $this->has_premium;
}
/**
* Позволяет получить заголовок плагина.
*
* @return string Возвращает заголовок плагина. См. Wbcr_Factory480_Base::plugin_title
*/
public function getPluginTitle()
{
return apply_filters('wbcr/factory/plugin_title', $this->plugin_title, $this->getPluginName());
}
/**
* Позволяет получить префикс плагина.
*
* @return string Возвращает префикс плагина.См. Wbcr_Factory480_Base::prefix
*/
public function getPrefix()
{
return $this->prefix;
}
/**
* Позволяет получить имя плагина.
*
* @return string Возвращает имя плагина. См. Wbcr_Factory480_Base::plugin_name
*/
public function getPluginName()
{
return $this->plugin_name;
}
/**
* Позволяет получить версию плагина.
*
* @return string Возвращает версию плагина. См. Wbcr_Factory480_Base::plugin_version
*/
public function getPluginVersion()
{
return $this->plugin_version;
}
/**
* Позволяет получить список подключаемых к плагином компонентов
*
* @return array
* @since 4.2.0
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
*/
public function get_load_plugin_components()
{
return $this->load_plugin_components;
}
/**
* Предоставляет доступ к сырым данным плагина. Может быть полезен, если вы хотите получить
* какие-то данные не описанные в интерфейсе этого плагина.
*
* @param string $attr_name Имя атрибута, который нужно получить. Идентично ключу в массиве
* Wbcr_Factory480_Base::plugin_data
*
* @return null
*/
public function getPluginInfoAttr($attr_name)
{
if( isset($this->plugin_data[$attr_name]) ) {
return $this->plugin_data[$attr_name];
}
return null;
}
/**
* Предоставляет доступ к экземпляру класса \WBCR\Factory_480\Entities\Support.
*
* @return \WBCR\Factory_480\Entities\Support
*/
public function get_support()
{
return $this->support;
}
/**
* Предоставляет доступ к экземпляру класса \WBCR\Factory_480\Entities\Paths.
*
* @return \WBCR\Factory_480\Entities\Paths
*/
public function get_paths()
{
return $this->paths;
}
/**
* Позволяет получить сырые данные плагина в виде объекта StdClass.
*
* @return object Возвращает объект с сырыми данными плагина. См. Wbcr_Factory480_Base::plugin_data
*/
public function getPluginInfo()
{
return (object)$this->plugin_data;
}
/**
* Проверяет права пользователя
*
* @return bool
* @since 4.2.0 Добавлен
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
*/
public function current_user_can($capability = 'manage_options')
{
// Просмотр страниц: read_pages
// Просмотр уведомлений: read_notices
// Редактирование: edit_forms
if( 'manage_options' == $capability && is_multisite() && $this->isNetworkActive() ) {
$capability = 'manage_network';
}
return current_user_can($capability);
}
/**
* Проверят, находится ли пользователь в панели усправления сетью сайтов
*
* @return bool
* @since 4.0.8 Добавлен
*
*/
public function isNetworkAdmin()
{
return is_multisite() && is_network_admin();
}
/**
* Проверяет активирован ли плагин для сети. Если проект работает в режиме мультисайтов..
*
* @return bool Если true, плагин активирован для сети или в текущий момент активируется для сети.
* @since 4.0.8 Добавлен
*/
public function isNetworkActive()
{
// Makes sure the plugin is defined before trying to use it
if( !function_exists('is_plugin_active_for_network') ) {
require_once(ABSPATH . '/wp-admin/includes/plugin.php');
}
$activate = is_plugin_active_for_network($this->get_paths()->basename);
if( !$activate && $this->isNetworkAdmin() && isset($_GET['action']) && $_GET['action'] == 'activate' ) {
return isset($_GET['networkwide']) && 1 == (int)$_GET['networkwide'];
}
return $activate;
}
/**
* Позволяет получить все активные сайты сети. Если проект работает в режиме мультисайтов.
*
* @return array|int
* @since 4.0.8
*/
public function getActiveSites($args = ['archived' => 0, 'mature' => 0, 'spam' => 0, 'deleted' => 0])
{
global $wp_version;
if( version_compare($wp_version, '4.6', '>=') ) {
return get_sites($args);
} else {
$converted_array = [];
$sites = wp_get_sites($args);
if( empty($sites) ) {
return $converted_array;
}
foreach((array)$sites as $key => $site) {
$obj = new stdClass();
foreach($site as $attr => $value) {
$obj->$attr = $value;
}
$converted_array[$key] = $obj;
}
return $converted_array;
}
}
}

View File

@@ -0,0 +1,115 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/*
* @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
* @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
*
* @package factory-core
*/
class Wbcr_Factory480_Request {
/**
* @param null $param
* @param bool|string $sanitize true/false or sanitize function name
* @param bool $default
* @param string $method_name
*
* @return array|bool|mixed
*/
private function getBody( $param, $sanitize = false, $default = false, $method_name = 'REQUEST' ) {
if ( empty( $param ) ) {
return null;
}
$sanitize_function_name = 'sanitize_text_field';
switch ( strtoupper( $method_name ) ) {
case 'GET':
$method = $_GET;
break;
case 'POST':
$method = $_POST;
break;
case 'REQUEST':
$method = $_REQUEST;
break;
}
if ( is_string( $sanitize ) && $sanitize !== $sanitize_function_name ) {
$sanitize_function_name = $sanitize;
}
if ( isset( $method[ $param ] ) ) {
if ( is_array( $method[ $param ] ) ) {
return ! empty( $sanitize ) ? $this->recursiveArrayMap( $sanitize_function_name, $method[ $param ] ) : $method[ $param ];
} else {
return ! empty( $sanitize ) ? call_user_func( $sanitize_function_name, $method[ $param ] ) : $method[ $param ];
}
}
return $default;
}
/**
* Recursive sanitation for an array
*
* @param string $function_name
* @param $array
*
* @return mixed
*/
public function recursiveArrayMap( $function_name, $array ) {
foreach ( $array as $key => &$value ) {
if ( is_array( $value ) ) {
$value = $this->recursiveArrayMap( $function_name, $value );
} else {
if ( ! function_exists( $function_name ) ) {
throw new Exception( 'Function ' . $function_name . 'is undefined.' );
}
$value = $function_name( $value );
}
}
return $array;
}
/**
* @param $param
* @param bool|string see method getBody
* @param bool $default
*
* @return mixed|null
*/
public function request( $param, $default = false, $sanitize = false ) {
return $this->getBody( $param, $sanitize, $default );
}
/**
* @param null $param
* @param bool|string see method getBody
* @param bool $default
*
* @return mixed|null
*/
public function get( $param, $default = false, $sanitize = false ) {
return $this->getBody( $param, $sanitize, $default, 'get' );
}
/**
* @param $param
* @param bool|string see method getBody
* @param bool $default
*
* @return mixed|null
*/
public function post( $param, $default = false, $sanitize = false ) {
return $this->getBody( $param, $sanitize, $default, 'post' );
}
}

View File

@@ -0,0 +1,294 @@
<?php
/**
* Class to check if the current WordPress and PHP versions meet our requirements
*
* @see Docs https://webcraftic.atlassian.net/wiki/spaces/FFD/pages/21692485/WFF+Requirements
*
* @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
* @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
*
* @version 2.0.0
* @since 4.0.9
*/
// @formatter:off
if ( ! class_exists( 'Wbcr_Factory480_Requirements' ) ) {
class Wbcr_Factory480_Requirements {
/**
* Factory framework version
*
* @var string
*/
protected $factory_version;
/**
* @var string
*/
protected $plugin_version;
/**
* Plugin file path
*
* @var string
*/
protected $plugin_file;
/**
* Plugin dir
*
* @var string
*/
protected $plugin_abs_path;
/**
* Plugin base dir
*
* @var string
*/
protected $plugin_basename;
/**
* Plugin url
*
* @var string
*/
protected $plugin_url;
/**
* Plugin prefix
*
* @var string
*/
protected $plugin_prefix;
/**
* Plugin name
*
* @var string
*/
protected $plugin_name;
/**
* Plugin title
*
* @var string
*/
protected $plugin_title = "(no title)";
/**
* @var string
*/
protected $plugin_text_domain;
/**
* Required PHP version
*
* @var string
*/
protected $required_php_version = '5.3';
/**
* Required WordPress version
*
* @var string
*/
protected $required_wp_version = '4.2.0';
/**
* Is this plugin already activated?
*
* @var bool
*/
protected $plugin_already_activate = false;
/**
* WFF_Requirements constructor.
*
* @param string $plugin_file
* @param array $plugin_info
*/
public function __construct( $plugin_file, array $plugin_info ) {
foreach ( (array) $plugin_info as $property => $value ) {
if ( property_exists( $this, $property ) ) {
$this->$property = $value;
}
}
$this->plugin_file = $plugin_file;
$this->plugin_abs_path = dirname( $plugin_file );
$this->plugin_basename = plugin_basename( $plugin_file );
$this->plugin_url = plugins_url( '', $plugin_file );
$plugin_info = get_file_data( $this->plugin_file, array(
'Version' => 'Version',
'FrameworkVersion' => 'Framework Version',
'TextDomain' => 'Text Domain'
), 'plugin' );
if ( isset( $plugin_info['FrameworkVersion'] ) ) {
$this->factory_version = $plugin_info['FrameworkVersion'];
}
if ( isset( $plugin_info['Version'] ) ) {
$this->plugin_version = $plugin_info['Version'];
}
if ( isset( $plugin_info['TextDomain'] ) ) {
$this->plugin_text_domain = $plugin_info['TextDomain'];
}
add_action( 'admin_init', array( $this, 'register_notices' ) );
}
public function get_plugin_version() {
return $this->plugin_version;
}
public function get_text_domain() {
return $this->plugin_text_domain;
}
/**
* @since 4.1.1
* @return void
*/
public function register_notices() {
if ( current_user_can( 'activate_plugins' ) && current_user_can( 'edit_plugins' ) && current_user_can( 'install_plugins' ) ) {
if ( is_multisite() ) {
add_action( 'network_admin_notices', array( $this, 'show_notice' ) );
if ( ! empty( $this->plugin_basename ) && in_array( $this->plugin_basename, (array) get_option( 'active_plugins', array() ) ) ) {
add_action( 'admin_notices', array( $this, 'show_notice' ) );
}
} else {
add_action( 'admin_notices', array( $this, 'show_notice' ) );
}
}
}
/**
* Shows the incompatibility notification.
*
* @since 4.1.1
* @return void
*/
public function show_notice() {
if ( $this->check() ) {
return;
}
echo '<div class="notice notice-error"><p>' . wp_kses($this->get_notice_text(), 'default') . '</p></div>';
}
/**
* The method checks the compatibility of the plugin with php and wordpress version.
*
* @since 4.1.1
* @return bool
*/
public function check() {
// Fix for ithemes sync. When the ithemes sync plugin accepts the request, set the WP_ADMIN constant,
// after which the plugin Clearfy begins to create errors, and how the logic of its work is broken.
// Solution to simply terminate the plugin if there is a request from ithemes sync
// --------------------------------------
if ( defined( 'DOING_AJAX' ) && DOING_AJAX && isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'ithemes_sync_request' ) {
return false;
}
if ( isset( $_GET['ithemes-sync-request'] ) && ! empty( $_GET['ithemes-sync-request'] ) ) {
return false;
}
// ----------------------------------------
if ( ! $this->check_php_compat() || ! $this->check_wp_compat() || $this->plugin_already_activate ) {
return false;
}
return true;
}
/**
* The method checks the compatibility of the plugin with the php version of the server.
*
* @return mixed
*/
public function check_php_compat() {
return version_compare( PHP_VERSION, $this->required_php_version, '>=' );
}
/**
* The method checks the compatibility of the plugin with the Wordpress version of the site.
*
* @return mixed
*/
public function check_wp_compat() {
// Get the WP Version global.
global $wp_version;
return version_compare( $wp_version, $this->required_wp_version, '>=' );
}
/**
* Method returns notification text
*
* @return string
*/
protected function get_notice_text() {
$notice_text = $notice_default_text = '';
$notice_default_text .= '<b>' . $this->plugin_title . ' ' . __( 'warning', '' ) . ':</b>' . '<br>';
$notice_default_text .= sprintf( __( 'The %s plugin has stopped.', 'wbcr_factory_templates_134' ), $this->plugin_title ) . ' ';
$notice_default_text .= __( 'Possible reasons:', '' ) . ' <br>';
$has_one = false;
if ( ! $this->check_php_compat() ) {
$has_one = true;
$notice_text .= '- ' . $this->get_php_incompat_text() . '<br>';
}
if ( ! $this->check_wp_compat() ) {
$has_one = true;
$notice_text .= '- ' . $this->get_wp_incompat_text() . '<br>';
}
if ( $this->plugin_already_activate ) {
$has_one = true;
$notice_text = '- ' . $this->get_plugin_already_activate_text() . '<br>';
}
if ( $has_one ) {
$notice_text = $notice_default_text . $notice_text;
}
return $notice_text;
}
/**
* @return string
*/
protected function get_php_incompat_text() {
return sprintf( __( 'You need to update the PHP version to %s or higher!', 'wbcr_factory_480' ), $this->required_php_version );
}
/**
* @return string
*/
protected function get_wp_incompat_text() {
return sprintf( __( 'You need to update WordPress to %s or higher!', 'wbcr_factory_480' ), $this->required_wp_version );
}
/**
* @return string
*/
protected function get_plugin_already_activate_text() {
return sprintf( __( 'Plugin %s is already activated, you are trying to activate it again.', 'wbcr_factory_480' ), $this->plugin_title );
}
}
}
// @formatter:on

View File

@@ -0,0 +1,57 @@
<?php
namespace WBCR\Factory_480\Components;
/**
* This file groups the settings for quick setup
*
* @author Webcraftic <wordpress.webraftic@gmail.com>
* @copyright (c) 16.09.2017, Webcraftic
* @version 1.0
*/
// Exit if accessed directly
if( !defined('ABSPATH') ) {
exit;
}
require_once 'class-install-component-button.php';
class Delete_Button extends Install_Button {
public $plugin;
/**
* @throws \Exception
*/
protected function build_wordpress()
{
parent::build_wordpress();
$this->action = 'delete';
$this->add_data('plugin-action', $this->action);
$this->remove_class('button-primary');
}
protected function build_internal()
{
// nothing
}
/**
* @param bool $echo
*
* @return string|void
*/
public function get_button()
{
$button = '<a href="#" class="' . implode(' ', $this->get_classes()) . '" ' . implode(' ', $this->get_data()) . '><span class="dashicons dashicons-trash"></span></a>';
if( $this->type == 'internal' || !$this->is_plugin_install() || $this->is_plugin_activate() ) {
$button = '';
}
return $button;
}
}

View File

@@ -0,0 +1,466 @@
<?php
namespace WBCR\Factory_480\Components;
/**
* This file groups the settings for quick setup
*
* @author Alex Kovalev <alex.kovalevv@gmail.com>
* @copyright (c) 16.09.2017, Webcraftic
* @version 1.0
*/
// Exit if accessed directly
if( !defined('ABSPATH') ) {
exit;
}
class Install_Button {
public $plugin;
protected $type;
protected $plugin_slug;
protected $classes = [
'button',
'wfactory-480-process-button'
];
protected $data = [];
protected $base_path;
protected $action;
protected $url;
/**
* @param string $group_name
*
* @throws \Exception
* @since 4.3.3
*/
public function __construct(\Wbcr_Factory480_Plugin $plugin, $type, $plugin_slug)
{
if( empty($type) || !is_string($plugin_slug) ) {
throw new \Exception('Empty type or plugin_slug attribute.');
}
$this->plugin = $plugin;
$this->type = $type;
$this->plugin_slug = $plugin_slug;
if( $this->type == 'wordpress' || $this->type == 'creativemotion' ) {
if( strpos(rtrim(trim($this->plugin_slug)), '/') !== false ) {
$this->base_path = $this->plugin_slug;
$base_path_parts = explode('/', $this->base_path);
if( sizeof($base_path_parts) === 2 ) {
$this->plugin_slug = $base_path_parts[0];
}
} else {
$this->base_path = $this->get_plugin_base_path_by_slug($this->plugin_slug);
}
$this->build_wordpress();
} else if( $this->type == 'internal' ) {
$this->build_internal();
} else {
throw new \Exception('Invalid button type.');
}
// Set default data
$this->add_data('storage', $this->type);
$this->add_data('i18n', \WBCR\Factory_Templates_134\Helpers::getEscapeJson($this->get_i18n()));
$this->add_data('wpnonce', wp_create_nonce('updates'));
}
// Удалить, через несколько версий!
// Добавлено в 4.3.3
//--------------------------------------------------------
/**
* todo: для совместимости со старыми плагинами
*
* @return string
* @throws \Exception
* @since 4.3.3
*/
public function getLink()
{
return $this->get_link();
}
/**
* todo: для совместимости со старыми плагинами
*
* @return string
* @since 4.3.3
*/
public function getButton()
{
return $this->get_button();
}
/**
* Print an install a link
* todo: для совместимости со старыми плагинами
*
* @throws \Exception
* @since 4.3.3
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
*/
public function renderLink()
{
echo esc_html($this->get_link());
}
/**
* Print an install button
* todo: для совместимости со старыми плагинами
*
* @throws \Exception
* @since 4.3.3
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
*/
public function renderButton()
{
$this->render_button();
}
/**
* todo: для совместимости со старыми плагинами
*
* @param $class
*
* @throws \Exception
* @since 4.3.3
*/
public function addClass($class)
{
$this->add_class($class);
}
/**
* todo: для совместимости со старыми плагинами
*
* @param $class
*
* @return bool
* @throws \Exception
* @since 4.3.3
*/
public function removeClass($class)
{
return $this->remove_class($class);
}
//--------------------------------------------------------
/**
* @return bool
* @since 4.3.3
*/
public function is_plugin_activate()
{
if( ($this->type == 'wordpress' || $this->type == 'creativemotion') && $this->is_plugin_install() ) {
require_once ABSPATH . '/wp-admin/includes/plugin.php';
return is_plugin_active($this->base_path);
} else if( $this->type == 'internal' ) {
$preinsatall_components = $this->plugin->getPopulateOption('deactive_preinstall_components', []);
return !in_array($this->plugin_slug, $preinsatall_components);
}
return false;
}
/**
* @return bool
* @since 4.3.3
*/
public function is_plugin_install()
{
if( $this->type == 'wordpress' || $this->type == 'creativemotion' ) {
if( empty($this->base_path) ) {
return false;
}
// Check if the function get_plugins() is registered. It is necessary for the front-end
// usually get_plugins() only works in the admin panel.
if( !function_exists('get_plugins') ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
$plugins = get_plugins();
if( isset($plugins[$this->base_path]) ) {
return true;
}
} else if( $this->type == 'internal' ) {
return true;
}
return false;
}
/**
* @param $class
*
* @throws \Exception
* @since 4.3.3
*/
public function add_class($class)
{
if( !is_string($class) ) {
throw new \Exception('Attribute class must be a string.');
}
$this->classes[] = $class;
}
/**
* @param $class
*
* @return bool
* @throws \Exception
* @since 4.3.3
*/
public function remove_class($class)
{
if( !is_string($class) ) {
throw new \Exception('Attribute class must be a string.');
}
$key = array_search($class, $this->classes);
if( isset($this->classes[$key]) ) {
unset($this->classes[$key]);
return true;
}
return false;
}
/**
* @param $name
* @param $value
*
* @throws \Exception
* @since 4.3.3
*/
public function add_data($name, $value)
{
if( !is_string($name) || !is_string($value) ) {
throw new \Exception('Attributes name and value must be a string.');
}
$this->data[$name] = $value;
}
/**
* @param $name
*
* @return bool
* @throws \Exception
* @since 4.3.3
*/
public function remove_data($name)
{
if( !is_string($name) ) {
throw new \Exception('Attribute name must be a string.');
}
if( isset($this->data[$name]) ) {
unset($this->data[$name]);
return true;
}
return false;
}
/**
* Print an install button
*
* @throws \Exception
* @since 4.3.3
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
*/
public function render_button()
{
echo $this->get_button();
}
/**
* @return string
* @since 4.3.3
*/
public function get_button()
{
$i18n = $this->get_i18n();
$button = '<a href="#" class="' . implode(' ', $this->get_classes()) . '" ' . implode(' ', $this->get_data()) . '>' . $i18n[$this->action] . '</a>';
return $button;
}
/**
* @return string
* @throws \Exception
* @since 4.3.3
*/
public function get_link()
{
$this->remove_class('button');
$this->remove_class('button-default');
$this->remove_class('button-primary');
//$this->add_class('link');
$this->add_class('button-link');
return $this->get_button();
}
/**
* Print an install a link
*
* @throws \Exception
* @since 4.3.3
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
*/
public function render_link()
{
echo $this->get_link();
}
/**
* @return array
* @since 4.3.3
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
*/
protected function get_data()
{
$data_to_print = [];
foreach((array)$this->data as $key => $value) {
$data_to_print[$key] = 'data-' . esc_attr($key) . '="' . esc_attr($value) . '"';
}
return $data_to_print;
}
/**
* @return array
* @since 4.3.3
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
*/
protected function get_classes()
{
return array_map('esc_attr', $this->classes);
}
/**
* @throws \Exception
* @since 4.3.3
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
*/
protected function build_wordpress()
{
if( ('wordpress' === $this->type || 'creativemotion' === $this->type) && !empty($this->base_path) ) {
$this->action = 'install';
if( $this->is_plugin_install() ) {
$this->action = 'deactivate';
if( !$this->is_plugin_activate() ) {
$this->action = 'activate';
}
}
$this->add_data('plugin-action', $this->action);
$this->add_data('slug', $this->plugin_slug);
$this->add_data('plugin', $this->base_path);
if( $this->action == 'activate' ) {
$this->add_class('button-primary');
} else {
$this->add_class('button-default');
}
}
}
/**
* Configurate button of internal components
*
* @throws \Exception
* @since 4.3.3
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
*/
protected function build_internal()
{
if( $this->type != 'internal' ) {
return;
}
$this->action = 'activate';
if( $this->is_plugin_activate() ) {
$this->action = 'deactivate';
}
$this->add_data('plugin-action', $this->action);
$this->add_data('plugin', $this->plugin_slug);
if( $this->action == 'activate' ) {
$this->add_class('button-primary');
} else {
$this->add_class('button-default');
}
}
/**
* Internalization for action buttons
*
* @return array
* @since 4.3.3
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
*/
protected function get_i18n()
{
return [
'activate' => __('Activate', 'wbcr_factory_480'),
'install' => __('Install', 'wbcr_factory_480'),
'deactivate' => __('Deactivate', 'wbcr_factory_480'),
'delete' => __('Delete', 'wbcr_factory_480'),
'loading' => __('Please wait...', 'wbcr_factory_480'),
'preparation' => __('Preparation...', 'wbcr_factory_480'),
'read' => __('Read more', 'wbcr_factory_480')
];
}
/**
* Allows you to get the base path to the plugin in the directory wp-content/plugins/
*
* @param $slug - slug for example "clearfy", "hide-login-page"
*
* @return int|null|string - "clearfy/clearfy.php"
*/
protected function get_plugin_base_path_by_slug($slug)
{
// Check if the function get_plugins() is registered. It is necessary for the front-end
// usually get_plugins() only works in the admin panel.
if( !function_exists('get_plugins') ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
$plugins = get_plugins();
foreach($plugins as $base_path => $plugin) {
if( strpos($base_path, rtrim(trim($slug))) !== false ) {
return $base_path;
}
}
return null;
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace WBCR\Factory_480\Entities;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/*
* @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
* @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
* @since 4.1.1
*/
class Paths {
public $absolute;
public $main_file;
public $relative;
public $url;
public $basename;
public $migrations;
protected $plugin_path;
public function __construct( $plugin_file ) {
$this->plugin_path = $plugin_file;
$this->main_file = $plugin_file;
$this->absolute = dirname( $plugin_file );
$this->basename = plugin_basename( $plugin_file );
$this->url = plugins_url( '', $plugin_file );
$this->migrations = $this->absolute . '/migrations';
}
}

View File

@@ -0,0 +1,124 @@
<?php
namespace WBCR\Factory_480\Entities;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/*
* @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
* @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
* @since 4.1.1
*/
class Support {
protected $plugin_name;
protected $site_url;
protected $features_page_slug = 'premium-features';
protected $pricing_page_slug = 'pricing';
protected $support_page_slug = 'support';
protected $docs_page_slug = 'docs';
/**
* Plugin_Site constructor.
*
* @param array $data
*/
public function __construct( array $data ) {
$this->site_url = isset( $data['url'] ) ? $data['url'] : null;
if ( isset( $data['pages_map'] ) && is_array( $data['pages_map'] ) ) {
foreach ( $data['pages_map'] as $key => $def_value ) {
$attr = $key . '_page_slug';
$this->{$attr} = isset( $data[ $key ] ) ? $data[ $key ] : $def_value;
}
}
}
/**
* @return string
*/
public function get_site_url( $track = false, $utm_content = null ) {
if ( $track ) {
return $this->get_tracking_page_url( $this->site_url, $utm_content );
}
return $this->site_url;
}
/**
* @return string
*/
public function get_features_url( $track = false, $utm_content = null ) {
if ( $track ) {
return $this->get_tracking_page_url( $this->features_page_slug, $utm_content );
}
return $this->get_site_url() . '/' . $this->features_page_slug;
}
/**
* @return string
*/
public function get_pricing_url( $track = false, $utm_content = null ) {
if ( $track ) {
return $this->get_tracking_page_url( $this->pricing_page_slug, $utm_content );
}
return $this->get_site_url() . '/' . $this->pricing_page_slug;
}
/**
* @return string
*/
public function get_contacts_url( $track = false, $utm_content = null ) {
if ( $track ) {
return $this->get_tracking_page_url( $this->support_page_slug, $utm_content );
}
return $this->get_site_url() . '/' . $this->support_page_slug;
}
/**
* @return string
*/
public function get_docs_url( $track = false, $utm_content = null ) {
if ( $track ) {
return $this->get_tracking_page_url( $this->docs_page_slug, $utm_content );
}
return $this->get_site_url() . '/' . $this->docs_page_slug;
}
/**
* @param null $page
* @param null $utm_content
* @param string $urm_source
*
* @return string
*/
public function get_tracking_page_url( $page = null, $utm_content = null, $urm_source = 'wordpress.org' ) {
$args = [ 'utm_source' => $urm_source ];
if ( ! empty( $plugin_name ) ) {
$args['utm_campaign'] = $plugin_name;
}
if ( ! empty( $utm_content ) ) {
$args['utm_content'] = $utm_content;
}
$raw_url = add_query_arg( $args, $this->get_site_url() . '/' . $page . '/' );
return esc_url( $raw_url );
}
}

View File

@@ -0,0 +1,205 @@
<?php
/**
* Factory Function Library
*
* @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
* @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
*
* @package factory-core
* @since 1.0.0
*/
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! function_exists( 'get_user_locale' ) ) {
function get_user_locale( $user_id = 0 ) {
$user = false;
if ( 0 === $user_id && function_exists( 'wp_get_current_user' ) ) {
$user = wp_get_current_user();
} else if ( $user_id instanceof WP_User ) {
$user = $user_id;
} else if ( $user_id && is_numeric( $user_id ) ) {
$user = get_user_by( 'id', $user_id );
}
if ( ! $user ) {
return get_locale();
}
$locale = $user->locale;
return $locale ? $locale : get_locale();
}
}
/**
* Fires functions attached to a deprecated filter hook.
*
* When a filter hook is deprecated, the apply_filters() call is replaced with
* apply_filters_deprecated(), which triggers a deprecation notice and then fires
* the original filter hook.
*
* This is a copy of `apply_filters_deprecated` introduced in WP 4.6.
*
* @since 1.0.0
*
* @param string $tag The name of the filter hook.
* @param array $args Array of additional function arguments to be passed to apply_filters().
* @param string $version The version of BP Block Users that deprecated the hook.
* @param string $replacement Optional. The hook that should have been used.
* @param string $message Optional. A message regarding the change.
*
* @return mixed
* @see wbcr_factory_480_deprecated_hook()
*
*/
function wbcr_factory_480_apply_filters_deprecated( $tag, $args, $version, $replacement = false, $message = null ) {
if ( function_exists( 'apply_filters_deprecated' ) ) {
return apply_filters_deprecated( $tag, $args, $version, $replacement, $message );
}
if ( ! has_filter( $tag ) ) {
return $args[0];
}
wbcr_factory_480_deprecated_hook( $tag, $version, $replacement, $message );
return apply_filters_ref_array( $tag, $args );
}
/**
* Fires functions attached to a deprecated action hook.
*
* When an action hook is deprecated, the do_action() call is replaced with
* do_action_deprecated(), which triggers a deprecation notice and then fires
* the original hook.
*
* This is a copy of `do_action_deprecated` introduced in WP 4.6.
*
* @since 1.0.0
*
* @param string $tag The name of the action hook.
* @param array $args Array of additional function arguments to be passed to do_action().
* @param string $version The version of BP Block Users that deprecated the hook.
* @param string $replacement Optional. The hook that should have been used.
* @param string $message Optional. A message regarding the change.
*
* @return void
* @see _deprecated_hook()
*
*/
function wbcr_factory_480_do_action_deprecated( $tag, $args, $version, $replacement = false, $message = null ) {
if ( function_exists( 'do_action_deprecated' ) ) {
do_action_deprecated( $tag, $args, $version, $replacement, $message );
return;
}
if ( ! has_action( $tag ) ) {
return;
}
wbcr_factory_480_deprecated_hook( $tag, $version, $replacement, $message );
do_action_ref_array( $tag, $args );
}
/**
* Marks a deprecated action or filter hook as deprecated and throws a notice.
*
* Use the 'wbcr_factory_480_deprecated_hook_run' action to get the backtrace describing where the
* deprecated hook was called.
*
* Default behavior is to trigger a user error if WP_DEBUG is true.
*
* This function is called by the do_action_deprecated() and apply_filters_deprecated()
* functions, and so generally does not need to be called directly.
*
* This is a copy of `_deprecated_hook` introduced in WP 4.6.
*
* @since 1.0.0
* @access private
*
* @param string $hook The hook that was used.
* @param string $version The version of WordPress that deprecated the hook.
* @param string $replacement Optional. The hook that should have been used.
* @param string $message Optional. A message regarding the change.
*/
function wbcr_factory_480_deprecated_hook( $hook, $version, $replacement = null, $message = null ) {
/**
* Fires when a deprecated hook is called.
*
* @since 1.0.0
*
* @param string $hook The hook that was called.
* @param string $replacement The hook that should be used as a replacement.
* @param string $version The version of BP Block Users that deprecated the argument used.
* @param string $message A message regarding the change.
*/
do_action( 'deprecated_hook_run', $hook, $replacement, $version, $message );
/**
* Filter whether to trigger deprecated hook errors.
*
* @since 1.0.0
*
* @param bool $trigger Whether to trigger deprecated hook errors. Requires
* `WP_DEBUG` to be defined true.
*/
if ( WP_DEBUG && apply_filters( 'deprecated_hook_trigger_error', true ) ) {
$message = empty( $message ) ? '' : ' ' . $message;
if ( ! is_null( $replacement ) ) {
trigger_error( sprintf( __( '%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.' ), $hook, $version, $replacement ) . $message );
} else {
trigger_error( sprintf( __( '%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.' ), $hook, $version ) . $message );
}
}
}
if ( ! function_exists( '_sanitize_text_fields' ) ) {
function _sanitize_text_fields( $str, $keep_newlines = false ) {
$filtered = wp_check_invalid_utf8( $str );
if ( strpos( $filtered, '<' ) !== false ) {
$filtered = wp_pre_kses_less_than( $filtered );
// This will strip extra whitespace for us.
$filtered = wp_strip_all_tags( $filtered, false );
// Use html entities in a special case to make sure no later
// newline stripping stage could lead to a functional tag
$filtered = str_replace( "<\n", "&lt;\n", $filtered );
}
if ( ! $keep_newlines ) {
$filtered = preg_replace( '/[\r\n\t ]+/', ' ', $filtered );
}
$filtered = trim( $filtered );
$found = false;
while( preg_match( '/%[a-f0-9]{2}/i', $filtered, $match ) ) {
$filtered = str_replace( $match[0], '', $filtered );
$found = true;
}
if ( $found ) {
// Strip out the whitespace that may now exist after removing the octets.
$filtered = trim( preg_replace( '/ +/', ' ', $filtered ) );
}
return $filtered;
}
}
if ( ! function_exists( 'sanitize_textarea_field' ) ) {
function sanitize_textarea_field( $str ) {
$filtered = _sanitize_text_fields( $str, true );
/**
* Filters a sanitized textarea field string.
*
* @since 4.7.0
*
* @param string $filtered The sanitized string.
* @param string $str The string prior to being sanitized.
*/
return apply_filters( 'sanitize_textarea_field', $filtered, $str );
}
}

View File

@@ -0,0 +1,2 @@
<?php
// Silence is golden.

View File

@@ -0,0 +1,32 @@
<?php
namespace WBCR\Factory_480\Premium\Interfaces;
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
* @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
* @copyright (c) 2018 Webraftic Ltd
* @version 1.0
*/
interface License {
public function get_key();
public function get_hidden_key();
public function get_expiration_time( $format = 'time' );
public function get_sites_quota();
public function get_count_active_sites();
public function is_valid();
public function is_lifetime();
}

View File

@@ -0,0 +1,90 @@
<?php
namespace WBCR\Factory_480\Premium;
use Exception;
use Wbcr_Factory480_Plugin;
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
* @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
*/
class Manager {
/**
* @author Alexander Kovalev <alex.kovalevv@gmail.com>
* @since 4.1.6
* @var array
*/
public static $providers;
/**
* @var Wbcr_Factory480_Plugin
*/
protected $plugin;
/**
* @var array
*/
protected $settings;
/**
* Manager constructor.
*
* @param Wbcr_Factory480_Plugin $plugin
* @param array $settings
*
* @throws Exception
*/
public function __construct( Wbcr_Factory480_Plugin $plugin, array $settings ) {
$this->plugin = $plugin;
$this->settings = $settings;
}
/**
* @param Wbcr_Factory480_Plugin $plugin
* @param array $settings
*
* @return \WBCR\Factory_Freemius_170\Premium\Provider
* @throws Exception
*/
public static function instance( Wbcr_Factory480_Plugin $plugin, array $settings ) {
$premium_manager = new Manager( $plugin, $settings );
return $premium_manager->instance_provider();
}
/**
* @param $provider_name
*
* @return \WBCR\Factory_Freemius_170\Premium\Provider
* @throws Exception
*/
public function instance_provider() {
$provider_name = $this->get_setting( 'provider' );
if ( isset( self::$providers[ $provider_name ] ) && class_exists( self::$providers[ $provider_name ] ) ) {
if ( self::$providers[ $provider_name ] instanceof Provider ) {
throw new Exception( "Provider {$provider_name} must extend the class WBCR\Factory_480\Premium\Provider interface!" );
}
return new self::$providers[ $provider_name ]( $this->plugin, $this->settings );
}
throw new Exception( "Provider {$provider_name} is not supported!" );
}
/**
* @param string $name
*
* @return mixed
*/
protected function get_setting( $name ) {
return isset( $this->settings[ $name ] ) ? $this->settings[ $name ] : null;
}
}

View File

@@ -0,0 +1,283 @@
<?php
namespace WBCR\Factory_480\Premium;
use Exception;
use Wbcr_Factory480_Plugin;
// Exit if accessed directly
if( !defined('ABSPATH') ) {
exit;
}
/**
* Выполняет проверку обновлений, обновления, скачивание плагинов
*
* @author Alex Kovalev <alex.kovalevv@gmail.com>, repo: https://github.com/alexkovalevv
* @author Webcraftic <wordpress.webraftic@gmail.com>, site: https://webcraftic.com
*
* @version 1.0
*/
abstract class Provider {
/**
* @var Wbcr_Factory480_Plugin
*/
protected $plugin;
/**
* @var array
*/
protected $settings;
/**
* @var bool
*/
private $is_install_package;
/**
* Provider constructor.
*
* @param Wbcr_Factory480_Plugin $plugin
* @param array $settings
*/
public function __construct(Wbcr_Factory480_Plugin $plugin, array $settings)
{
$this->plugin = $plugin;
$this->settings = $settings;
$this->register_hooks();
}
/**
* @return array
*/
public function get_settings()
{
return $this->settings;
}
/**
* @param $name
* @param bool $default
*
* @return bool|mixed
*/
public function get_setting($name, $default = false)
{
return isset($this->settings[$name]) && !empty($this->settings[$name]) ? $this->settings[$name] : $default;
}
/**
* @return bool|mixed
*/
public function get_price()
{
return $this->get_setting('price');
}
/**
* @return bool
*/
public function is_install_package()
{
if( !is_null($this->is_install_package) ) {
return $this->is_install_package;
}
$premium_plugin_slug = $this->get_setting('slug');
$premium_package = $this->get_package_data();
if( !empty($premium_package) && !empty($premium_package['basename']) ) {
$basename_part = explode('/', $premium_package['basename']);
$is_valid_basename = sizeof($basename_part) === 2;
if( $is_valid_basename && !file_exists(WP_PLUGIN_DIR . '/' . $premium_package['basename']) ) {
$this->delete_package();
$this->is_install_package = false;
return false;
}
} else if( $premium_plugin_slug && file_exists(WP_PLUGIN_DIR . '/' . $premium_plugin_slug) ) {
// If plugin is installed before we update the premium package in database.
// ------------------------------------------------------------------------
$plugins = get_plugins($plugin_folder = '');
if( !empty($plugins) ) {
foreach((array)$plugins as $plugin_base => $plugin) {
$basename_parts = explode('/', $plugin_base);
if( sizeof($basename_parts) == 2 && $basename_parts[0] == $premium_plugin_slug ) {
$plugin_basename = $plugin_base;
$plugin_main_file = WP_PLUGIN_DIR . '/' . $plugin_base;
$default_headers = [
'Version' => 'Version',
'FrameworkVersion' => 'Framework Version'
];
$plugin_data = get_file_data($plugin_main_file, $default_headers, 'plugin');
$this->update_package_data([
'basename' => $plugin_basename,
'version' => $plugin_data['Version'],
'framework_version' => isset($plugin_data['FrameworkVersion']) ? $plugin_data['FrameworkVersion'] : null,
]);
$premium_package = $this->get_package_data();
/**
* @param string $plugin_name Имя плагина
*
* @param string $package Дополнительная информация о лицензии
* @since 4.1.1
*
*/
do_action('wbcr/factory/premium/installed_package', $premium_package, $this->plugin->getPluginName());
}
}
}
}
$this->is_install_package = !empty($premium_package);
return $this->is_install_package;
}
/**
* @return bool|mixed|null
*/
public function get_package_data()
{
$premium_package = $this->plugin->getPopulateOption('premium_package');
if( !empty($premium_package) ) {
return wp_parse_args($premium_package, [
'basename' => null,
'version' => null,
'framework_version' => null
]);
}
return null;
}
/**
* @param $plugin_data
*
* @throws Exception
*/
public function update_package_data(array $package)
{
$parsed_args = wp_parse_args($package, [
'basename' => null,
'version' => null,
'framework_version' => null
]);
if( empty($parsed_args['basename']) || empty($parsed_args['version']) ) {
throw new Exception('You must pass the required attributes (basename, version).');
}
$this->plugin->updatePopulateOption('premium_package', $parsed_args);
$this->is_install_package = true;
}
public function delete_package()
{
$this->plugin->deletePopulateOption('premium_package');
$this->is_install_package = false;
}
protected function register_hooks()
{
/**
* Добавляет крон задачу на синхронизацию лицензии
*
* @param array $license_info
* @param string $provider
*/
add_action("{$this->plugin->getPluginName()}/factory/premium/license_activate", function ($provider, $license_info) {
if( !wp_next_scheduled("{$this->plugin->getPluginName()}_license_autosync") ) {
wp_schedule_event(time(), 'twicedaily', "{$this->plugin->getPluginName()}_license_autosync");
}
}, 10, 2);
/**
* Удаляет крон задачу на синхронизацию лицензии, когда лицензия деактивирована
*
* @param array $license_info
* @param string $provider
*/
add_action("{$this->plugin->getPluginName()}/factory/premium/license_deactivate", function ($provider, $license_info) {
if( wp_next_scheduled("{$this->plugin->getPluginName()}_license_autosync") ) {
wp_clear_scheduled_hook("{$this->plugin->getPluginName()}_license_autosync");
}
}, 10, 2);
/**
* Обработчик крон задачи на синхронизацию лицензии, выполняется 2 раза в день.
*/
add_action("{$this->plugin->getPluginName()}_license_autosync", function () {
$this->sync();
});
}
/**
* @return bool
*/
abstract public function is_activate();
/**
* @return bool
*/
abstract public function is_active();
/**
* @return string|null
*/
abstract public function get_plan();
/**
* @return string|null
*/
abstract public function get_billing_cycle();
/**
* @return \WBCR\Factory_480\Premium\Interfaces\License
*/
abstract public function get_license();
/**
* @return string|null
*/
abstract public function get_package_download_url();
/**
* @param string $key
*
* @return mixed
*/
abstract public function activate($key);
/**
* @return bool
*/
abstract public function deactivate();
/**
* @return bool
*/
abstract public function sync();
/**
* @return bool
*/
abstract public function has_paid_subscription();
/**
* @return bool
*/
abstract public function cancel_paid_subscription();
}

Some files were not shown because too many files have changed in this diff Show More