Your IP : 216.73.216.111
<?php
/**
* @link https://seowriting.ai/
* @since 1.1.8
* @package SEOWriting
*
* @wordpress-plugin
* Plugin Name: SEOWriting
* Description: SEOWriting - AI Writing Tool Plugin For Text Generation
* Version: 1.12.5
* Author: SEOWriting
* Author URI: https://seowriting.ai/?utm_source=wp_plugin
* License: GPL-2.0 or later
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
* Text Domain: seowriting
* Domain Path: /languages
*/
// If this file is called directly, abort.
defined('WPINC') || exit;
include_once __DIR__ . '/utils.php';
if (!class_exists('SEOWriting')) {
class SEOWriting
{
public $plugin_slug;
public $plugin_path;
public $version = '1.12.5';
/**
* @var \SEOWriting\APIClient|null
*/
private $api_client = null;
private $settings = null;
private $log_file = __DIR__ . '/log.php';
private $css_file = __DIR__ . '/style.css';
private $default_css_file = __DIR__ . '/default.css';
const SETTINGS_CSS_KEY = "seowriting_css";
const SETTINGS_CSS_HASH_KEY = "seowriting_css_hash";
const SETTINGS_GENERATOR_NAME = 'seowriting';
const SETTINGS_GENERATOR_NAME_KEY = 'seowriting_generator';
const SETTINGS_GENERATOR_PAGE_TYPE = 'seowriting_page_type';
const SETTINGS_INIT = 'seowriting_init';
const SETTINGS_KEY = 'seowriting_settings';
const SETTINGS_PLUGIN_NAME_KEY = 'seowriting_plugin_name';
const SETTINGS_PLUGIN_VERSION_KEY = 'seowriting_plugin_version';
const REST_VERSION = 1;
const MB_ENCODING = 'UTF-8';
const SCHEMA_TYPE_JSON = 'json';
const SCHEMA_TYPE_MICRODATA = 'microdata';
const SCHEMA_TYPE_OFF = 'off';
const SEOWRITING_PHP = 'seowriting.php';
public function __construct()
{
set_exception_handler(function ($e) {
$record = [
'type' => 'exceptionHandler',
'message' => $e->getMessage(),
'code' => $e->getCode(),
'backtrace' => []
];
foreach ($e->getTrace() as $item) {
if (isset($item['file'])) {
$file = $item['file'];
} else {
$file = 'unknown';
}
if (isset($item['line'])) {
$line = $item['line'];
} else {
$line = -1;
}
$record['backtrace'][] = [
$file,
$line
];
}
$this->writeLog($record);
});
$this->plugin_slug = plugin_basename(__DIR__);
$this->plugin_path = plugin_dir_path(__FILE__);
if (is_admin()) {
$this->adminPages();
add_filter('plugin_action_links_' . plugin_basename($this->plugin_path . self::SEOWRITING_PHP), [$this, 'adminSettingsLink']);
register_deactivation_hook(__FILE__, [$this, 'deactivate']);
register_activation_hook(__FILE__, [$this, 'activate']);
}
if (wp_doing_ajax()) {
add_action('wp_ajax_seowriting-notify', [$this, 'ajaxWebhook']);
add_action('wp_ajax_nopriv_seowriting-notify', [$this, 'ajaxWebhook']);
}
add_action('rest_api_init', [$this, 'initRest']);
add_filter('wp_kses_allowed_html', [$this, 'ksesAllowedHtml'], 10, 2);
add_filter('the_content', [$this, 'onContent'], 20);
add_action("wp_head", [$this, 'printJSONLD'], 20);
add_action('upgrader_process_complete', [$this, 'onUpdate'], 10, 2);
add_action('requests-requests.before_parse', [$this, 'onAfterRequest'], 10, 6);
add_action('plugins_loaded', [$this, 'onPluginsLoaded']);
add_action('init', [$this, 'onInit']);
}
public function onPluginsLoaded()
{
/** @phpstan-ignore-next-line */
$pluginName = (string)get_option(self::SETTINGS_PLUGIN_NAME_KEY);
if (strlen($pluginName) > 0 && $pluginName !== basename(__DIR__)) {
include_once __DIR__ . '/classes/settings-form.php';
$form = new \SEOWriting\SettingsForm($this);
$form->rename_plugin($pluginName);
}
}
public function activate()
{
update_option(self::SETTINGS_PLUGIN_VERSION_KEY, $this->version);
$this->setCSS($this->readCSS());
}
/**
* @return string
*/
private function readCSS()
{
return (string)(is_readable($this->css_file) ? @file_get_contents($this->css_file) : (is_readable($this->default_css_file) ? @file_get_contents($this->default_css_file) : ''));
}
public function onAfterRequest(&$response, $url, $headers, $data, $type, $options)
{
if (strpos($url, 'seowriting') === false || strpos($url, '.zip') === false) {
return;
}
if (!is_array($options) || !isset($options['filename']) || !is_readable($options['filename'])) {
return;
}
if (!class_exists('ZipArchive')) {
return;
}
/** @phpstan-ignore-next-line */
$pluginName = (string)get_option(self::SETTINGS_PLUGIN_NAME_KEY);
if (strlen($pluginName) === 0) {
return;
}
$filename = $options['filename'];
$tmpDir = sys_get_temp_dir() . '/' . uniqid('seowriting_');
$fs = seowriting_get_filesystem();
$fs->mkdir($tmpDir);
$newDir = $tmpDir . '/' . $pluginName;
$zip = new ZipArchive();
if ($zip->open($filename)) {
$zip->extractTo($tmpDir);
$zip->close();
$fs->move($tmpDir . '/seowriting/', $newDir);
$resultFile = $tmpDir . '/' . basename($filename);
$result = new ZipArchive();
if ($result->open($resultFile, ZipArchive::CREATE | ZipArchive::OVERWRITE)) {
$result->addEmptyDir($pluginName);
seowriting_add_file_to_zip($newDir, $result, $pluginName);
$result->close();
copy($resultFile, $filename);
seowriting_delete_dir($tmpDir);
}
}
}
/**
* @param $upgrader_object
* @param $options
* @return bool
*/
public function onUpdate($upgrader_object, $options)
{
if (
!is_array($options)
|| !isset($options['action'])
|| $options['action'] !== 'update'
|| !isset($options['type'])
|| $options['type'] !== 'plugin'
|| !isset($options['plugins'])
|| !isset($options['plugins'][0])
) {
return false;
}
foreach ($options['plugins'] as $plugin) {
if (strpos($plugin, 'seowriting.php') !== false) {
update_option(self::SETTINGS_INIT, true);
return true;
}
}
return false;
}
public function onInit()
{
if (!get_option(self::SETTINGS_INIT)) {
return;
}
delete_option(self::SETTINGS_INIT);
$this->activate();
$this->getAPIClient()->update($this->version);
}
public function ksesAllowedHtml($allowed, $context)
{
if (!is_array($context) && ($context === 'post')) {
$allowed['a']['rel'] = true;
$allowed['a']['target'] = true;
$allowed['div']['itemscope'] = true;
$allowed['div']['itemprop'] = true;
$allowed['div']['itemtype'] = true;
$allowed['h3']['itemprop'] = true;
$allowed['iframe'] = [
'src' => true,
'height' => true,
'width' => true,
'frameborder' => true,
'allowfullscreen' => true,
'allow' => true,
'loading' => true,
'referrerpolicy' => true,
'sandbox' => true,
'title' => true,
'onload' => true,
'class' => true
];
$allowed['input'] = [
'class' => true,
'placeholder' => true,
'type' => true
];
$allowed['option'] = [
'class' => true
];
$allowed['select'] = [
'class' => true
];
$allowed['textarea'] = [
'class' => true,
'placeholder' => true
];
}
return $allowed;
}
public function initRest()
{
register_rest_route($this->getRestNamespace(), '/webhook', [
'methods' => 'POST',
'callback' => [$this, 'restWebhook'],
'permission_callback' => '__return_true'
]);
register_rest_route($this->getRestNamespace(), '/log', [
'methods' => 'POST',
'callback' => [$this, 'restLog'],
'permission_callback' => '__return_true'
]);
}
public function getRestNamespace()
{
return 'seowriting/v' . self::REST_VERSION;
}
/**
* @param WP_REST_Request $request
* @return WP_REST_Response|WP_Error
*/
public function restLog($request)
{
$res = [];
$post = $request->get_json_params();
$settings = $this->getSettings();
$client = $this->getAPIClient();
if (isset($settings['secret'])
&& isset($post['sign'])
&& $client->checkSign($post, $settings['secret'])
&& is_readable($this->log_file)
) {
// @phpstan-ignore-next-line
$res = json_decode('[' . str_replace("}\n", "},", trim(explode('?>', @file_get_contents($this->log_file))[1])) . ']', true);
}
return new WP_REST_Response($res, is_array($res) && count($res) > 0 ? 200 : 400);
}
/**
* @param WP_REST_Request $request
* @return WP_REST_Response|WP_Error
*/
public function restWebhook($request)
{
$rs = $request->has_valid_params();
if (is_wp_error($rs)) {
$this->writeLog([
'type' => 'restWebhookValidation',
'data' => $rs->get_error_messages(),
]);
return new WP_REST_Response(['message' => $rs->get_error_messages()], 400);
}
// WP 4.9 compatibility, do not edit
$contentType = $request->get_content_type();
if (!is_array($contentType) || !isset($contentType['value']) || $contentType['value'] !== 'application/json') {
$error = 'Wrong Content-Type: ' . (isset($contentType['value']) ? $contentType['value'] : '');
$this->writeLog([
'type' => 'restWebhookContentType',
'message' => $error,
]);
return new WP_REST_Response(['message' => $error], 400);
}
$ret = $this->webhook($request->get_json_params());
return is_array($ret)
? new WP_REST_Response($ret)
: new WP_REST_Response([
'message' => 'You do not have permission to access this resource.',
], 400);
}
public function adminSettingsLink($links)
{
array_unshift($links,
'<a href="' . esc_url($this->getPageUrl('seowriting-setting')) . '">Settings</a>'
);
return $links;
}
public function getPageUrl($page)
{
$args = ['page' => $page];
return add_query_arg($args, admin_url('options-general.php'));
}
public function getSettings()
{
if (is_null($this->settings)) {
$this->settings = get_option(self::SETTINGS_KEY, []);
if (!is_array($this->settings)) {
$this->settings = [];
}
}
return $this->settings;
}
public function setSettings($data)
{
$modified = false;
foreach ($data as $k => $v) {
if (is_null($v)) {
if (isset($this->settings[$k])) {
unset($this->settings[$k]);
$modified = true;
}
} elseif (!isset($this->settings[$k]) || ($this->settings[$k] !== $v)) {
$this->settings[$k] = $v;
$modified = true;
}
}
if ($modified) {
if (count($this->settings) > 0) {
update_option(self::SETTINGS_KEY, $this->settings);
} else {
delete_option(self::SETTINGS_KEY);
}
}
}
public function deleteSettings()
{
$this->settings = [];
delete_option(self::SETTINGS_KEY);
delete_option(self::SETTINGS_PLUGIN_NAME_KEY);
}
/**
* @return bool
*/
public function isConnected()
{
$settings = $this->getSettings();
return !empty($settings['api_key']);
}
public function connect($params)
{
return $this->getAPIClient()->connect($params);
}
public function disconnect()
{
return $this->getAPIClient()->disconnect();
}
private function getWebhookData()
{
$post = @file_get_contents('php://input');
if (!empty($post)) {
$_data = @json_decode($post, true);
if (is_array($_data)) {
return $_data;
}
}
return [];
}
public function rename($data)
{
return $this->getAPIClient()->rename($data);
}
/**
* @param array<string, string> $post
* @return array<string, string>|null
*/
private function webhook($post)
{
$settings = $this->getSettings();
if (isset($settings['secret']) && isset($post['sign'])) {
$client = $this->getAPIClient();
if ($client->checkSign($post, $settings['secret'])) {
$action = isset($post['action']) ? sanitize_text_field($post['action']) : '';
$ret = [
'result' => 0,
'version' => $this->version,
];
if ($action === 'post') {
$rs = $this->publishPost($settings['user_id'], $post);
} elseif (($action === 'connect') && isset($post['api_key'])) {
$this->setSettings([
'api_key' => sanitize_text_field($post['api_key']),
]);
$rs = [
'result' => 1,
'categories' => $this->getCategories(),
'authors' => $this->getAuthors(),
'types' => $this->getPostTypes(),
];
} elseif ($action === 'disconnect') {
$this->deleteSettings();
$rs = [
'result' => 1
];
} elseif ($action === 'get_categories') {
$rs = [
'result' => 1,
'categories' => $this->getCategories(isset($post['page_type']) ? $post['page_type'] : 'post')
];
} elseif ($action === 'get_authors') {
$rs = [
'result' => 1,
'authors' => $this->getAuthors()
];
} elseif ($action === 'get_posts') {
$rs = [
'result' => 1,
'posts' => $this->getPosts(
intval(isset($post['page']) ? sanitize_text_field($post['page']) : '1'),
intval(isset($post['per_page']) ? sanitize_text_field($post['per_page']) : '50')
)
];
} elseif ($action === 'get_post') {
$rs = [
'result' => 1,
'post' => $this->getPost(isset($post['post_id']) ? sanitize_text_field($post['post_id']) : '')
];
} elseif ($action === 'get_post_slug') {
$rs = [
'result' => 1,
'slug' => get_permalink(intval($post['post_id']))
];
} elseif ($action === 'get_version') {
$rs = [
'result' => 1,
'version' => $this->getVersion()
];
} elseif ($action == 'get_meta') {
$rs = [
'result' => 1,
'authors' => $this->getAuthors(),
'categories' => $this->getCategories(isset($post['page_type']) ? $post['page_type'] : 'post'),
'types' => $this->getPostTypes(),
'version' => $this->getVersion()
];
} elseif ($action === 'search_pages') {
$rs = [
'result' => 1,
'pages' => $this->searchPages(sanitize_text_field($post['q']), isset($post['limit']) ? intval($post['limit']) : 10)
];
} elseif ($action === 'set_css') {
$err = $this->setCSS(sanitize_text_field($post['css']));
$rs = [
'result' => strlen($err) > 0 ? 0 : 1,
'error' => $err,
];
} elseif ($action === 'get_stat') {
include_once __DIR__ . '/../../../wp-admin/includes/plugin.php';
$plugins = [];
if (function_exists('get_plugins')) {
foreach (get_plugins() as $pluginFile => $settings) {
$plugins[] = [
'name' => seowriting_escape(explode('/', $pluginFile)[0]),
'version' => seowriting_escape($settings['Version']),
'active' => is_plugin_active($pluginFile),
'author_uri' => seowriting_escape($settings['AuthorURI'])
];
}
}
$theme = wp_get_theme();
$rs = [
'result' => 1,
'stat' => [
'engine' => [
'name' => 'wordpress',
'version' => seowriting_escape(get_bloginfo('version')),
],
'php' => [
'version' => seowriting_escape(PHP_VERSION),
],
'web_server' => [
'name' => seowriting_escape(isset($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : 'Unknown'),
],
'plugins' => $plugins,
'theme' => [
'name' => $theme->get('Name'),
'version' => $theme->get('Version'),
'uri' => $theme->get('ThemeURI'),
]
]
];
} else {
$rs = [
'error' => 'Plugin does not support this feature'
];
}
return array_merge($ret, $rs);
}
}
return null;
}
private function isDisabledSchema()
{
return get_option('sw_shema_type') === self::SCHEMA_TYPE_OFF;
}
public function ajaxWebhook()
{
$ret = $this->webhook($this->getWebhookData());
if (is_array($ret)) {
wp_send_json($ret);
}
exit();
}
/**
* @param $content
* @return string
*/
private function clearSchemaSection($content)
{
if (preg_match('#<section itemscope itemprop="mainEntity" itemtype="https://schema.org/FAQPage">(.*?)</section>#s', $content, $matches)) {
$html = $matches[0];
$html = str_replace('itemscope itemprop="mainEntity" itemtype="https://schema.org/FAQPage"', 'class="schema-section"', $html);
$items = array(' itemscope', ' itemprop="mainEntity"', ' itemprop="text"', ' itemprop="name"', ' itemprop="acceptedAnswer"', ' itemtype="https://schema.org/Question"', ' itemtype="https://schema.org/Answer"');
$html = str_replace($items, "", $html);
$content = preg_replace('#<section itemscope itemprop="mainEntity" itemtype="https://schema.org/FAQPage">(.*?)</section>#s', $html, $content);
}
return $content;
}
/**
* @return bool
*/
private function isJSONSchema()
{
return get_option('sw_shema_type') === self::SCHEMA_TYPE_JSON;
}
/**
* @return bool
*/
private function isMicrodataSchema()
{
return get_option('sw_shema_type') === self::SCHEMA_TYPE_MICRODATA;
}
public function printJSONLD()
{
if (!is_single() || !$this->isJSONSchema()) {
return;
}
// WP 4.9 compatibility, do not edit
$post = get_post(get_queried_object_id());
if ($post instanceof WP_Post) {
$content = $post->post_content;
} else {
return;
}
$qa = $this->qaList($content);
if (!is_array($qa) || !isset($qa[1])) {
return;
}
$questions = $qa[0];
$answers = $qa[1];
$count = count($questions);
$items = '';
for ($i = 0; $i < $count; $i++) {
if (isset($answers[$i]) && isset($questions[$i])) {
$items .= '{'
. '"@type": "Question",'
. '"name": "' . esc_html($questions[$i]) . '",'
. '"acceptedAnswer": {'
. '"@type": "Answer",'
. '"text": "' . esc_html($answers[$i]) . '"'
. '}'
. '}';
if ($i != $count - 1) {
$items .= ',';
}
}
}
echo '<script type="application/ld+json">'
. '{'
. '"@context": "https://schema.org",'
. '"@type": "FAQPage",'
. '"mainEntity": [' . $items . ']'
. '}'
. '</script>';
}
private function qaList($html)
{
if (preg_match('#<section class="schema-section">(.*?)</section>#s', $html, $matches)) {
$title = '';
$fhtml = $matches[1];
if (preg_match('#<h2>(.*?)</h2>#s', $fhtml, $titles)) {
$title = $titles[1];
$fhtml = str_replace($titles[0], '', $fhtml);
}
$fhtml = strip_tags($fhtml, "<h3><p><b>");
preg_match_all('#<h3>(.*?)</h3>#s', $fhtml, $questions);
$questions = isset($questions[1]) ? $questions[1] : [];
$answers = preg_split('#<h3>(.*?)</h3>#s', $fhtml);
if (is_array($answers)) {
array_shift($answers);
foreach ($answers as $idx => $answer) {
$answers[$idx] = trim(str_replace(PHP_EOL, "", wp_strip_all_tags($answer)));
}
}
return [$questions, $answers, $title];
}
return false;
}
private function addStyles($content)
{
if ((is_single() || is_page()) && get_post_meta((int)get_the_ID(), self::SETTINGS_GENERATOR_NAME_KEY, true) == self::SETTINGS_GENERATOR_NAME && is_readable($this->css_file)) {
$content = str_replace('styled-container', 'styled-container-' . md5((string)microtime(true)), '<style>' . $this->readCSS() . '</style>' . $content);
}
return $content;
}
public function onContent($content)
{
if (!is_single() && !is_page()) {
return $content;
}
if ($this->isJSONSchema()) {
return $this->addStyles($content);
}
$qa = $this->qaList($content);
if (!isset($qa[2]) || !isset($qa[0][0]) || !isset($qa[1][0])) {
return $this->addStyles($content);
}
$questions = $qa[0];
$answers = $qa[1];
$title = $qa[2];
$count = count($questions);
$isDisabled = !$this->isMicrodataSchema() && $this->isDisabledSchema();
$out = '<section' . ($isDisabled ? '' : ' itemscope itemtype="https://schema.org/FAQPage"') . '>';
$out .= '<h2>' . $title . '</h2>';
for ($i = 0; $i < $count; $i++) {
if (isset($answers[$i]) && isset($questions[$i])) {
$out .= '<div' . ($isDisabled ? '' : ' itemscope itemprop="mainEntity" itemtype="https://schema.org/Question"') . '>'
. '<h3' . ($isDisabled ? '' : ' itemprop="name"') . '>' . $questions[$i] . '</h3>'
. '<div' . ($isDisabled ? '' : ' itemscope itemprop="acceptedAnswer" itemtype="https://schema.org/Answer"') . '>'
. '<div' . ($isDisabled ? '' : ' itemprop="text"') . '>' . $answers[$i] . '</div>'
. '</div>'
. '</div>';
}
}
$out .= '</section>';
return $this->addStyles(preg_replace('#<section class="schema-section">(.*?)</section>#s', $out, $content));
}
private function deleteImages($post_id)
{
$images = get_children([
'post_parent' => $post_id,
'post_type' => 'attachment',
'post_mime_type' => 'image',
'numberposts' => -1,
]);
if (is_array($images)) {
foreach ($images as $attachment) {
if (!is_object($attachment) || get_class($attachment) !== 'WP_Post') {
continue;
}
wp_delete_attachment($attachment->ID, true);
}
}
}
private function downloadImages(&$data, $post_id, $featured_image, $is_update = false)
{
$html = $data['html'];
if ($is_update === true) {
$this->deleteImages($post_id);
}
if (preg_match_all('/<img .*src="([^">]+)"[^>]*>/uU', $html, $matches)) {
$data['images'] = [];
include_once(ABSPATH . 'wp-admin/includes/image.php');
include_once(ABSPATH . 'wp-admin/includes/file.php');
include_once(ABSPATH . 'wp-admin/includes/media.php');
$api = $this->getAPIClient();
$images = [];
foreach ($matches[1] as $i => $path) {
$alt = '';
if (preg_match('/ alt="([^"]*)"/u', $matches[0][$i], $_matches)) {
$alt = html_entity_decode($_matches[1], ENT_COMPAT | ENT_HTML401, self::MB_ENCODING);
}
$attachment_id = 0;
if (isset($images[$path])) {
$attachment_id = $images[$path];
} elseif ($file = $api->loadImage($path, $alt)) {
$id = media_handle_sideload($file, $post_id);
$api->deleteImage($file);
if (is_wp_error($id)) {
$this->writeLog([
'type' => 'downloadImagesWpError',
'data' => $id->get_error_messages(),
]);
} else {
$attachment_id = $id;
$images[$path] = $id;
if (strlen($alt) > 0) {
update_post_meta($attachment_id, '_wp_attachment_image_alt', $alt);
}
}
} else {
$this->writeLog([
'type' => 'downloadImagesApiError',
'path' => $path,
'data' => $api->error,
]);
}
if ($attachment_id > 0) {
if ($featured_image) {
set_post_thumbnail($post_id, $attachment_id);
$featured_image = false;
$html = str_replace($matches[0][$i], '', $html);
} else {
$data['images'][wp_get_attachment_url($attachment_id)] = $attachment_id;
$html = str_replace($matches[0][$i],
get_image_tag($attachment_id, $alt, $alt, 'center', 'large'),
$html
);
}
}
}
if (count($images) > 0) {
wp_update_post([
'ID' => $post_id,
'post_content' => wp_slash($html)
]);
}
$data['html'] = $html;
}
}
private function publishPost($user_id, $data)
{
global $current_user;
$maxExecutionTime = (int)ini_get('max_execution_time');
@set_time_limit(120);
$post_status = (isset($data['publish']) && intval($data['publish']) === 1) ? 'publish' : 'draft';
$post_time = time();
if (($post_status === 'publish') && isset($data['post_time'])) {
$new_post_time = intval($data['post_time']);
if ($new_post_time > 0) {
if ($new_post_time > $post_time) {
$post_status = 'future';
}
$post_time = $new_post_time;
}
}
$content = wp_kses(
$this->clearSchemaSection(
str_replace('itemscope="" itemprop=', 'itemscope itemprop=', $data['html'])
),
wp_kses_allowed_html('post')
);
$data['html'] = trim($content);
if (isset($data['author_id'])) {
$user_id = (int)$data['author_id'];
}
$current_user = new WP_User($user_id);
$post_type = isset($data['post_type']) ? $data['post_type'] : 'post';
$new_post = [
'post_title' => sanitize_text_field($data['theme']),
'post_content' => $content,
'post_status' => $post_status,
'post_date' => gmdate('Y-m-d H:i:s', $post_time),
'post_author' => $user_id,
'post_type' => $post_type,
'post_excerpt' => isset($data['excerpt']) && (int)$data['excerpt'] === 1
? (isset($data['description']) ? sanitize_text_field($data['description']) : '')
: '',
];
if (in_array('category', get_object_taxonomies($post_type))) {
$new_post['post_category'] = array_map('intval', explode(',', isset($data['category']) ? sanitize_text_field($data['category']) : '0'));
} else {
$ids = array_map('intval', explode(',', sanitize_text_field($data['category'])));
foreach ($ids as $id) {
$term = get_term($id);
if (!is_wp_error($term) && $term) {
/** @phpstan-ignore-next-line */
$taxonomy_name = $term->taxonomy;
if (!isset($new_post['tax_input'])) {
$new_post['tax_input'] = [];
}
if (!isset($new_post['tax_input'][$taxonomy_name])) {
$new_post['tax_input'][$taxonomy_name] = [];
}
$new_post['tax_input'][$taxonomy_name][] = $id;
}
}
}
if (isset($data['post_slug'])) {
$slug = sanitize_title($data['post_slug']);
if (strlen($slug) > 0) {
$new_post['post_name'] = $slug;
}
}
if (isset($data['post_type']) && $data['post_type'] === 'page' && isset($data['parent_id'])) {
global $wpdb;
$new_post['post_parent'] = $data['parent_id'];
if (isset($data['sort_order'])) {
$new_post['menu_order'] = $data['sort_order'];
} else {
$sort_order = $wpdb->get_var($wpdb->prepare("select max(menu_order)+1 from $wpdb->posts where post_parent = %s", $data['parent_id']));
if ($sort_order) {
$new_post['menu_order'] = $sort_order;
}
}
}
$is_update = is_array($data) && isset($data['post_id']);
if ($is_update) {
$new_post['ID'] = intval($data['post_id']);
$post_id = wp_update_post($new_post, true);
} else {
$post_id = wp_insert_post($new_post, true);
}
if (is_wp_error($post_id)) {
return [
'result' => 0,
'error' => $post_id->get_error_message(),
];
}
if (!empty($data['tags']) && is_array($data['tags'])) {
$rs = wp_set_post_tags($post_id, $data['tags']);
if (is_wp_error($rs)) {
$this->writeLog([
'type' => 'setPostTags',
'id' => $post_id,
'data' => $rs->get_error_message(),
'tags' => $data['tags'],
]);
}
}
$this->downloadImages($data, $post_id, isset($data['featured_image']), $is_update);
include_once(__DIR__ . '/classes/post-meta.php');
$pm = new \SEOWriting\PostMeta($post_id);
$pm->set($data);
@set_time_limit($maxExecutionTime);
add_post_meta($post_id, self::SETTINGS_GENERATOR_NAME_KEY, self::SETTINGS_GENERATOR_NAME, true);
add_post_meta($post_id, self::SETTINGS_GENERATOR_PAGE_TYPE, isset($data['ct']) ? seowriting_escape($data['ct']) : 'unk', true);
return [
'result' => 1,
'post_id' => $post_id,
'url' => wp_get_shortlink($post_id),
'slug' => get_permalink($post_id)
];
}
public function onSearchPages($where, $wp_query)
{
global $wpdb;
if ($search_term = $wp_query->get('post_title_like')) {
/** @phpstan-ignore-next-line */
$where .= ' AND ' . $wpdb->posts . '.post_title LIKE \'%' . esc_sql($wpdb->esc_like($search_term)) . '%\'';
}
return $where;
}
/**
* @param string $css
* @return string
*/
public function setCSS($css)
{
$css = trim($css);
if (strlen($css) === 0) {
return "empty css";
}
delete_option(self::SETTINGS_CSS_KEY);
if (intval(update_option(self::SETTINGS_CSS_KEY, $css)) === 1) {
file_put_contents($this->css_file, $css);
} else {
return "cannot update css option";
}
delete_option(self::SETTINGS_CSS_HASH_KEY);
if (!update_option(self::SETTINGS_CSS_HASH_KEY, md5($css))) {
return "cannot update css hash option";
}
return "";
}
/**
* @param string $query
* @param int $limit
*/
public function searchPages($query, $limit = 10)
{
if ($limit < 10) {
$limit = 10;
}
add_filter('posts_where', [$this, 'onSearchPages'], 10, 2);
$pages = new WP_Query([
'post_type' => 'page',
'post_title_like' => $query,
'posts_per_page' => $limit,
'post_status' => 'publish',
]);
remove_filter('posts_where', [$this, 'onSearchPages']);
$res = [];
if ($pages->have_posts()) {
while ($pages->have_posts()) {
$pages->the_post();
$res[] = [
'id' => get_the_ID(),
'title' => get_the_title(),
];
}
wp_reset_postdata();
}
return $res;
}
public function getVersion()
{
return $this->version;
}
public function getPost($post_id)
{
$post = get_post($post_id);
if (!$post || !($post instanceof WP_Post) || $post->post_status !== 'publish') {
return false;
}
return [
'id' => (int)$post->ID,
'content' => $post->post_content,
'title' => $post->post_title,
'url' => get_permalink($post->ID)
];
}
public function getPosts($page = 1, $per_page = 50)
{
$result = [];
$query = new WP_Query([
'post_type' => ['page', 'post'],
'post_status' => 'publish',
'posts_per_page' => $per_page,
'paged' => $page,
'order' => 'DESC',
'orderby' => 'ID'
]);
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
$result[] = [
'id' => intval(get_the_ID()),
'content' => get_the_content(),
'title' => get_the_title(),
'url' => get_permalink()
];
}
}
wp_reset_postdata();
return $result;
}
/**
* @return array<array<string, int|string>>
*/
public function getAuthors()
{
$users = get_users([
'role__in' => ['administrator', 'author', 'editor']
]);
$settings = $this->getSettings();
$settingsUserID = isset($settings['user_id']) ? (int)$settings['user_id'] : 0;
$result = [];
foreach ($users as $user) {
$data = [
'id' => (int)$user->ID,
'login' => $user->data->user_login,
];
if ($settingsUserID > 0 && (int)$user->ID === $settingsUserID) {
$data['default'] = 1;
}
$result[] = $data;
}
return $result;
}
public function getPostTypes()
{
return array_merge(['post', 'page'], get_post_types(['public' => true, '_builtin' => false]));
}
/**
* @return array<array<string, int|string>>
*/
public function getCategories($page_type = 'post')
{
$taxonomies = get_object_taxonomies($page_type, 'names');
$result = [];
foreach ($taxonomies as $taxonomy) {
$term_query = new WP_Term_Query([
'taxonomy' => $taxonomy,
'hide_empty' => false,
]);
if (!empty($term_query->terms)) {
foreach ($term_query->terms as $term) {
if ($term->taxonomy === 'post_tag' || $term->taxonomy === 'elementor_library_type') {
continue;
}
$result[] = [
'id' => (int)$term->term_id,
'name' => $term->name,
'parent' => (int)$term->parent
];
}
}
}
return $result;
}
/**
* @return \SEOWriting\APIClient
*/
public function getAPIClient()
{
if (is_null($this->api_client)) {
require_once($this->plugin_path . 'classes/api-client.php');
$this->api_client = new \SEOWriting\APIClient($this);
}
return $this->api_client;
}
public function adminPages()
{
include_once($this->plugin_path . 'classes/settings-form.php');
$form = new \SEOWriting\SettingsForm($this);
$form->init();
}
public function deactivate()
{
if ($this->isConnected()) {
$this->disconnect();
}
$this->deleteSettings();
}
private function writeLog($s)
{
if (!is_array($s)) {
$s = [
'source' => $s,
];
}
$s['now'] = gmdate('Y-m-d H:i:s');
if (!file_exists($this->log_file)) {
@file_put_contents($this->log_file, "<?php die(); ?>\n\n");
}
@file_put_contents($this->log_file, seowriting_json_encode_unescaped($s) . "\n", FILE_APPEND);
}
/**
* @static
* @return SEOWriting
*/
public static function i()
{
return new SEOWriting();
}
}
SEOWriting::i();
}