Bläddra i källkod

Initial

master
ChiefRed 3 år sedan
incheckning
dd9e002105
15 ändrade filer med 1996 tillägg och 0 borttagningar
  1. +146
    -0
      Readme.md
  2. +103
    -0
      chiefred.php
  3. +192
    -0
      class.chiefred-admin.php
  4. +820
    -0
      class.chiefred.php
  5. +0
    -0
      index.html
  6. +0
    -0
      logs/index.html
  7. +137
    -0
      res/chiefred.default.css
  8. +113
    -0
      res/chiefred.default.js
  9. +46
    -0
      res/chiefred_options.css
  10. +162
    -0
      res/chiefred_options.js
  11. +0
    -0
      res/index.html
  12. +18
    -0
      res/jquery.mask.min.js
  13. +69
    -0
      views/article.default.php
  14. +0
    -0
      views/index.html
  15. +190
    -0
      views/options.php

+ 146
- 0
Readme.md Visa fil

@@ -0,0 +1,146 @@
# Плагин WordPress для интеграции с Редакцией
Написан в 2017 году.
Есть некоторые отступления от PSR. Но у WP свои стандарты кодирования, плюс тогда мой внутренний перфекционист, местами, желал странного. Сейчас, разумеется, автоформат — маст хэв!
Имеется видеоролик (3 минуты), о том, как сей плагин предполагалось использовать:
https://youtu.be/qjWFutZEUlM
Если, вдруг, возникнет вопрос "Что еще за Редакция?" то про нее (12 минут) тут:
https://youtu.be/Dn0X1Mhjg6c
---
### Дальше оригинальное Readme плагина:
---
Данное решение позволяет подключить к Редакции наполняемый сайт,
построенный на базе популярной CMS WordPress. Для этого Вам
не понадобится изучать наш API и в абсолютном большинстве случаев
не потребуется программирование.
Системные требования:
- WordPress 4.7.3+
- PHP 5.4+ (gd, curl, json, mbstring)
Устанавливается плагин через панель управления WordPress:
`Плагины > Добавить новый > Загрузить плагин`
Папка `/wp-content/plugins/chiefred/logs` должна быть доступна для записи.
После активации плагина в меню Настройки появится подпункт
`API ChiefRed.com`, где нужно задать параметры взаимодействия с Редакцией,
получить данные для настройки самой Редакции для работы с Вашим сайтом,
а также можно отрегулировать отображение на сайте загружаемых из
Редакции материалов.
## Настройки сайта для взаимодействия с редакцией
- ID этого cайта в Редакции – берется в первой колонке таблицы
подраздела «Сайты» роли Администратора в Редакции.
- IP-адрес сервера API и Порт API (Редакции) – указаны в подразделе
«Обзор состояния системы» роли Администратора в Редакции – инфоблок
«Реквизиты API Редакции».
- Секрет синхронизации – последовательность случайных символов,
длиной до 64 знаков. Допускаются только латинские маленькие и
большие буквы, а также цифры.
## Реквизиты данного сайта для настройки редакции
Важно после сохранения Секрета в плагине в точности скопировать его в
настройки Вашего сайта в самой Редакции. Кроме него в реквизитах сайта
в Редакции нужно указать:
- Домен
- IP-адрес сервера сайта;
- Скрипт канонического URL статьи;
- Скрипт сброса флага задержки.
Все это можно узнать на странице настроек плагина.
## Синхронизация
После сохранения всех настроек в плагине и Редакции все будет готово к
выкладке статей из Редакции на Ваш сайт. Этот процесс осуществляется
автоматически, по мере отправки статей на публикацию Менеджером
предметной области.
Если же Вы выкладываете материалы на сайт повторно (переносите или
восстанавливаете сайт с нуля, уже имея в Редакции готовые статьи), то
начало процесса синхронизации можно ускорить с помощью утилиты
«Выполнить синхронизацию», доступной в нижней части страницы настроек
плагина.
Там же можно просмотреть «Журнал последней синхронизации» и отменить
очередную внеплановую синхронизацию.
Плановая синхронизация осуществляется каждые четыре часа.
> ВАЖНО! Для систематического осуществления процесса синхронизации
> необходимо обеспечить регулярный запуск скрипта wp-cron.php,
> отвечающего в WordPress за периодические задачи. На молодых сайтах
> с низкой посещаемостью для этого необходимо использовать системный
> планировщик хостинга. На эту тему существует множество материалов,
> найти которые можно в Google, например, по запросу:
> «WordPress запуск по crontab».
## Отображение статей на сайте
Получив статью из Редакции, плагин создает обычную статическую
страницу (page). WordPress (как и Редакция) поддерживает иерархическую
структуру материалов. Так что размещаемые на сайте статьи органично
вписываются в структуру данных WordPress. Дополнительные данные из
Редакции, необходимые для работы плагина, размещаются в скрытых
мета-полях статьи. Например, там хранятся, и выводятся плагином на
странице статьи, мета-поля keywords и description (полезные для SEO).
Плагин «из коробки» настроен отображать статьи в расширенном формате:
со ссылкой на родительскую статью, подписями авторов, шлейфом анонсов
дочерних статей и формой сбора возражений читателей. Но все эти
дополнительные компоненты статьи можно отключить в настройках плагина.
Для более тонкой настройки вывода статьи можно отредактировать файлы,
отвечающие за ее отображение:
- `/wp-content/plugins/chiefred/views/article.php` – шаблон вывода;
- `/wp-content/plugins/chiefred/res/chiefred.css` – таблицы стилей;
- `/wp-content/plugins/chiefred/res/chiefred.js` – скрипты формы
сбора возражений читателей.
Правда, вместо них Вы найдете: `article.default.php`, `chiefred.default.css`
и `chiefred.default.js` – это входящие в поставку плагина
стандартные (default) файлы, которые нужно скопировать, соответственно,
в `article.php`, `chiefred.css` и `chiefred.js`, в которые и следует вносить
изменения.
Плагин также добавляет визуальный редактор поля «Отрывок» в редакторе
статей WordPress, где размещается Анонс статьи.
## Отображение иллюстраций на сайте
WordPress, как и Редакция, поддерживает несколько форматов миниатюр
иллюстраций, создаваемых в процессе синхронизации. В настройках плагина
можно указать, какой формат иллюстрации Вы хотите вставлять в статью:
одну из миниатюр или полный.
Также здесь можно задать присваиваемый тегу иллюстрации класс и
настроить обертывание иллюстраций ссылкой на полноформатное изображение.
> ВАЖНО! В теле статьи хранится тег картинки с минимальным набором
> атрибутов: идентификатор, класс и ссылка на миниатюру выбранного
> формата. Остальные атрибуты и обертывание ссылкой добавляются
> динамически, в момент вывода статьи читателю. Это сделано для
> сохранения возможности изменить формат вывода иллюстраций, если Вы
> решите пересмотреть дизайн своего сайта. То есть, простым изменением
> настроек плагина можно менять вывод сразу всех иллюстраций во всех
> статьях, при условии что в теле статьи в тегах картинок были
> сохранены их идентификаторы.
>
> Не удаляйте и не меняйте атрибут «id» картинок в статьях!

+ 103
- 0
chiefred.php Visa fil

@@ -0,0 +1,103 @@
<?php
/**
* @package ChiefRedCom
* @version 1.0
*/
/*
Plugin Name: API v1 ChiefRed.com
Description: Подключение к API v1 сервиса наполнения сайтов статьями <a href="https://chiefred.com">ChiefRed.com</a>
Version: 1.0
Author: ChiefRed.com
Author URI: https://ChiefRed.com/
*/
if ( ! defined( 'ABSPATH' ) ) exit;
define( 'CHIEFRED_VERSION', '1.0' );
define( 'CHIEFRED_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
define( 'CHIEFRED_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
define( 'CHIEFRED_LOCAL_DEBUG', getenv('DEV_LOCAL') );
define( 'CHIEFRED_LOCAL_BASE', 'https://chiefred.dev' );
define('CHIEFRED_LL_OFF', 0);
define('CHIEFRED_LL_ERROR', 1);
define('CHIEFRED_LL_WARNING', 2);
define('CHIEFRED_LL_INFO', 3);
define('CHIEFRED_LL_DEBUG', 4);
define('CHIEFRED_LOG_LEVEL', CHIEFRED_LL_INFO);
if(CHIEFRED_LOG_LEVEL > CHIEFRED_LL_OFF) {
define('CHIEFRED_LOG_FILE', fopen(CHIEFRED_PLUGIN_DIR.'/logs/chiefred.log', 'a+'));
}
define( 'CHIEFRED_MEDIUM_IMG_WIDTH_LIMIT', 400 );
define( 'CHIEFRED_SMALL_IMG_WIDTH_LIMIT', 200 );
register_activation_hook(__FILE__, 'chiefred_plugin_activation');
function chiefred_plugin_activation()
{
add_option('chiefred_site_id', '', '', 'no');
add_option('chiefred_api_ip', '', '', 'no');
add_option('chiefred_api_port', '', '', 'no');
add_option('chiefred_sync_lock', '0', '', 'no');
add_option('chiefred_article_parent_link', '1', '', 'yes');
add_option('chiefred_article_creators', '1', '', 'yes');
add_option('chiefred_article_childrens', '1', '', 'yes');
add_option('chiefred_article_was_useful', '1', '', 'yes');
add_option('chiefred_illustration_size', 'medium', '', 'yes');
add_option('chiefred_illustration_class', '', '', 'yes');
add_option('chiefred_illustration_link', '1', '', 'yes');
add_option('chiefred_illustration_link_class', 'photo', '', 'yes');
add_option('chiefred_illustration_link_rel', 'lightbox', '', 'yes');
add_option('chiefred_illustration_link_target', '_blank', '', 'yes');
if (! wp_next_scheduled ( 'chiefred_every4hours_synchronize' )) {
wp_schedule_event(time(), 'every4hours', 'chiefred_every4hours_synchronize');
}
}
register_deactivation_hook(__FILE__, 'chiefred_plugin_deactivation');
function chiefred_plugin_deactivation()
{
wp_clear_scheduled_hook('chiefred_synchronize');
wp_clear_scheduled_hook('chiefred_every4hours_synchronize');
}
require_once( CHIEFRED_PLUGIN_DIR . 'class.chiefred.php' );
add_action( 'init', array( 'ChiefRed', 'init' ) );
if ( is_admin() ) {
require_once( CHIEFRED_PLUGIN_DIR . 'class.chiefred-admin.php' );
add_action( 'init', array( 'ChiefRed_Admin', 'init' ) );
}
function chiefred_log_e($msg=null, $var=null)
{
if (CHIEFRED_LOG_LEVEL >= CHIEFRED_LL_ERROR) chiefred_logger('ERROR', $msg, $var);
}
function chiefred_log_w($msg=null, $var=null)
{
if (CHIEFRED_LOG_LEVEL >= CHIEFRED_LL_WARNING) chiefred_logger('WARNING', $msg, $var);
}
function chiefred_log_i($msg=null, $var=null)
{
if (CHIEFRED_LOG_LEVEL >= CHIEFRED_LL_INFO) chiefred_logger('INFO', $msg, $var);
}
function chiefred_log_d($msg=null, $var=null)
{
if (CHIEFRED_LOG_LEVEL >= CHIEFRED_LL_DEBUG) chiefred_logger('DEBUG', $msg, $var);
}
function chiefred_logger($level='debug', $msg=null, $var=null)
{
if (CHIEFRED_LOG_FILE && $msg) {
if ($var !== null) $msg .= ': '.var_export($var, true);
$level = str_pad("[{$level}]", 9, ' ');
fwrite(CHIEFRED_LOG_FILE, date( 'Y-m-d H:i:s', current_time( 'timestamp', 0 ) )." {$level} {$msg}\n");
}
}

+ 192
- 0
class.chiefred-admin.php Visa fil

@@ -0,0 +1,192 @@
<?php
if ( ! defined( 'ABSPATH' ) ) exit;
class ChiefRed_Admin {
private static $initiated = false;
public static function init()
{
if ( ! self::$initiated ) {
self::init_hooks();
}
if (isset($_POST['chiefred_action'])) {
if ( function_exists('current_user_can') && !current_user_can('manage_options') ) exit('CANT');
if (
! isset( $_POST['chiefred_token'] )
|| ! wp_verify_nonce( $_POST['chiefred_token'], 'wp_rest' )
) {
exit('CSRF');
} else {
switch ($_POST['chiefred_action']) {
case 'synchronize':
wp_clear_scheduled_hook('chiefred_synchronize');
if (false !== wp_schedule_single_event( time(), 'chiefred_synchronize' )) {
exit('ok');
} else {
exit('notOk');
}
case 'clear_synchronize':
wp_clear_scheduled_hook('chiefred_synchronize');
exit('ok');
case 'save':
update_option('chiefred_site_id', absint($_POST['site_id']));
if (filter_var(trim($_POST['api_ip']), FILTER_VALIDATE_IP)) {
update_option('chiefred_api_ip', trim($_POST['api_ip']));
}
update_option('chiefred_api_port', absint($_POST['api_port']));
update_option('chiefred_api_secret', preg_replace('/[^a-zA-Z0-9]+/', '', $_POST['api_secret']));
update_option('chiefred_article_parent_link', absint($_POST['article_parent_link']));
update_option('chiefred_article_creators', absint($_POST['article_creators']));
update_option('chiefred_article_childrens', absint($_POST['article_childrens']));
update_option('chiefred_article_was_useful', absint($_POST['article_was_useful']));
if (in_array($_POST['illustration_size'], ['thumbnail', 'medium', 'medium_large', 'full'])) {
update_option('chiefred_illustration_size', $_POST['illustration_size']);
}
update_option('chiefred_illustration_class', sanitize_html_class($_POST['illustration_class']));
update_option('chiefred_illustration_link', absint($_POST['illustration_link']));
update_option('chiefred_illustration_link_class', sanitize_html_class($_POST['illustration_link_class']));
update_option('chiefred_illustration_link_rel', sanitize_html_class($_POST['illustration_link_rel']));
update_option('chiefred_illustration_link_target', sanitize_html_class($_POST['illustration_link_target']));
exit('<script type="text/javascript">window.location = window.location.href;</script>');
}
}
}
}
public static function init_hooks()
{
self::$initiated = true;
add_filter( 'plugin_action_links', [__CLASS__, 'options_link'], 2, 2);
add_action( 'admin_menu', [__CLASS__, 'admin_menu'], 5 );
add_action( 'admin_enqueue_scripts', [__CLASS__, 'load_resources'] );
add_action( 'wp_ajax_display_synchronize_log', [__CLASS__, 'display_synchronize_log'] );
add_action( 'add_meta_boxes', [__CLASS__, 'switch_boxes'] );
add_post_type_support( 'page', 'excerpt' );
}
public static function admin_menu()
{
add_options_page(
'Настройки плагина API ChiefRed.com',
'API ChiefRed.com',
'manage_options',
'chiefred',
array( __CLASS__, 'display_options_page' )
);
}
public static function options_link($actions, $file)
{
if (false !== strpos($file, 'chiefred')) {
$add['options'] = '<a href="options-general.php?page=chiefred">Настройки</a>';
$actions = $add + $actions;
}
return $actions;
}
public static function load_resources()
{
wp_register_style( 'chiefred_options.css', CHIEFRED_PLUGIN_URL . 'res/chiefred_options.css', array(), CHIEFRED_VERSION );
wp_enqueue_style( 'chiefred_options.css' );
wp_register_script( 'chiefred_options.js', CHIEFRED_PLUGIN_URL . 'res/chiefred_options.js', array('jquery'), CHIEFRED_VERSION );
wp_enqueue_script( 'chiefred_options.js' );
wp_register_script( 'jquery.mask.min.js', CHIEFRED_PLUGIN_URL . 'res/jquery.mask.min.js', array('jquery'), CHIEFRED_VERSION );
wp_enqueue_script( 'jquery.mask.min.js' );
}
public static function display_options_page()
{
$options['site_id'] = get_option('chiefred_site_id');
$options['api_ip'] = get_option('chiefred_api_ip');
$options['api_port'] = get_option('chiefred_api_port');
$options['api_secret'] = get_option('chiefred_api_secret');
$options['article_parent_link'] = get_option('chiefred_article_parent_link');
$options['article_creators'] = get_option('chiefred_article_creators');
$options['article_childrens'] = get_option('chiefred_article_childrens');
$options['article_was_useful'] = get_option('chiefred_article_was_useful');
$options['illustration_size'] = get_option('chiefred_illustration_size');
$options['illustration_class'] = get_option('chiefred_illustration_class');
$options['illustration_link'] = get_option('chiefred_illustration_link');
$options['illustration_link_class'] = get_option('chiefred_illustration_link_class');
$options['illustration_link_rel'] = get_option('chiefred_illustration_link_rel');
$options['illustration_link_target'] = get_option('chiefred_illustration_link_target');
foreach (ChiefRed::get_image_sizes() as $size_name => $size) {
switch ($size_name) {
case 'thumbnail':
$options['image_sizes']['thumbnail'] = ['nname'=>'Малый', 'width'=>$size['width']];
break;
case 'medium':
$options['image_sizes']['medium'] = ['nname'=>'Средний', 'width'=>$size['width']];
break;
case 'medium_large':
$options['image_sizes']['medium_large'] = ['nname'=>'Крупный', 'width'=>$size['width']];
break;
}
}
$options['image_sizes']['full'] = ['nname'=>'Полный', 'width'=>800];
ChiefRed::view( 'options', $options );
}
public static function display_synchronize_log()
{
header('Content-Type: text/plain; charset=utf-8');
echo htmlspecialchars(file_get_contents( CHIEFRED_PLUGIN_DIR . '/logs/chiefred.log' ));
wp_die();
}
public static function switch_boxes()
{
if ( ! post_type_supports( $GLOBALS['post']->post_type, 'excerpt' ) )
{
return;
}
remove_meta_box(
'postexcerpt',
'',
'normal'
);
add_meta_box(
'postexcerpt2',
__('Excerpt'),
array(__CLASS__, 'show'),
null,
'normal',
'core'
);
}
public static function show( $post )
{
?>
<label class="screen-reader-text" for="excerpt"><?php
_e( 'Excerpt' )
?></label>
<?php
wp_editor(
self::unescape($post->post_excerpt),
'excerpt',
array(
'editor_height' => 500,
'media_buttons' => FALSE,
'teeny' => TRUE,
'tinymce' => TRUE
)
);
}
public static function unescape( $str )
{
return str_replace(
array ( '&lt;', '&gt;', '&quot;', '&amp;', '&nbsp;', '&amp;nbsp;' ),
array ( '<', '>', '"', '&', ' ', ' ' ),
$str
);
}
}

+ 820
- 0
class.chiefred.php Visa fil

@@ -0,0 +1,820 @@
<?php
if ( ! defined( 'ABSPATH' ) ) exit;
class ChiefRed {
private static $initiated = false;
public static function init()
{
if(!session_id()) {
session_start();
$_SESSION['starttime'] = (!isset($_SESSION['starttime'])) ? time() : $_SESSION['starttime'];
}
if ( ! self::$initiated ) {
self::init_hooks();
}
}
private static function init_hooks()
{
self::$initiated = true;
add_action( 'rest_api_init',
function () {
register_rest_route( 'chiefred', '/sync(.*)',
array(
'methods' => 'GET',
'callback' => array( 'ChiefRed', 'sync' ),
)
);
register_rest_route( 'chiefred', '/canonical(.*)',
array(
'methods' => 'GET',
'callback' => array( 'ChiefRed', 'canonical' ),
)
);
register_rest_route( 'chiefred', '/was_useful(.*)',
array(
'methods' => 'POST',
'callback' => array( 'ChiefRed', 'was_useful' ),
)
);
}
);
add_filter( 'cron_schedules', [__CLASS__, 'add_every4hours_schedule'] );
add_action( 'chiefred_synchronize', [__CLASS__, 'synchronize'] );
add_action( 'chiefred_every4hours_synchronize', [__CLASS__, 'synchronize'] );
add_action( 'wp_enqueue_scripts', [__CLASS__, 'load_resources'] );
add_action( 'wp_head', [__CLASS__, 'add_article_headers'] );
add_filter( 'the_content', [__CLASS__, 'add_article_components'] );
}
public static function add_every4hours_schedule( $schedules ) {
$schedules['every4hours'] = array(
'interval' => 14400,
'display' => __('Every 4 hours')
);
return $schedules;
}
public static function load_resources()
{
$post = get_post();
if ($post) {
$article_id = get_post_meta($post->ID, '_chiefred_id', true);
if ( $post && 'page' == $post->post_type && $article_id ) {
$css_file = (file_exists(CHIEFRED_PLUGIN_DIR.'res/chiefred.css')) ? CHIEFRED_PLUGIN_URL.'res/chiefred.css' : CHIEFRED_PLUGIN_URL.'res/chiefred.default.css';
wp_register_style( 'chiefred.css', $css_file, array(), CHIEFRED_VERSION );
wp_enqueue_style( 'chiefred.css');
$js_file = (file_exists(CHIEFRED_PLUGIN_DIR.'res/chiefred.js')) ? CHIEFRED_PLUGIN_URL.'res/chiefred.js' : CHIEFRED_PLUGIN_URL.'res/chiefred.default.js';
wp_register_script( 'chiefred.js', $js_file, array('jquery'), CHIEFRED_VERSION );
wp_enqueue_script( 'chiefred.js' );
}
}
}
public static function add_article_headers()
{
$post = get_post();
if ($post) {
$keywords = esc_attr(get_post_meta($post->ID, '_chiefred_keyword', true));
$description = esc_attr(get_post_meta($post->ID, '_chiefred_description', true));
if ( $post && 'page' == $post->post_type && $keywords ) {
echo "<meta name=\"keywords\" content=\"{$keywords}\" />\n";
}
if ( $post && 'page' == $post->post_type && $description ) {
echo "<meta name=\"description\" content=\"{$description}\" />\n";
}
}
}
public static function add_article_components($content)
{
$illustration_size = get_option('chiefred_illustration_size', 'medium');
$illustration_class = get_option('chiefred_illustration_class');
$illustration_link = get_option('chiefred_illustration_link');
$illustration_link_class = get_option('chiefred_illustration_link_class');
$illustration_link_rel = get_option('chiefred_illustration_link_rel');
$illustration_link_target = get_option('chiefred_illustration_link_target');
$dom = new DOMDocument('1.0', 'UTF-8');
libxml_use_internal_errors(true);
$post = get_post();
$article = (object)[];
$article->id = get_post_meta($post->ID, '_chiefred_id', true);
if ( $post && 'page' == $post->post_type && $article->id ) {
if ( get_option('chiefred_article_parent_link') && $post->post_parent ) {
$article->parent = (object)[];
$article->parent->href = wp_get_canonical_url($post->post_parent);
$article->parent->title = get_the_title($post->post_parent);
}
if ( get_option('chiefred_article_creators') ) {
$article->creators = [];
$creators = json_decode(get_post_meta($post->ID, '_chiefred_creators', true));
if(isset($creators->author)) {
$article->creators[(is_array($creators->author)?$creators->author[0]:$creators->author)] = 'автор'; //обратная совместимость со старым форматом с массивом
}
if(isset($creators->editor)) {
$article->creators[(is_array($creators->editor)?$creators->editor[0]:$creators->editor)] = 'редактор'; //обратная совместимость со старым форматом с массивом
}
if(isset($creators->illustrators)) foreach($creators->illustrators as $creator) {
$article->creators[$creator] = (isset($article->creators[$creator]))?($article->creators[$creator].', иллюстрации'):'иллюстрации';
}
}
$article->content = $content;
$iquery = new WP_Query( "post_type=attachment&post_status=inherit&post_mime_type=image/jpeg&meta_key=_chiefred_article_id&meta_value={$article->id}" );
foreach ($iquery->posts as $i) {
$attachment_image = wp_get_attachment_image_src($i->ID, $illustration_size);
$src = $attachment_image[0];
$href = wp_get_attachment_image_src($i->ID, 'full')[0];
$illustration_id = get_post_meta($i->ID, '_chiefred_id', true);
$illustration_alt = get_post_meta($i->ID, '_chiefred_alt', true);
$illustration_title = get_post_meta($i->ID, '_chiefred_title', true);
$attrs = ['class'=>$illustration_class, 'src'=>$src, 'alt'=>$illustration_alt, 'title'=>$illustration_title, 'width'=>$attachment_image[1], 'height'=>$attachment_image[2]];
$link_attrs = ($illustration_link) ? ['class'=>$illustration_link_class, 'href'=>$href, 'rel'=>$illustration_link_rel, 'target'=>$illustration_link_target] : null;
if (false !== $dom->loadHTML('<?xml encoding="UTF-8"><div id="chiefred-wrapper">'.$article->content.'</div>')) {
$dom = self::update_img($dom, 'chiefred_img_'.$illustration_id, $attrs, $link_attrs);
$article->content = self::DOMinnerHTML($dom->getElementById('chiefred-wrapper'));
}
}
if ( get_option('chiefred_article_childrens') ) {
$article->childrens = [];
$cquery = new WP_Query( "post_type=page&post_status=publish&post_parent={$post->ID}&orderby=meta_value_num&order=ASC&meta_key=_chiefred_order&posts_per_page=-1" );
foreach ($cquery->posts as $c) {
$child = (object)[];
$child->article_id = get_post_meta($c->ID, '_chiefred_id', true);
$child->href = wp_get_canonical_url($c);
$child->title = $c->post_title;
$child->excerpt = $c->post_excerpt;
$iquery = new WP_Query( "post_type=attachment&post_status=inherit&post_mime_type=image/jpeg&meta_key=_chiefred_article_id&meta_value={$child->article_id}" );
foreach ($iquery->posts as $i) {
$attachment_image = wp_get_attachment_image_src($i->ID, $illustration_size);
$src = $attachment_image[0];
$href = wp_get_attachment_image_src($i->ID, 'full')[0];
$illustration_id = get_post_meta($i->ID, '_chiefred_id', true);
$illustration_alt = get_post_meta($i->ID, '_chiefred_alt', true);
$illustration_title = get_post_meta($i->ID, '_chiefred_title', true);
$attrs = ['class'=>$illustration_class, 'src'=>$src, 'alt'=>$illustration_alt, 'title'=>$illustration_title, 'width'=>$attachment_image[1], 'height'=>$attachment_image[2]];
$link_attrs = ($illustration_link) ? ['class'=>$illustration_link_class, 'href'=>$href, 'rel'=>$illustration_link_rel, 'target'=>$illustration_link_target] : null;
if (false !== $dom->loadHTML('<?xml encoding="UTF-8"><div id="chiefred-wrapper">'.$child->excerpt.'</div>')) {
$dom = self::update_img($dom, 'chiefred_img_'.$illustration_id, $attrs, $link_attrs);
$child->excerpt = self::DOMinnerHTML($dom->getElementById('chiefred-wrapper'));
}
}
$article->childrens[] = $child;
}
}
if ( get_option('chiefred_article_was_useful') ) {
$article->was_useful = true;
}
return ChiefRed::view( 'article', compact('article'), true );
} else {
return $content;
}
}
public static function was_useful(WP_REST_Request $request)
{
$ret = ["code"=>200, "message"=>"ok"];
$post = $request->get_body_params();
if (
! isset( $post['chiefred_token'] )
|| ! wp_verify_nonce( $post['chiefred_token'], 'wp_rest' )
) {
exit('CSRF');
} else {
$api_port = get_option('chiefred_api_port');
$sync_base = (CHIEFRED_LOCAL_DEBUG) ? CHIEFRED_LOCAL_BASE.":{$api_port}/sync/v1" : "https://chiefred.com:{$api_port}/sync/v1";
$site_id = get_option('chiefred_site_id');
$sync_secret = get_option('chiefred_api_secret');
if (!$api_port || !$site_id || !$sync_secret) {
return $ret;
}
$scrollpath = intval($post['scrollpath']);
$objection = (object)[
'article_id' => intval($post['article_id']),
'is_error' => ('error' == $post['type']) ? 1 : 0,
'message' => sanitize_text_field($post['message']),
];
if($scrollpath == 0) return $ret;
if(time() - $_SESSION['starttime'] < 30) return $ret;
if(mb_strlen($objection->message) < 10) return $ret;
if(mb_strpos($objection->message, 'http://') !== false) return $ret;
if(mb_strpos($objection->message, 'https://') !== false) return $ret;
if(mb_strpos($objection->message, 'www.') !== false) return $ret;
$data = json_encode($objection);
$challenge = md5(uniqid());
$sign = md5($challenge . $data . $sync_secret);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "{$sync_base}/objection/{$challenge}/{$site_id}/{$sign}");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
if (CHIEFRED_LOCAL_DEBUG) {
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
}
$raw_resp = curl_exec($ch);
curl_close ($ch);
return $ret;
}
}
public static function sync(WP_REST_Request $request)
{
$get = $request->get_query_params();
$challenge = preg_replace('[^a-zA-Z0-9]', '', (isset($get['challenge']))?$get['challenge']: '');
if ($challenge) {
if ($_SERVER['REMOTE_ADDR'] == get_option('chiefred_api_ip')) {
wp_schedule_single_event( time(), 'chiefred_synchronize' );
return ["code"=>200, "message"=>"ok", "data"=>null, "sign"=>md5($challenge . get_option('chiefred_api_secret'))];
} else {
return ["code"=>401, "message"=>"Wrong Request IP", "data"=>null, "sign"=>null];
}
} else {
return ["code"=>400, "message"=>"Wrong Request Format", "data"=>null, "sign"=>null];
}
}
public static function canonical(WP_REST_Request $request)
{
$get = $request->get_query_params();
$challenge = preg_replace('[^a-zA-Z0-9]', '', (isset($get['challenge']))?$get['challenge']: '');
$article_id = intval((isset($_GET['article_id']))?$_GET['article_id']:0);
if ($challenge && $article_id) {
if ($_SERVER['REMOTE_ADDR'] == get_option('chiefred_api_ip')) {
$query = new WP_Query( "post_type=page&post_status=publish&meta_key=_chiefred_id&meta_value={$article_id}&posts_per_page=1" );
if ($query->have_posts()) {
$query->the_post();
$canonical = wp_get_canonical_url();
wp_reset_postdata();
$data = json_encode($canonical);
return ["code"=>200, "message"=>"ok", "data"=>$data, "sign"=>md5($challenge . $data . get_option('chiefred_api_secret'))];
} else {
return ["code"=>404, "message"=>"Article Not Found", "data"=>null, "sign"=>null];
}
} else {
return ["code"=>401, "message"=>"Wrong Request IP", "data"=>null, "sign"=>null];
}
} else {
return ["code"=>400, "message"=>"Wrong Request Format", "data"=>null, "sign"=>null];
}
}
public static function synchronize()
{
$sync_lock = intval(get_option('chiefred_sync_lock', 0));
if ($sync_lock+600 > time()) {
chiefred_log_i('Сеанс синхронизации перенесен на 5 минут в связи с блокировкой, установленной другим сенасом');
wp_schedule_single_event( time()+300, 'chiefred_synchronize' );
return;
}
update_option('chiefred_sync_lock', time());
file_put_contents( CHIEFRED_PLUGIN_DIR . '/logs/chiefred.log', '' );
$api_port = get_option('chiefred_api_port');
$sync_base = (CHIEFRED_LOCAL_DEBUG) ? CHIEFRED_LOCAL_BASE.":{$api_port}/sync/v1" : "https://chiefred.com:{$api_port}/sync/v1";
$site_id = get_option('chiefred_site_id');
$sync_secret = get_option('chiefred_api_secret');
$illustration_size = get_option('chiefred_illustration_size', 'medium');
$illustration_class = get_option('chiefred_illustration_class');
if (!$api_port || !$site_id || !$sync_secret) {
chiefred_log_e('СИНХРОНИЗАЦИЯ НЕВОЗМОЖНА: Необходимо произвести настройку плагина для взаимодействия с Редакцией');
return;
}
$dom = new DOMDocument('1.0', 'UTF-8');
libxml_use_internal_errors(true);
chiefred_log_i('Начало процесса синхронизации');
$max_query = new WP_Query( array( 'post_type' => 'page', 'post_status' => 'publish', 'orderby'=>'meta_value_num', 'order'=>'DESC','meta_key'=>'_chiefred_id','posts_per_page'=>1) );
if ($max_query->have_posts()) {
$max_query->the_post();
$post_id = get_the_ID();
$max_id = get_post_meta( $post_id, '_chiefred_id', true );
wp_reset_postdata();
} else {
$max_id = 0;
}
$max_query = new WP_Query( array( 'post_type' => 'page', 'post_status' => 'publish', 'orderby'=>'meta_value_num', 'order'=>'DESC','meta_key'=>'_chiefred_sync_at','posts_per_page'=>1) );
if ($max_query->have_posts()) {
$max_query->the_post();
$post_id = get_the_ID();
$sync_at = get_post_meta( $post_id, '_chiefred_sync_at', true );
wp_reset_postdata();
} else {
$sync_at = 0;
}
chiefred_log_i("Запрашиваем обновления статей с параметрами: \$max_id={$max_id}, \$sync_at={$sync_at}");
$challenge = md5(uniqid());
$raw_resp = self::file_get_contents_curl("{$sync_base}/articles/{$challenge}/{$site_id}/{$max_id}/{$sync_at}");
//chiefred_log_d("raw_resp", $raw_resp);
$resp = json_decode($raw_resp);
if($resp && $resp->code==200){
chiefred_log_i("Получен ответ Редакции с кодом 200 (ок)");
$data = json_encode($resp->data);
if (md5($challenge . $data . $sync_secret) == $resp->sign) {
chiefred_log_i("Подпись данных верна");
$articles_ids = $resp->data;
$articles_update_count = 0;
foreach ($articles_ids as $article_id) {
$articles_update_count++;
if ($articles_update_count > 2) {
chiefred_log_i("Есть еще статьи, требующие обновления, но в текущем сеансе достигнута квота по статьям.");
if (false !== wp_schedule_single_event( time()+300, 'chiefred_synchronize' )) {
chiefred_log_i("Поэтому, ставим еще одно задание по синхронизации через 5 минут");
}
break;
}
chiefred_log_i("Нужно обновить статью с id={$article_id}");
$challenge = md5(uniqid());
$raw_resp = self::file_get_contents_curl("{$sync_base}/article/{$challenge}/{$site_id}/{$article_id}");
$resp = json_decode($raw_resp);
//chiefred_log_d("resp", $resp);
if($resp && $resp->code==200){
chiefred_log_i("Получен ответ Редакции с кодом 200 (ок)");
$data = json_encode($resp->data);
if (md5($challenge . $data . $sync_secret) == $resp->sign) {
chiefred_log_i("Подпись данных верна");
$article = $resp->data;
$article->creators = json_encode($article->creators);
$query = new WP_Query( "post_type=page&post_status=publish&meta_key=_chiefred_id&meta_value={$article->id}" );
if ($query->have_posts()) {
chiefred_log_i("На сайте обнаружена статья с id={$article_id} - обновим ее");
$query->the_post();
$the_post = array();
$the_post['ID'] = get_the_ID();
$the_post['post_title'] = $article->title;
$the_post['post_excerpt'] = str_replace('<img data-id', '<img id', $article->short);
$the_post['post_content'] = str_replace('<img data-id', '<img id', $article->full);
remove_action( 'post_updated', 'wp_save_post_revision' );
if (wp_update_post( $the_post )) {
chiefred_log_i("Статья успешно обновлена");
}
add_action( 'post_updated', 'wp_save_post_revision' );
chiefred_log_d("the_post", $the_post);
update_post_meta($the_post['ID'], '_chiefred_parent_id', $article->parent_id);
update_post_meta($the_post['ID'], '_chiefred_order', $article->order);
update_post_meta($the_post['ID'], '_chiefred_keyword', $article->keyword);
update_post_meta($the_post['ID'], '_chiefred_description', $article->description);
update_post_meta($the_post['ID'], '_chiefred_creators', $article->creators);
update_post_meta($the_post['ID'], '_chiefred_sync_at', $article->sync_at);
chiefred_log_d("the_post_metas", get_post_meta($the_post['ID']));
wp_reset_postdata();
} else {
chiefred_log_i("На сайте нет статьи с id={$article_id} - добавляем");
$the_post = array();
if ($article->parent_id>0) {
chiefred_log_i("Полученная статья является дочерней \$parent_id={$article->parent_id} - ищем родительскую на сайте");
$query = new WP_Query( "post_type=page&post_status=publish&meta_key=_chiefred_id&meta_value={$article->parent_id}" );
if ($query->have_posts()) {
$query->the_post();
$the_post['post_parent'] = get_the_ID();
$the_post['menu_order'] = $article->order;
wp_reset_postdata();
chiefred_log_i("Родительская статья обнаружена - устанавливаем связь");
}
}
$the_post['post_author'] = 1;
$the_post['post_type'] = 'page';
$the_post['post_status'] = 'publish';
$the_post['post_title'] = $article->title;
$the_post['post_excerpt'] = str_replace('<img data-id="', '<img id="chiefred_img_', $article->short);
$the_post['post_content'] = str_replace('<img data-id="', '<img id="chiefred_img_', $article->full);
$the_post['post_name'] = $article->keyword;
chiefred_log_d("the_post", $the_post);
$post_id = wp_insert_post($the_post, false);
if ($post_id) {
chiefred_log_i("Статья успешно добавлена");
}
add_post_meta($post_id, '_chiefred_id', $article->id, true);
add_post_meta($post_id, '_chiefred_parent_id', $article->parent_id, true);
add_post_meta($post_id, '_chiefred_order', $article->order, true);
add_post_meta($post_id, '_chiefred_keyword', $article->keyword, true);
add_post_meta($post_id, '_chiefred_description', $article->description, true);
add_post_meta($post_id, '_chiefred_creators', wp_slash($article->creators), true);
add_post_meta($post_id, '_chiefred_sync_at', $article->sync_at, true);
chiefred_log_d("the_post_metas", get_post_meta($post_id));
wp_reset_postdata();
}
} else {
chiefred_log_w("Проверка подписи провалена");
}
} else {
if (!$resp) {
chiefred_log_w("Сервер {$sync_base} не ответил на запрос");
} else {
chiefred_log_w("Сервер вернул ошибку - code:{$resp->code}, message:{$resp->message}");
}
}
}
} else {
chiefred_log_w("Проверка подписи провалена");
}
} else {
if (!$resp) {
chiefred_log_w("Сервер {$sync_base} не ответил на запрос");
} else {
chiefred_log_w("Сервер вернул ошибку - code:{$resp->code}, message:{$resp->message}");
}
}
///// Иллюстрации /////
$max_query = new WP_Query( array( 'post_type' => 'attachment', 'post_status' => 'inherit', 'post_mime_type' => 'image/jpeg', 'orderby'=>'meta_value_num', 'order'=>'DESC','meta_key'=>'_chiefred_id','posts_per_page'=>1) );
if ($max_query->have_posts()) {
$max_query->the_post();
$post_id = get_the_ID();
$max_id = get_post_meta( $post_id, '_chiefred_id', true );
wp_reset_postdata();
} else {
$max_id = 0;
}
$max_query = new WP_Query( array( 'post_type' => 'attachment', 'post_status' => 'inherit', 'post_mime_type' => 'image/jpeg', 'orderby'=>'meta_value_num', 'order'=>'DESC','meta_key'=>'_chiefred_sync_at','posts_per_page'=>1) );
if ($max_query->have_posts()) {
$max_query->the_post();
$post_id = get_the_ID();
$sync_at = get_post_meta( $post_id, '_chiefred_sync_at', true );
wp_reset_postdata();
} else {
$sync_at = 0;
}
chiefred_log_i("Запрашиваем обновления иллюстраций с параметрами: \$max_id={$max_id}, \$sync_at={$sync_at}");
$challenge = md5(uniqid());
$raw_resp = self::file_get_contents_curl("{$sync_base}/illustrations/{$challenge}/{$site_id}/{$max_id}/{$sync_at}");
$resp = json_decode($raw_resp);
//chiefred_log_d("resp", $resp);
if($resp && $resp->code==200){
chiefred_log_i("Получен ответ Редакции с кодом 200 (ок)");
$data = json_encode($resp->data);
if (md5($challenge . $data . $sync_secret) == $resp->sign) {
chiefred_log_i("Подпись данных верна");
$illustrations_ids = $resp->data;
$illustrations_update_count = 0;
foreach ($illustrations_ids as $illustration_id) {
$illustrations_update_count++;
if ($illustrations_update_count > 16) {
chiefred_log_i("Есть еще иллюстрации, требующие обновления, но в текущем сеансе достигнута квота по иллюстрациям.");
if (false !== wp_schedule_single_event( time()+300, 'chiefred_synchronize' )) {
chiefred_log_i("Поэтому, ставим еще одно задание по синхронизации через 5 минут");
}
break;
}
chiefred_log_i("Нужно обновить иллюстрацию с id={$illustration_id}");
$challenge = md5(uniqid());
$raw_resp = self::file_get_contents_curl("{$sync_base}/illustration/{$challenge}/{$site_id}/{$illustration_id}");
$resp = json_decode($raw_resp);
//chiefred_log_d("resp", $resp);
if($resp && $resp->code==200){
chiefred_log_i("Получен ответ Редакции с кодом 200 (ок)");
$data = json_encode($resp->data);
if (md5($challenge . $data . $sync_secret) == $resp->sign) {
chiefred_log_i("Подпись данных верна");
$illustration = $resp->data;
$query = new WP_Query( "post_type=attachment&post_status=inherit&post_mime_type=image/jpeg&meta_key=_chiefred_id&meta_value={$illustration->id}" );
if ($query->have_posts()) {
chiefred_log_i("На сайте обнаружена иллюстрация с id={$article_id} - заменяем ее");
$query->the_post();
$attachment_id = get_the_ID();
wp_reset_postdata();
wp_delete_attachment( $attachment_id, true );
}
$query = new WP_Query( "post_type=page&post_status=publish&meta_key=_chiefred_id&meta_value={$illustration->article_id}" );
if ($query->have_posts()) {
$query->the_post();
$the_post = get_post(get_the_ID(), OBJECT);
wp_reset_postdata();
chiefred_log_i("На сайте найдена статья, к которой относится иллюстрация");
$upload_dir = wp_upload_dir();
$upload_path = str_replace( '/', DIRECTORY_SEPARATOR, $upload_dir['path'] ) . DIRECTORY_SEPARATOR;
$img = $illustration->image;
$img = str_replace('data:image/jpeg;base64,', '', $img);
$img = str_replace(' ', '+', $img);
$img_decoded = base64_decode($img);
$filename = $illustration->id . '.jpeg';
$hashed_filename = md5( $filename . microtime() ) . '_' . $filename;
$image_upload = file_put_contents( $upload_path . $hashed_filename, $img_decoded );
if( !function_exists( 'wp_handle_sideload' ) ) {
require_once( ABSPATH . 'wp-admin/includes/file.php' );
}
if( !function_exists( 'wp_get_current_user' ) ) {
require_once( ABSPATH . 'wp-includes/pluggable.php' );
}
$file = array();
$file['error'] = '';
$file['tmp_name'] = $upload_path . $hashed_filename;
$file['name'] = $hashed_filename;
$file['type'] = 'image/jpeg';
$file['size'] = filesize( $upload_path . $hashed_filename );
$file_return = wp_handle_sideload( $file, array( 'test_form' => false ) );
$filename = $file_return['file'];
$attachment = array(
'post_author' => 1,
'post_mime_type' => $file_return['type'],
'post_title' => $illustration->name,
'post_content' => $illustration->title,
'post_status' => 'inherit',
'guid' => $upload_dir['url'] . '/' . basename($filename)
);
chiefred_log_i("Иллюстрация сохранена в файл: {$attachment['guid']}");
$attach_id = wp_insert_attachment( $attachment, $filename, $the_post->ID );
require_once(ABSPATH . 'wp-admin/includes/image.php');
$attach_data = wp_generate_attachment_metadata( $attach_id, $filename );
wp_update_attachment_metadata( $attach_id, $attach_data );
add_post_meta($attach_id, '_chiefred_id', $illustration->id, true);
add_post_meta($attach_id, '_chiefred_article_id', $illustration->article_id, true);
add_post_meta($attach_id, '_chiefred_sync_at', $illustration->sync_at, true);
add_post_meta($attach_id, '_chiefred_alt', $illustration->name, true);
add_post_meta($attach_id, '_chiefred_title', $illustration->title, true);
chiefred_log_d("\$attach_id={$attach_id}");
$t = $illustration;
$t->image = '<truncated>';
chiefred_log_d("\$illustration", $illustration);
$image = imagecreatefromstring($img_decoded);
@$iSize = getimagesizefromstring($img_decoded);
if ($image && $iSize) {
foreach ($attach_data['sizes'] as $size_name => $size) {
if (CHIEFRED_SMALL_IMG_WIDTH_LIMIT > $size['width']) {
$k = max($size['width'] / 120, $size['height'] / 90);
$newwidth = $iSize[0] * $illustration->preview_s_z * $k;
$newheight = $iSize[1] * $illustration->preview_s_z * $k;
$resized = imagecreatetruecolor($newwidth, $newheight);
$dest = imagecreatetruecolor($size['width'], $size['height']);
imagecopyresampled($resized, $image, 0, 0, 0, 0, $newwidth, $newheight, $iSize[0], $iSize[1]);
imagecopy($dest, $resized, 0, 0, -1*$illustration->preview_s_x*$k, -1*$illustration->preview_s_y*$k, $size['width'], $size['height']);
imagedestroy($resized);
ob_start();
imagejpeg($dest, "{$upload_dir['path']}/{$size['file']}");
ob_end_clean();
imagedestroy($dest);
} elseif(CHIEFRED_MEDIUM_IMG_WIDTH_LIMIT > $size['width']) {
$k = max($size['width'] / 240, $size['height'] / 180);
$newwidth = $iSize[0] * $illustration->preview_m_z * $k;
$newheight = $iSize[1] * $illustration->preview_m_z * $k;
$resized = imagecreatetruecolor($newwidth, $newheight);
$dest = imagecreatetruecolor($size['width'], $size['height']);
imagecopyresampled($resized, $image, 0, 0, 0, 0, $newwidth, $newheight, $iSize[0], $iSize[1]);
imagecopy($dest, $resized, 0, 0, -1*$illustration->preview_m_x*$k, -1*$illustration->preview_m_y*$k, $size['width'], $size['height']);
imagedestroy($resized);
ob_start();
imagejpeg($dest, "{$upload_dir['path']}/{$size['file']}");
ob_end_clean();
imagedestroy($dest);
}
}
imagedestroy($image);
$iSize = null;
}
$src = wp_get_attachment_image_src($attach_id, $illustration_size)[0];
chiefred_log_d("img \$illustration_class:{$illustration_class} \$illustration_size:{$illustration_size} \$src:{$src}");
$attrs = ['class'=>$illustration_class, 'src'=>$src];
if (false !== $dom->loadHTML('<?xml encoding="UTF-8"><div id="chiefred-wrapper">'.$the_post->post_excerpt.'</div>')) {
$dom = self::update_img($dom, 'chiefred_img_'.$illustration->id, $attrs);
$the_post->post_excerpt = self::DOMinnerHTML($dom->getElementById('chiefred-wrapper'));
}
if (false !== $dom->loadHTML('<?xml encoding="UTF-8"><div id="chiefred-wrapper">'.$the_post->post_content.'</div>')) {
$dom = self::update_img($dom, 'chiefred_img_'.$illustration->id, $attrs);
$the_post->post_content = self::DOMinnerHTML($dom->getElementById('chiefred-wrapper'));
}
remove_action( 'post_updated', 'wp_save_post_revision' );
if (wp_update_post( $the_post )) {
chiefred_log_i("Страница иллюстрации успешно обновлена");
} else {
chiefred_log_w("Страницу иллюстрации обновить НЕ УДАЛОСЬ");
}
add_action( 'post_updated', 'wp_save_post_revision' );
} else {
chiefred_log_i("Иллюстрации без привязки к статье нам не нужны - загрузим потом");
continue;
}
} else {
chiefred_log_w("Проверка подписи провалена");
}
} else {
if (!$resp) {
chiefred_log_w("Сервер {$sync_base} не ответил на запрос");
} else {
chiefred_log_w("Сервер вернул ошибку - code:{$resp->code}, message:{$resp->message}");
}
}
}
} else {
chiefred_log_w("Проверка подписи провалена");
}
} else {
if (!$resp) {
chiefred_log_w("Сервер {$sync_base} не ответил на запрос");
} else {
chiefred_log_w("Сервер вернул ошибку - code:{$resp->code}, message:{$resp->message}");
}
}
chiefred_log_i('Процесс синхронизации завершен');
update_option('chiefred_sync_lock', 0);
}
// [ UTILS ] /////////////////////////////////////////////////////////////////////////////////////////////////////
public static function update_img(DOMDocument $dom, $id=null, $attrs=[], $link_attrs=null)
{
foreach ($dom->getElementsByTagName('img') as $item) {
if ($item->getAttribute('id') == $id) {
foreach ($attrs as $attr => $val) {
if ($val) {
$item->setAttribute($attr, $val);
} else {
$item->removeAttribute($attr);
}
}
if (null !== $link_attrs && 'a' != $item->parentNode->tagName) {
$link = $dom->createElement('a');
foreach ($link_attrs as $attr => $val) {
if ($val) {
$link->setAttribute($attr, $val);
} else {
$link->removeAttribute($attr);
}
}
$item->parentNode->replaceChild($link, $item);
$link->appendChild($item);
}
}
}
return $dom;
}
public static function get_image_sizes( $size = '' )
{
global $_wp_additional_image_sizes;
$sizes = array();
$get_intermediate_image_sizes = get_intermediate_image_sizes();
foreach( $get_intermediate_image_sizes as $_size ) {
if ( in_array( $_size, array( 'thumbnail', 'medium', 'medium_large', 'large' ) ) ) {
$sizes[ $_size ]['width'] = get_option( $_size . '_size_w' );
$sizes[ $_size ]['height'] = get_option( $_size . '_size_h' );
$sizes[ $_size ]['crop'] = (bool) get_option( $_size . '_crop' );
} elseif ( isset( $_wp_additional_image_sizes[ $_size ] ) ) {
$sizes[ $_size ] = array(
'width' => $_wp_additional_image_sizes[ $_size ]['width'],
'height' => $_wp_additional_image_sizes[ $_size ]['height'],
'crop' => $_wp_additional_image_sizes[ $_size ]['crop']
);
}
}
if ( $size ) {
if( isset( $sizes[ $size ] ) ) {
return $sizes[ $size ];
} else {
return false;
}
}
return $sizes;
}
public static function DOMinnerHTML(DOMNode $element)
{
$innerHTML = "";
$children = $element->childNodes;
foreach ($children as $child)
{
$innerHTML .= $element->ownerDocument->saveHTML($child);
}
return $innerHTML;
}
public static function view( $name, array $args = array(), $as_string=false )
{
foreach ( $args AS $key => $val ) {
$$key = $val;
}
if (file_exists(CHIEFRED_PLUGIN_DIR."views/{$name}.php")) {
$file = CHIEFRED_PLUGIN_DIR."views/{$name}.php";
} elseif(file_exists(CHIEFRED_PLUGIN_DIR."views/{$name}.default.php")) {
$file = CHIEFRED_PLUGIN_DIR."views/{$name}.default.php";
} else {
return 'ChiefRedERROR: View ($name) not found';
}
if($as_string) {
ob_start();
}
include( $file );
if($as_string) {
return ob_get_clean();
}
}
public static function file_get_contents_curl($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_AUTOREFERER, TRUE);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
if (CHIEFRED_LOCAL_DEBUG) {
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
}
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
}

+ 0
- 0
index.html Visa fil


+ 0
- 0
logs/index.html Visa fil


+ 137
- 0
res/chiefred.default.css Visa fil

@@ -0,0 +1,137 @@
/**
* Файл chiefred.default.css - стандартный набор стилей для отображения статьи,
* загруженной по API ChiefRed.com
*
* НЕ РЕДАКТИРУЙТЕ ЭТОТ ФАЙЛ!!!
*
* При последующих обновлениях плагина он будет замещаться и все Ваши изменения пропадут.
* Создайте новый файл с именем chiefred.css в той же папке, скопируйте в него содержимое
* этого файла и там уже вносите свои правки.
*
*/
.chiefred-article-parent span::before {
content: "\2190 ";
color: #007acc;
display: inline-block;
width: 10px;
height: 10px;
margin-right: 10px;
}
.chiefred-article-creators {
font-size: 13px;
color: #3fa55e;
margin: 20px 0;
cursor: default;
}
.chiefred-article-creators span {
font-style: italic;
margin: 0 2px;
}
.chiefred-article-creators span::after {
content: ", ";
}
.chiefred-article-creators span:last-child::after {
content: "";
}
.chiefred-article-content p,
.chiefred-article-child p
{
text-align: justify;
text-indent: 2em;
font-size: 1em;
line-height: 1.7em;
padding-bottom: 11px;
margin: 0;
}
.chiefred-article-content .photo,
.chiefred-article-child .photo
{
margin: 5px 25px 5px 0;
float: left;
cursor: zoom-in;
}
.chiefred-article-child-readmore {
overflow: hidden;
margin: 0 0 40px;
}
.chiefred-article-child-readmore a:hover {
background: #107eb5;
}
.chiefred-article-child-readmore a {
float: right;
display: block;
background: #1494d5;
color: #fff;
text-decoration: none;
text-transform: uppercase;
font-weight: bold;
padding: 7px 28px;
border-radius: 4px;
}
#chiefred-was-usefull {
border-top: 1px solid #ccc;
overflow: hidden;
padding: 30px 0;
}
#chiefred-wu-is {
width: 473px;
overflow: hidden;
margin: 0 auto;
}
#chiefred-wu-caption {
font-size: 16px;
font-weight: bold;
float: left;
}
#chiefred-wu-buttons {
float: left;
margin-top: 24px;
}
.chiefred-btn {
border: 1px solid #ccc !important;
border-radius: 3px !important;
min-width: 100px !important;
padding: 7px !important;
outline: none !important;
background: #fff !important;
color: #3E4156 !important;
font-size: 14px !important;
cursor: pointer !important;
margin-right: 30px !important;
}
.chiefred-btn:hover {
background: #ccc !important;
}
#chiefred-pwu-yes, #chiefred-pwu-no, #chiefred-pwu-error {
width: 473px;
margin: 30px auto;
}
#chiefred-was-usefull textarea {
width: 100%;
height: 100px;
padding: 10px 20px;
max-width: 100%;
outline-color: #ffd27d;
}
.chiefred-wu-limit {
font-size: 12px;
}
.chiefred-wu-limit .chiefred-btn {
float: right !important;
margin: 5px 0 !important;
background: #428bca !important;
color: #fff !important;
border-color: #357ebd !important;
}

+ 113
- 0
res/chiefred.default.js Visa fil

@@ -0,0 +1,113 @@
/**
* Файл chiefred.default.js - стандартный Java-скрипт для отображения статьи,
* загруженной по API ChiefRed.com
*
* НЕ РЕДАКТИРУЙТЕ ЭТОТ ФАЙЛ!!!
*
* При последующих обновлениях плагина он будет замещаться и все Ваши изменения пропадут.
* Создайте новый файл с именем chiefred.js в той же папке, скопируйте в него содержимое
* этого файла и там уже вносите свои правки.
*
*/
var chiefred_scrollpath = 0;
jQuery( document ).scroll(function()
{
chiefred_scrollpath++;
});
jQuery( document ).ready(function()
{
var chiefred_wu_submit = function(e)
{
var wu_type = (e.target.id == 'chiefred-swu-no') ? 'useless' : 'error';
var message = (wu_type == 'useless') ? jQuery('#chiefred-twu-no').val() : jQuery('#chiefred-twu-error').val();
jQuery.ajax({
type: "POST",
url: jQuery('#chiefred-was-usefull').data('href'),
data: {
article_id: jQuery('#chiefred-was-usefull').data('article-id'),
type: wu_type,
message: message,
scrollpath: chiefred_scrollpath,
chiefred_token: jQuery('#chiefred-was-usefull').data('nonce')
},
beforeSend: function (xhr) {
xhr.setRequestHeader('X-WP-Nonce', jQuery('#chiefred-was-usefull').data('nonce'));
},
success: function(data)
{
console.log('chiefred-was-usefull: ok');
},
error: function(data)
{
console.log('error:', data);
},
});
jQuery('#chiefred-was-usefull').html('<div id="chiefred-wu-is thanks">Спасибо!</div>');
}
jQuery('#chiefred-pwu-yes').hide();
jQuery('#chiefred-bwu-yes').click(function()
{
jQuery('#chiefred-bwu-yes').addClass('active');
jQuery('#chiefred-pwu-yes').show();
jQuery('#chiefred-bwu-no').removeClass('active');
jQuery('#chiefred-pwu-no').hide();
jQuery('#chiefred-bwu-error').removeClass('active');
jQuery('#chiefred-pwu-error').hide();
});
var chiefred_ta_lim = 1000;
jQuery('#chiefred-pwu-no').hide();
jQuery('#chiefred-bwu-no').click(function()
{
jQuery('#chiefred-bwu-yes').removeClass('active');
jQuery('#chiefred-pwu-yes').hide();
jQuery('#chiefred-bwu-no').addClass('active');
jQuery('#chiefred-pwu-no').show();
jQuery('#chiefred-twu-no').focus();
jQuery('#chiefred-bwu-error').removeClass('active');
jQuery('#chiefred-pwu-error').hide();
});
jQuery('#chiefred-swu-no').click(chiefred_wu_submit);
var chiefred_twu_no_updated = function()
{
cur = chiefred_ta_lim - jQuery('#chiefred-twu-no').val().length;
if (cur < 0) {
jQuery('#chiefred-twu-no').val(jQuery('#chiefred-twu-no').val().substr(0, chiefred_ta_lim));
cur = 0;
}
jQuery('#chiefred-lwu-no').html(cur);
}
chiefred_twu_no_updated();
jQuery('#chiefred-twu-no').keyup(chiefred_twu_no_updated);
jQuery('#chiefred-twu-no').change(chiefred_twu_no_updated);
jQuery('#chiefred-pwu-error').hide();
jQuery('#chiefred-bwu-error').click(function()
{
jQuery('#chiefred-bwu-yes').removeClass('active');
jQuery('#chiefred-pwu-yes').hide();
jQuery('#chiefred-bwu-no').removeClass('active');
jQuery('#chiefred-pwu-no').hide();
jQuery('#chiefred-bwu-error').addClass('active');
jQuery('#chiefred-pwu-error').show();
jQuery('#chiefred-twu-error').focus();
});
jQuery('#chiefred-swu-error').click(chiefred_wu_submit);
var chiefred_twu_error_updated = function()
{
cur = chiefred_ta_lim - jQuery('#chiefred-twu-error').val().length;
if (cur < 0) {
jQuery('#chiefred-twu-error').val(jQuery('#chiefred-twu-error').val().substr(0, chiefred_ta_lim));
cur = 0;
}
jQuery('#chiefred-lwu-error').html(cur);
}
chiefred_twu_error_updated();
jQuery('#chiefred-twu-error').keyup(chiefred_twu_error_updated);
jQuery('#chiefred-twu-error').change(chiefred_twu_error_updated);
});

+ 46
- 0
res/chiefred_options.css Visa fil

@@ -0,0 +1,46 @@
.chiefred-options {
display: block;
margin: 1em 0;
width: 100%;
max-width: 630px;
}
.chiefred-options th {
display: inline-block;
width: 250px;
text-align: left;
}
.chiefred-options .devider {
display: inline-block;
width: 10px;
}
.chiefred-options .option {
display: inline-block;
width: 360px;
text-align: left;
}
.chiefred-options input,
.chiefred-options select {
width: 360px;
}
.chiefred-options .error {
border: 1px solid red;
}
#options-changed {
display:inline-block;
margin: 6px 12px;
}
#TB_window {
width: 90% !important;
margin-left: -45% !important;
}
#TB_ajaxContent {
width: auto !important;
}

+ 162
- 0
res/chiefred_options.js Visa fil

@@ -0,0 +1,162 @@
jQuery( document ).ready( function ()
{
jQuery('#options-changed').hide();
jQuery('#site_id').mask("09999")
.blur(function()
{
if( jQuery(this).val().match(/^\d+$/gm) ) {
jQuery(this).removeClass('error');
} else {
jQuery(this).addClass('error');
}
});
jQuery('#api_ip').mask("099.099.099.099")
.blur(function()
{
if( jQuery(this).val().match(/^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/gm) ) {
jQuery(this).removeClass('error');
} else {
jQuery(this).addClass('error');
}
});
jQuery('#api_port').mask("99999")
.blur(function()
{
if( jQuery(this).val().match(/^\d{5}$/gm) ) {
jQuery(this).removeClass('error');
} else {
jQuery(this).addClass('error');
}
});
jQuery('#api_secret').mask("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ", {translation: {'Z': {pattern: /[a-zA-Z0-9]/, optional: true}}})
.blur(function()
{
if( '' !== jQuery(this).val() ) {
jQuery(this).removeClass('error');
} else {
jQuery(this).addClass('error');
}
});
jQuery('#chiefred-options input, #chiefred-options select').trigger( "blur" );
jQuery("#site_ip,#sync_script_url,#canonical_script_url").click(function()
{
jQuery(this).select();
});
jQuery('#chiefred-options #site_id, #chiefred-options #api_ip , #chiefred-options #api_port, #chiefred-options #api_secret').change(function()
{
jQuery('.utils').hide();
jQuery('#options-changed').show();
});
jQuery('.chiefred-options-cancel-btn').click(function()
{
location.reload();
});
jQuery('.chiefred-options-save-btn').click(function()
{
jQuery('#chiefred-options').submit();
});
jQuery('.chiefred-synchronize-log-btn').click(function()
{
jQuery.ajax({
type: "POST",
url: ajaxurl,
data: {
action: 'display_synchronize_log',
},
success: function(data)
{
jQuery('#TB_ajaxWindowTitle').text('Журнал последней синхронизации');
jQuery('#TB_ajaxContent').html('<pre class="synchronize_log">' + data + '</pre>');
},
error: function(data)
{
console.log('error:', data);
},
});
});
setInterval(
function()
{
if(jQuery('pre.synchronize_log').is(":visible")) {
jQuery.ajax({
type: "POST",
url: ajaxurl,
data: {
action: 'display_synchronize_log',
},
success: function(data)
{
jQuery('pre.synchronize_log').html(data);
},
error: function(data)
{
console.log('error:', data);
},
});
}
}
, 3000
);
jQuery('.chiefred-synchronize-btn').click(function()
{
jQuery.ajax({
type: "POST",
url: location.href,
data: {
chiefred_action: 'synchronize',
chiefred_token: jQuery('#chiefred_token').val()
},
beforeSend: function (xhr) {
xhr.setRequestHeader('X-WP-Nonce', jQuery('#chiefred_token').val());
},
success: function(data)
{
if('ok'==data){
alert('Внеплановая синхронизация успешно инициирована');
} else {
alert('Не удалось инициировать синхронизацию');
}
},
error: function(data)
{
console.log('error:', data);
},
});
});
jQuery('.chiefred-clear-synchronize-btn').click(function()
{
jQuery.ajax({
type: "POST",
url: location.href,
data: {
chiefred_action: 'clear_synchronize',
chiefred_token: jQuery('#chiefred_token').val()
},
beforeSend: function (xhr) {
xhr.setRequestHeader('X-WP-Nonce', jQuery('#chiefred_token').val());
},
success: function(data)
{
if('ok'==data){
alert('Внеплановая синхронизация успешно отменена');
} else {
alert('Не удалось отменить внеплановую синхронизацию');
}
},
error: function(data)
{
console.log('error:', data);
},
});
});
});

+ 0
- 0
res/index.html Visa fil


+ 18
- 0
res/jquery.mask.min.js Visa fil

@@ -0,0 +1,18 @@
// jQuery Mask Plugin v1.14.10
// github.com/igorescobar/jQuery-Mask-Plugin
var $jscomp={scope:{},findInternal:function(a,f,c){a instanceof String&&(a=String(a));for(var l=a.length,g=0;g<l;g++){var b=a[g];if(f.call(c,b,g,a))return{i:g,v:b}}return{i:-1,v:void 0}}};$jscomp.defineProperty="function"==typeof Object.defineProperties?Object.defineProperty:function(a,f,c){if(c.get||c.set)throw new TypeError("ES3 does not support getters and setters.");a!=Array.prototype&&a!=Object.prototype&&(a[f]=c.value)};
$jscomp.getGlobal=function(a){return"undefined"!=typeof window&&window===a?a:"undefined"!=typeof global&&null!=global?global:a};$jscomp.global=$jscomp.getGlobal(this);$jscomp.polyfill=function(a,f,c,l){if(f){c=$jscomp.global;a=a.split(".");for(l=0;l<a.length-1;l++){var g=a[l];g in c||(c[g]={});c=c[g]}a=a[a.length-1];l=c[a];f=f(l);f!=l&&null!=f&&$jscomp.defineProperty(c,a,{configurable:!0,writable:!0,value:f})}};
$jscomp.polyfill("Array.prototype.find",function(a){return a?a:function(a,c){return $jscomp.findInternal(this,a,c).v}},"es6-impl","es3");
(function(a,f,c){"function"===typeof define&&define.amd?define(["jquery"],a):"object"===typeof exports?module.exports=a(require("jquery")):a(f||c)})(function(a){var f=function(b,h,e){var d={invalid:[],getCaret:function(){try{var a,n=0,h=b.get(0),e=document.selection,k=h.selectionStart;if(e&&-1===navigator.appVersion.indexOf("MSIE 10"))a=e.createRange(),a.moveStart("character",-d.val().length),n=a.text.length;else if(k||"0"===k)n=k;return n}catch(A){}},setCaret:function(a){try{if(b.is(":focus")){var p,
d=b.get(0);d.setSelectionRange?d.setSelectionRange(a,a):(p=d.createTextRange(),p.collapse(!0),p.moveEnd("character",a),p.moveStart("character",a),p.select())}}catch(z){}},events:function(){b.on("keydown.mask",function(a){b.data("mask-keycode",a.keyCode||a.which);b.data("mask-previus-value",b.val())}).on(a.jMaskGlobals.useInput?"input.mask":"keyup.mask",d.behaviour).on("paste.mask drop.mask",function(){setTimeout(function(){b.keydown().keyup()},100)}).on("change.mask",function(){b.data("changed",!0)}).on("blur.mask",
function(){c===d.val()||b.data("changed")||b.trigger("change");b.data("changed",!1)}).on("blur.mask",function(){c=d.val()}).on("focus.mask",function(b){!0===e.selectOnFocus&&a(b.target).select()}).on("focusout.mask",function(){e.clearIfNotMatch&&!g.test(d.val())&&d.val("")})},getRegexMask:function(){for(var a=[],b,d,e,k,c=0;c<h.length;c++)(b=m.translation[h.charAt(c)])?(d=b.pattern.toString().replace(/.{1}$|^.{1}/g,""),e=b.optional,(b=b.recursive)?(a.push(h.charAt(c)),k={digit:h.charAt(c),pattern:d}):
a.push(e||b?d+"?":d)):a.push(h.charAt(c).replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&"));a=a.join("");k&&(a=a.replace(new RegExp("("+k.digit+"(.*"+k.digit+")?)"),"($1)?").replace(new RegExp(k.digit,"g"),k.pattern));return new RegExp(a)},destroyEvents:function(){b.off("input keydown keyup paste drop blur focusout ".split(" ").join(".mask "))},val:function(a){var d=b.is("input")?"val":"text";if(0<arguments.length){if(b[d]()!==a)b[d](a);d=b}else d=b[d]();return d},calculateCaretPosition:function(a,d){var h=
d.length,e=b.data("mask-previus-value")||"",k=e.length;8===b.data("mask-keycode")&&e!==d?a-=d.slice(0,a).length-e.slice(0,a).length:e!==d&&(a=a>=k?h:a+(d.slice(0,a).length-e.slice(0,a).length));return a},behaviour:function(e){e=e||window.event;d.invalid=[];var h=b.data("mask-keycode");if(-1===a.inArray(h,m.byPassKeys)){var h=d.getMasked(),c=d.getCaret();setTimeout(function(a,b){d.setCaret(d.calculateCaretPosition(a,b))},10,c,h);d.val(h);d.setCaret(c);return d.callbacks(e)}},getMasked:function(a,b){var c=
[],p=void 0===b?d.val():b+"",k=0,g=h.length,f=0,l=p.length,n=1,v="push",w=-1,r,u;e.reverse?(v="unshift",n=-1,r=0,k=g-1,f=l-1,u=function(){return-1<k&&-1<f}):(r=g-1,u=function(){return k<g&&f<l});for(var y;u();){var x=h.charAt(k),t=p.charAt(f),q=m.translation[x];if(q)t.match(q.pattern)?(c[v](t),q.recursive&&(-1===w?w=k:k===r&&(k=w-n),r===w&&(k-=n)),k+=n):t===y?y=void 0:q.optional?(k+=n,f-=n):q.fallback?(c[v](q.fallback),k+=n,f-=n):d.invalid.push({p:f,v:t,e:q.pattern}),f+=n;else{if(!a)c[v](x);t===x?
f+=n:y=x;k+=n}}p=h.charAt(r);g!==l+1||m.translation[p]||c.push(p);return c.join("")},callbacks:function(a){var f=d.val(),p=f!==c,g=[f,a,b,e],k=function(a,b,d){"function"===typeof e[a]&&b&&e[a].apply(this,d)};k("onChange",!0===p,g);k("onKeyPress",!0===p,g);k("onComplete",f.length===h.length,g);k("onInvalid",0<d.invalid.length,[f,a,b,d.invalid,e])}};b=a(b);var m=this,c=d.val(),g;h="function"===typeof h?h(d.val(),void 0,b,e):h;m.mask=h;m.options=e;m.remove=function(){var a=d.getCaret();d.destroyEvents();
d.val(m.getCleanVal());d.setCaret(a);return b};m.getCleanVal=function(){return d.getMasked(!0)};m.getMaskedVal=function(a){return d.getMasked(!1,a)};m.init=function(c){c=c||!1;e=e||{};m.clearIfNotMatch=a.jMaskGlobals.clearIfNotMatch;m.byPassKeys=a.jMaskGlobals.byPassKeys;m.translation=a.extend({},a.jMaskGlobals.translation,e.translation);m=a.extend(!0,{},m,e);g=d.getRegexMask();if(c)d.events(),d.val(d.getMasked());else{e.placeholder&&b.attr("placeholder",e.placeholder);b.data("mask")&&b.attr("autocomplete",
"off");c=0;for(var f=!0;c<h.length;c++){var l=m.translation[h.charAt(c)];if(l&&l.recursive){f=!1;break}}f&&b.attr("maxlength",h.length);d.destroyEvents();d.events();c=d.getCaret();d.val(d.getMasked());d.setCaret(c)}};m.init(!b.is("input"))};a.maskWatchers={};var c=function(){var b=a(this),c={},e=b.attr("data-mask");b.attr("data-mask-reverse")&&(c.reverse=!0);b.attr("data-mask-clearifnotmatch")&&(c.clearIfNotMatch=!0);"true"===b.attr("data-mask-selectonfocus")&&(c.selectOnFocus=!0);if(l(b,e,c))return b.data("mask",
new f(this,e,c))},l=function(b,c,e){e=e||{};var d=a(b).data("mask"),h=JSON.stringify;b=a(b).val()||a(b).text();try{return"function"===typeof c&&(c=c(b)),"object"!==typeof d||h(d.options)!==h(e)||d.mask!==c}catch(u){}},g=function(a){var b=document.createElement("div"),c;a="on"+a;c=a in b;c||(b.setAttribute(a,"return;"),c="function"===typeof b[a]);return c};a.fn.mask=function(b,c){c=c||{};var e=this.selector,d=a.jMaskGlobals,h=d.watchInterval,d=c.watchInputs||d.watchInputs,g=function(){if(l(this,b,
c))return a(this).data("mask",new f(this,b,c))};a(this).each(g);e&&""!==e&&d&&(clearInterval(a.maskWatchers[e]),a.maskWatchers[e]=setInterval(function(){a(document).find(e).each(g)},h));return this};a.fn.masked=function(a){return this.data("mask").getMaskedVal(a)};a.fn.unmask=function(){clearInterval(a.maskWatchers[this.selector]);delete a.maskWatchers[this.selector];return this.each(function(){var b=a(this).data("mask");b&&b.remove().removeData("mask")})};a.fn.cleanVal=function(){return this.data("mask").getCleanVal()};
a.applyDataMask=function(b){b=b||a.jMaskGlobals.maskElements;(b instanceof a?b:a(b)).filter(a.jMaskGlobals.dataMaskAttr).each(c)};g={maskElements:"input,td,span,div",dataMaskAttr:"*[data-mask]",dataMask:!0,watchInterval:300,watchInputs:!0,useInput:!/Chrome\/[2-4][0-9]|SamsungBrowser/.test(window.navigator.userAgent)&&g("input"),watchDataMask:!1,byPassKeys:[9,16,17,18,36,37,38,39,40,91],translation:{0:{pattern:/\d/},9:{pattern:/\d/,optional:!0},"#":{pattern:/\d/,recursive:!0},A:{pattern:/[a-zA-Z0-9]/},
S:{pattern:/[a-zA-Z]/}}};a.jMaskGlobals=a.jMaskGlobals||{};g=a.jMaskGlobals=a.extend(!0,{},g,a.jMaskGlobals);g.dataMask&&a.applyDataMask();setInterval(function(){a.jMaskGlobals.watchDataMask&&a.applyDataMask()},g.watchInterval)},window.jQuery,window.Zepto);

+ 69
- 0
views/article.default.php Visa fil

@@ -0,0 +1,69 @@
<?php
/**
* Файл article.default.php - стандартный шаблон вывода статьи,
* загруженной по API ChiefRed.com
*
* НЕ РЕДАКТИРУЙТЕ ЭТОТ ФАЙЛ!!!
*
* При последующих обновлениях плагина он будет замещаться и все Ваши изменения пропадут.
* Создайте новый файл с именем article.php в той же папке, скопируйте в него содержимое
* этого файла и там уже вносите свои правки.
*
*/
if ( ! defined( 'ABSPATH' ) ) exit;
if(isset($article->parent)) { ?>
<div class="chiefred-article-parent">
<span></span>
<a href="<?php echo esc_url($article->parent->href); ?>"><?php echo sanitize_text_field($article->parent->title); ?></a>
</div>
<?php } ?>
<?php if(isset($article->creators)) { ?>
<div class="chiefred-article-creators">
Материал подготовили:
<?php foreach($article->creators as $name => $parts) { ?>
<span title="<?php echo esc_attr($parts); ?>"><?php echo sanitize_text_field($name); ?></span>
<?php } ?>
</div>
<?php } ?>
<div class="chiefred-article-content">
<?php echo wp_kses_post($article->content); ?>
</div>
<?php if(isset($article->childrens)) { ?>
<?php foreach($article->childrens as $child) { ?>
<div class="chiefred-article-child">
<a href="<?php echo esc_url($child->href); ?>"><h2><?php echo sanitize_text_field($child->title); ?></h2></a>
<?php echo wp_kses_post($child->excerpt); ?>
<div class="chiefred-article-child-readmore">
<a href="<?php echo esc_url($child->href); ?>">Подробнее</a>
</div>
</div>
<?php } ?>
<?php } ?>
<?php if(isset($article->was_useful)) { ?>
<div id="chiefred-was-usefull" data-href="<?php echo esc_url( get_rest_url('', 'chiefred/was_useful') ); ?>" data-article-id="<?php echo absint($article->id); ?>" data-nonce="<?php echo esc_attr(wp_create_nonce('wp_rest')); ?>">
<div id="chiefred-wu-is">
<div id="chiefred-wu-caption">Была ли наша статья полезной для Вас?</div>
<div id="chiefred-wu-buttons">
<input type="button" id="chiefred-bwu-yes" class="chiefred-btn" value="Да" />
<input type="button" id="chiefred-bwu-no" class="chiefred-btn" value="Нет" />
<input type="button" id="chiefred-bwu-error" class="chiefred-btn" value="Ошибка" />
</div>
</div>
<div id="chiefred-pwu-yes"><div>Спасибо!</div></div>
<div id="chiefred-pwu-no">
<textarea id="chiefred-twu-no" placeholder="На какой вопрос Вы не смогли найти ответ?"></textarea>
<div class="chiefred-wu-limit">Доступно <span id="chiefred-lwu-no"></span> символов <input type="button" id="chiefred-swu-no" class="chiefred-btn" value="Отправить" /></div>
</div>
<div id="chiefred-pwu-error">
<textarea id="chiefred-twu-error" placeholder="Пожалуйста, скопируйте сюда содержащий ошибку текст и поясните ее суть."></textarea>
<div class="chiefred-wu-limit">Доступно <span id="chiefred-lwu-error"></span> символов <input type="button" id="chiefred-swu-error" class="chiefred-btn" value="Отправить" /></div>
</div>
</div>
<?php } ?>

+ 0
- 0
views/index.html Visa fil


+ 190
- 0
views/options.php Visa fil

@@ -0,0 +1,190 @@
<?php if ( ! defined( 'ABSPATH' ) ) exit; ?>
<h1>Настройки взаимодействия с API v1 ChiefRed.com</h1>
<form id="chiefred-options" action="" method="POST">
<input type="hidden" name="chiefred_action" value="save">
<?php wp_nonce_field( 'wp_rest', 'chiefred_token' ); ?>
<h2 style="margin: 2em 0 1em 0;">Настройки сайта для взаимодействия с Редакцией</h2>
<table cellspacing="0" class="chiefred-options">
<tr>
<th>ID этого cайта в Редакции</th>
<td class="devider" />
<td class="option">
<span class="site-id"><input id="site_id" name="site_id" type="text" value="<?php echo esc_attr( $site_id ); ?>" class="regular-text code" placeholder="номер"></span>
</td>
</tr>
<tr>
<th>IP-адрес сервера API</th>
<td class="devider" />
<td class="option">
<span class="api-ip"><input id="api_ip" name="api_ip" type="text" value="<?php echo esc_attr( $api_ip ); ?>" class="regular-text code" placeholder="IPv4-адрес"></span>
</td>
</tr>
<tr>
<th>Порт API (Редакции)</th>
<td class="devider" />
<td class="option">
<span class="api-port"><input id="api_port" name="api_port" type="text" value="<?php echo esc_attr( $api_port ); ?>" class="regular-text code" placeholder="5 цифр"></span>
</td>
</tr>
<tr>
<th>Секрет синхронизации</th>
<td class="devider" />
<td class="option">
<span class="api-secret"><input id="api_secret" name="api_secret" type="text" value="<?php echo esc_attr( $api_secret ); ?>" class="regular-text code" placeholder="до 64 знаков: a-zA-Z0-9"></span>
</td>
</tr>
</table>
<h2 style="margin: 2em 0 1em 0;">Реквизиты данного сайта для настройки Редакции</h2>
<table cellspacing="0" class="chiefred-options">
<tr>
<th>IP-адрес сервера этого cайта</th>
<td class="devider" />
<td class="option">
<span class="site-id"><input id="site_ip" name="site_ip" type="text" value="<?php echo esc_attr( $_SERVER['SERVER_ADDR'] ); ?>" class="regular-text code" readonly="readonly"></span>
</td>
</tr>
<tr>
<th>Скрипт канонического URL статьи</th>
<td class="devider" />
<td class="option">
<span class="canonical_script_url"><input id="canonical_script_url" name="canonical_script_url" type="text" value="<?php echo esc_url( get_rest_url('', 'chiefred/canonical') ); ?>" class="regular-text code" readonly="readonly"></span>
</td>
</tr>
<tr>
<th>Скрипт сброса флага задержки</th>
<td class="devider" />
<td class="option">
<span class="site-id"><input id="sync_script_url" name="sync_script_url" type="text" value="<?php echo esc_url( get_rest_url('', 'chiefred/sync') ); ?>" class="regular-text code" readonly="readonly"></span>
</td>
</tr>
</table>
<h2 style="margin: 2em 0 1em 0;">Параметры отображения статей</h2>
<table cellspacing="0" class="chiefred-options">
<tr>
<th>Ссылка на статью-родителя</th>
<td class="devider" />
<td class="option">
<select name="article_parent_link">
<option value="0"<?php echo (0 == $article_parent_link)?' selected':'' ?>>Не добавлять</option>
<option value="1"<?php echo (1 == $article_parent_link)?' selected':'' ?>>Добавить</option>
</select>
</td>
</tr>
<tr>
<th>Подписи авторов</th>
<td class="devider" />
<td class="option">
<select name="article_creators">
<option value="0"<?php echo (0 == $article_creators)?' selected':'' ?>>Не добавлять</option>
<option value="1"<?php echo (1 == $article_creators)?' selected':'' ?>>Добавить</option>
</select>
</td>
</tr>
<tr>
<th>Анонсы дочерних статей</th>
<td class="devider" />
<td class="option">
<select name="article_childrens">
<option value="0"<?php echo (0 == $article_childrens)?' selected':'' ?>>Не добавлять</option>
<option value="1"<?php echo (1 == $article_childrens)?' selected':'' ?>>Добавить</option>
</select>
</td>
</tr>
<tr>
<th>Форма &laquo;Была ли статья полезна?&raquo;</th>
<td class="devider" />
<td class="option">
<select name="article_was_useful">
<option value="0"<?php echo (0 == $article_was_useful)?' selected':'' ?>>Не добавлять</option>
<option value="1"<?php echo (1 == $article_was_useful)?' selected':'' ?>>Добавить</option>
</select>
</td>
</tr>
</table>
<h2 style="margin: 2em 0 1em 0;">Параметры отображения иллюстраций</h2>
<table cellspacing="0" class="chiefred-options">
<tr>
<th>Размер иллюстраций в тексте</th>
<td class="devider" />
<td class="option">
<select name="illustration_size">
<?php
foreach ($image_sizes as $size_name => $size) {
if ($size['width'] <= 800) echo '<option value="' . esc_attr($size_name) . '"' . (($size_name == $illustration_size)?' selected':'') . '>' . esc_attr($size['nname']) . ' (ширина ' . absint($size['width']) . ' пикселей)</option>';
}
?>
</select>
</td>
</tr>
<tr>
<th>CLASS тега IMG иллюстрации</th>
<td class="devider" />
<td class="option">
<input id="illustration_class" name="illustration_class" type="text" value="<?php echo sanitize_html_class( $illustration_class ); ?>" />
</td>
</tr>
<tr>
<th>Ссылка на полный размер</th>
<td class="devider" />
<td class="option">
<select name="illustration_link">
<option value="0"<?php echo (0 == $illustration_link)?' selected':'' ?>>Не добавлять</option>
<option value="1"<?php echo (1 == $illustration_link)?' selected':'' ?>>Добавить</option>
</select>
</td>
</tr>
<tr>
<th>CLASS тега A ссылки</th>
<td class="devider" />
<td class="option">
<input id="illustration_link_class" name="illustration_link_class" type="text" value="<?php echo sanitize_html_class( $illustration_link_class ); ?>" />
</td>
</tr>
<tr>
<th>REL тега A ссылки</th>
<td class="devider" />
<td class="option">
<input id="illustration_link_rel" name="illustration_link_rel" type="text" value="<?php echo sanitize_html_class( $illustration_link_rel ); ?>" />
</td>
</tr>
<tr>
<th>TARGET тега A ссылки</th>
<td class="devider" />
<td class="option">
<input id="illustration_link_target" name="illustration_link_target" type="text" value="<?php echo sanitize_html_class( $illustration_link_target ); ?>" />
</td>
</tr>
</table>
<input class="button button-primary chiefred-options-save-btn" value="Сохранить изменения" type="button">
<b id="options-changed">Настройки были изменены!</b>
<div class="utils">
<h1 style="margin: 2em 0 1em 0;">Утилиты</h1>
<?php if ($site_id && $api_ip && $api_port && $api_secret) { ?>
<input class="button chiefred-synchronize-btn" value="Выполнить синхронизацию" type="button" title="Инициировать внеплановый сеанс синхронизации сайта с Редакцией. Не следует вызывать чаще чем один раз в 5 минут. Редакция может отклонить слишком частые запросы.">
<input class="button chiefred-clear-synchronize-btn" value="Остановить синхронизацию" type="button" title="Отменить следующую инициированную внеплановую синхронизацию (сеансы могут назначаться сами, с интервалом в 5 минут, если в Редакции еще остался готовый, но неопубликованный контент). Не влияет на плановую синхронизацию, выполняемую каждые 4 часа.">
<?php } ?>
<a class="button thickbox chiefred-synchronize-log-btn" href="#TB_inline?width=600&height=650&inlineId=chiefred-synchronize-log">Журнал последней синхронизации</a>
</div>
</form>
<?php add_thickbox(); ?>
<div id="chiefred-synchronize-log" style="display:none;">
<p>Загрузка...</p>
</div>

Laddar…
Avbryt
Spara