Fix File
•
/
home
/
sportsfe...
/
httpdocs
/
wp-conte...
/
plugins
/
flow-flo...
/
libs
/
flowflow
/
core
/
src
/
db
•
File:
LADBManager.php
•
Content:
<?php namespace la\core\db; use Exception; use la\core\LAUtils; use la\core\settings\LAGeneralSettings; use la\core\settings\LASettingsUtils; use mysqli; use Unirest\Request; use Unirest\Response; if ( ! defined( 'WPINC' ) ) die; /** * FlowFlow. * * @property LASafeMySQL $conn * * @package FlowFlow * @author Looks Awesome <email@looks-awesome.com> * * @link https://looks-awesome.com * @copyright Looks Awesome */ abstract class LADBManager { public $table_prefix; public $option_table_name; public $posts_table_name; public $cache_table_name; public $streams_table_name; public $image_cache_table_name; public $streams_sources_table_name; public $snapshot_table_name; public $comments_table_name; public $post_media_table_name; protected $context; protected $plugin_slug; protected $plugin_slug_down; protected $init = false; protected $sources = null; protected $streams = null; private $conn = null; /** * LADBManager constructor. * * @param array $context */ function __construct($context) { $this->context = $context; $this->table_prefix = $context['table_name_prefix']; $this->plugin_slug = LAUtils::slug($context); $this->plugin_slug_down = LAUtils::slug_down($context); $this->option_table_name = $this->table_prefix . 'options'; $this->posts_table_name = $this->table_prefix . 'posts'; $this->cache_table_name = $this->table_prefix . 'cache'; $this->streams_table_name = $this->table_prefix . 'streams'; $this->image_cache_table_name = $this->table_prefix . 'image_cache'; $this->streams_sources_table_name = $this->table_prefix . 'streams_sources'; $this->snapshot_table_name= $this->table_prefix . 'snapshots'; $this->comments_table_name= $this->table_prefix . 'comments'; $this->post_media_table_name = $this->table_prefix . 'post_media'; } public function conn($reopen = false) { if ($reopen || $this->conn == null){ $this->conn = LADB::create(); $this->conn->autocommit(true); } return $this->conn; } /** * @param false $only_enable * @param false $safe * @param bool $remote * * @throws Exception */ public final function dataInit($only_enable = false, $safe = false, $remote = true){ $this->init = true; $conn = $this->conn(); if ($safe && !LADDLUtils::existTable($conn, $this->streams_sources_table_name)) { $this->sources = []; $this->streams = []; return; } $boosted = []; $load_boosted = false; $sources = LADB::sources($conn, $this->cache_table_name, $this->streams_sources_table_name, null, $only_enable); if ($remote) { foreach ( $sources as $id => &$tmp_source ) { if ($tmp_source['boosted'] == LASettingsUtils::YEP){ if (!$load_boosted){ $boosted = $this->getBoostSources(); $load_boosted = true; } if (isset($boosted[$id])){ $tmp_source = $boosted[$id]; } } } } $this->sources = $sources; $this->streams = LADB::streams($conn, $this->streams_table_name); $connections = $conn->getIndMultiRow('stream_id', 'select `stream_id`, `feed_id` from ?n order by `stream_id`', $this->streams_sources_table_name); foreach ( $this->streams as &$stream ) { $stream = (array)LADB::unserializeStream($stream); if (!isset($stream['feeds'])) $stream['feeds'] = []; $stream['status'] = '1'; if (isset($connections[$stream['id']])){ foreach ($connections[$stream['id']] as $source){ if (isset($this->sources[$source['feed_id']])){ $full_source = $this->sources[$source['feed_id']]; $stream['feeds'][] = $full_source; if (isset($full_source['status']) && $full_source['status'] == 0) $stream['status'] = '0'; } } } } } /** * Get stream settings by id endpoint * @throws Exception */ public final function get_stream_settings(){ if (FF_USE_WP) { if (!current_user_can('manage_options') || !check_ajax_referer( 'flow_flow_nonce', 'security', false ) ) { die( json_encode( [ 'error' => 'not_allowed' ] ) ); } } $id = $_GET['stream-id']; $this->dataInit(false, false); $stream = $this->streams[$id]; // cleaning if error was saved in database stream model, can be removed in future, now it's needed for affected users if ( isset( $stream['error'] ) ) unset( $stream['error'] ); die( json_encode( $stream ) ); } public final function get_shortcode_pages() { global $wpdb; if (FF_USE_WP) { if (!current_user_can('manage_options') || !check_ajax_referer( 'flow_flow_nonce', 'security', false ) ) { die( json_encode( [ 'error' => 'not_allowed' ] ) ); } } $stream = $_POST['stream']; $query = "SELECT ID, post_title FROM " . $wpdb->posts . " WHERE post_content LIKE '%s' AND post_status = 'publish'"; $results = $wpdb->get_results ( $wpdb->prepare( $query, '%[ff id="' . $stream . '"%' ) ); foreach ($results as $result) { $result->url = get_permalink( $result->ID ); } die( json_encode( $results ) ); } /** * Create stream endpoint */ public final function create_stream(){ $this->checkSecurity(); $stream = $this->getStreamFromRequestWithoutErrors(); $conn = $this->conn(); try{ $conn->beginTransaction(); if (false !== ($max = LADB::maxIdOfStreams( $conn, $this->streams_table_name))){ $newId = (string) ($max + 1); $stream->id = $newId; $stream->feeds = isset($stream->feeds) ? $stream->feeds : json_encode( [] ); $stream->name = isset($stream->name) ? $stream->name : ''; LADB::setStream($conn, $this->streams_table_name, $this->streams_sources_table_name, $newId, $stream); $response = json_encode(LADB::getStream($conn, $this->streams_table_name, $newId)); $conn->commit(); $this->refreshCache($newId); echo $response; } else echo false; }catch ( Exception $e){ $conn->rollbackAndClose(); echo 'Caught exception: ' . $e->getMessage() . "\n"; } $conn->close(); die(); } /** * Save sources endpoint * @throws Exception */ public final function save_sources_settings(){ if (FF_USE_WP) { if (!current_user_can('manage_options') || !check_ajax_referer( 'flow_flow_nonce', 'security', false ) ) { $dontChange = true; } } if (isset($_POST['model'])){ $model = $_POST['model']; $model['id'] = 1; // DON'T DELETE, ID is always 1, this is needed to detect if model was saved if (isset( $dontChange ) && isset( $_POST['model']['feeds_changed'] )) { unset( $_POST['model']['feeds_changed'] ); } $boosted = false; $original_status = 0; if (isset($_POST['model']['feeds_changed'])){ foreach ( $_POST['model']['feeds_changed'] as $feed ) { switch ($feed['state']) { case 'changed': $source = $_POST['model']['feeds'][ $feed['id'] ]; $original_status = $source['status']; $sources = LADB::sources($this->conn(), $this->cache_table_name, $this->streams_sources_table_name); $old = $sources[$source['id']]; $changed_content = $this->changedContent($source, $old); if ($changed_content) { $this->cleanFeed($feed['id']); if (!$boosted){ $boosted = LASettingsUtils::YepNope2ClassicStyle($source['boosted'], false); if (!$boosted && ($source['boosted'] != $old['boosted'])){ $boosted = true; } } } else if (!$boosted){ $boosted = LASettingsUtils::YepNope2ClassicStyle($source['boosted'], false); } $this->modifySource( $source, $changed_content ); if ($source['enabled'] == 'yep') { $this->refreshCache4Source($feed['id'], false, $boosted); } break; case 'created': $source = $_POST['model']['feeds'][$feed['id']]; $this->modifySource($source); if (!$boosted){ $boosted = LASettingsUtils::YepNope2ClassicStyle($source['boosted'], false); } $this->refreshCache4Source($feed['id'], true, $boosted); break; case 'reset_cache': $source = $_POST['model']['feeds'][ $feed['id'] ]; $this->cleanFeed($feed['id']); if (!$boosted){ $boosted = LASettingsUtils::YepNope2ClassicStyle($source['boosted'], false); } $this->refreshCache4Source($feed['id'], true, $boosted); break; case 'deleted': $sources = LADB::sources($this->conn(), $this->cache_table_name, $this->streams_sources_table_name); if (isset($sources[$feed['id']])){ $source = $sources[$feed['id']]; $this->deleteFeed($feed['id']); if (!$boosted){ $boosted = LASettingsUtils::YepNope2ClassicStyle($source['boosted'], false); } } break; } } } if ($boosted){ $response = $this->proxyRequest($_POST); if ($response->code == 200){ $json = $response->body; foreach ( $json['feeds'] as &$feed ) { $enabled = LASettingsUtils::YepNope2ClassicStyle($feed['enabled'], false) ? 1 : 0; $status = ['last_update' => $feed['last_update'], 'status' => $original_status, 'enabled' => $enabled]; if (isset($feed['errors']) && is_array($feed['errors'])) $status['errors'] = serialize($feed['errors']); $this->saveSource($feed['id'], $status); $feed['last_update'] = $feed['last_update'] == 0 ? 'N/A' : LASettingsUtils::classicStyleDate($feed['last_update']); } echo json_encode($json); } else if ($response->code == 504){ header('HTTP/1.1 504 Gateway Time-out'); } else if ($response->code == 403){ header('HTTP/1.1 403 Forbidden'); echo $response->raw_body; } } else { if (isset($model['feeds'])){ $this->dataInit(); $sources = $this->sources(); foreach ( $model['feeds'] as &$source ) { if (array_key_exists($source['id'], $sources)){ $source = $sources[$source['id']]; } } } if (isset( $dontChange )) { $model['error'] = 'Not allowed'; } echo json_encode($model); } die(); } die(1); } /** * Save stream endpoint */ public final function save_stream_settings(){ $this->checkSecurity(); $stream = $this->getStreamFromRequestWithoutErrors(); $conn = $this->conn(); try{ $conn->beginTransaction(); $stream->last_changes = time(); LADB::setStream($conn, $this->streams_table_name, $this->streams_sources_table_name, $stream->id, $stream); $this->generateCss($stream); echo json_encode($stream); $conn->commit(); $this->proxyRequest($_POST); }catch (Exception $e){ $conn->rollbackAndClose(); error_log('save_stream_settings error:'); error_log($e->getMessage()); error_log($e->getTraceAsString()); } $conn->close(); die(); } /** * Save general settings endpoint */ public final function ff_save_settings_fn() { if (FF_USE_WP) { if (!current_user_can('manage_options') || !check_ajax_referer( 'flow_flow_nonce', 'security', false ) ) { die( json_encode( [ 'error' => 'not_allowed' ] ) ); } } $serialized_settings = $_POST['settings']; // param1=foo¶m2=bar $settings = []; parse_str( $serialized_settings, $settings ); $conn = $this->conn(); try{ $activated = $this->activate($settings); $force_load_cache = $this->clean_cache($settings); $conn->beginTransaction(); $settings = $this->saveGeneralSettings($settings); $conn->commit(); global $wp_locale; $_POST['wp_locale'] = json_encode($wp_locale); $_POST['wp_timezone_string'] = get_option( 'timezone_string' ); $_POST['wp_date_format'] = get_option( 'date_format' ); $_POST['wp_time_format'] = get_option( 'time_format' ); if (false !== ($option = get_option( 'la_facebook_access_token', false ))) $_POST['la_facebook_access_token'] = $option; if (false !== ($option = get_option( 'la_facebook_access_token_expires', false ))) $_POST['la_facebook_access_token_expires'] = $option; $this->proxyRequest($_POST); if ($force_load_cache) { $this->refreshCache(null, $force_load_cache); } $response = [ 'settings' => $settings, 'activated' => $activated ]; $this->customizeResponse($response); echo json_encode( $response ); }catch ( Exception $e){ error_log('ff_save_settings_fn error:'); $msg = $e->getMessage(); if ( strpos( $msg, 'Connection timed out after') !== false ) { $msg .= '. Failed to connect to https://flow.looks-awesome.com which validates purchase code. Please ask help from your hosting support and tell them curl_exec exits with connection timeout error on line 889 of wp-content/plugins/flow-flow/includes/db/LADBManager.php'; } error_log( $msg ); error_log($e->getTraceAsString()); $conn->rollbackAndClose(); die($e->getMessage()); } $conn->close(); die(); } /** * @param mixed $old_value * @param mixed $value * @param string $option * * @noinspection PhpUnusedParameterInspection * @throws Exception */ public function update_wp_date_format_hook($old_value, $value, $option){ if ($option === 'WPLANG'){ switch_to_locale(empty($value) ? 'en_US' : $value); } global $wp_locale; $post['action'] = 'flow_flow_save_settings_date_format'; $post['wp_locale'] = json_encode($wp_locale); $post['wp_timezone_string'] = get_option( 'timezone_string' ); $post['wp_date_format'] = get_option( 'date_format' ); $post['wp_time_format'] = get_option( 'time_format' ); $this->proxyRequest($post); } /** * @throws Exception */ public function update_options(){ $data = [ 'action' => 'flow_flow_save_settings', 'options' => $this->getOption('options', false, false, true), 'fb_auth_options' => $this->getOption('fb_auth_options', false, false, true) ]; if (false != ($la_facebook_access_token = get_option('la_facebook_access_token', false))){ $data['la_facebook_access_token'] = $la_facebook_access_token; } if (false != ($la_facebook_access_token_expires = get_option('la_facebook_access_token_expires', false))) { $data['la_facebook_access_token_expires'] = $la_facebook_access_token_expires; } $this->proxyRequest($data); } /** * @throws Exception */ public function get_sources( ) { if (FF_USE_WP) { if (!current_user_can('manage_options') || !check_ajax_referer( 'flow_flow_nonce', 'security', false ) ) { die( json_encode( [ 'error' => 'not_allowed' ] ) ); } } $this->dataInit(false, false); if (isset($_REQUEST['id']) && !empty($_REQUEST['id'])){ if (isset($this->sources[$_REQUEST['id']])){ die( json_encode( $this->sources[$_REQUEST['id']] ) ); } else { header("HTTP/1.0 404 Not Found"); die(); } } die( json_encode( $this->sources ) ); } /** * @throws Exception */ public final function get_boosts(){ if ( FF_USE_WP ) { if ( !current_user_can('manage_options') || !check_ajax_referer( 'flow_flow_nonce', 'security', false ) ) { die( json_encode( [ 'error' => 'not_allowed' ] ) ); } } if ( isset($_POST['not_active']) ) { // return dummy $response = [ 'status' => 'never_used', // 'active', 'cancelled', 'paused' 'plan' => 0, 'available' => 0, 'expire' => 0 ]; echo json_encode( $response ); die(); } if (null != ($token = $this->getToken())){ $response = Request::post(FF_BOOST_SERVER . 'flow-flow/ff', [ 'Content-Type: application/x-www-form-urlencoded' ], http_build_query(['action' => 'get_subscription', 'token' => $token])); if ($response->code == 200 && !empty($response->raw_body) && is_object($response->body)) { $subscription = json_encode($response->body); if (JSON_ERROR_NONE == json_last_error()){ echo $subscription; } else { error_log($response->raw_body); } } else if ($this->isExpiredToken($response)){ $this->get_boosts(); } else { error_log($response->raw_body); } } die; } /** * @throws Exception */ public function paymentSuccess(){ $email = $_REQUEST['email']; $checkout_id = $_REQUEST['checkout_id']; $this->setOption( 'boosts_email', $email); $this->setOption( 'boosts_checkout_id', $checkout_id); $this->deleteOption('boosts_token'); $this->deleteOption('boosts_subscription'); $domain = $_SERVER['HTTP_HOST']; $url = FF_BOOST_SERVER . 'registration?shop=' . $domain; $data = [ 'action' => 'domain_registration', 'email' => $email, 'checkout_id' => $checkout_id, 'options' => $this->getOption('options', false, false, true), 'fb_auth_options' => $this->getOption('fb_auth_options', false, false, true), 'url' => get_site_url() ]; global $wp_locale; $data['wp_locale'] = json_encode($wp_locale); $data['wp_timezone_string'] = get_option( 'timezone_string' ); $data['wp_date_format'] = get_option( 'date_format' ); $data['wp_time_format'] = get_option( 'time_format' ); if (false != ($la_facebook_access_token = get_option('la_facebook_access_token', false))){ $data['la_facebook_access_token'] = $la_facebook_access_token; } if (false != ($la_facebook_access_token_expires = get_option('la_facebook_access_token_expires', false))) { $data['la_facebook_access_token_expires'] = $la_facebook_access_token_expires; } Request::jsonOpts(true); Request::timeout(120); $response = Request::post($url, [ 'Content-Type: application/x-www-form-urlencoded' ], http_build_query($data)); if ($response->code != 200) { error_log($response->raw_body); $this->deleteOption('boosts_email'); $this->deleteOption('boosts_checkout_id'); if ($response->code == 403 && isset($response->body['error']) && $response->body['error'] == 'Exceeded the limit on the number of domains') { header('Location: ' . admin_url('admin.php?page=flow-flow-admin&subscription=exceeded_domains'), true, 301); die(); } } header('Location: ' . admin_url('admin.php?page=flow-flow-admin&subscription=1'), true, 301); die(); } /** * @throws Exception */ public function upgradeSubscription() { if (null != ($token = $this->getToken())){ $plan_id = $_REQUEST['plan_id']; $response = Request::post(FF_BOOST_SERVER . 'flow-flow/ff', [ 'Content-Type: application/x-www-form-urlencoded' ], http_build_query(['action' => 'upgrade_subscription', 'token' => $token, 'plan_id' => $plan_id])); if ($response->code == 200) { $response->body = (array)$response->body; if ($response->body['success']){ header('Location: ' . admin_url('admin.php?page=flow-flow-admin'), true, 301); die; } } else if ($this->isExpiredToken($response)){ $this->upgradeSubscription(); } else { error_log($response->raw_body); } } error_log('FLOW-FLOW DEBUG: no subscription token' ); http_response_code(500); die; } /** * @throws Exception */ public function cancelSubscription() { if (null != ($token = $this->getToken())){ $response = Request::post(FF_BOOST_SERVER . 'flow-flow/ff', [ 'Content-Type: application/x-www-form-urlencoded' ], http_build_query(['action' => 'cancel_subscription', 'token' => $token])); if ($response->code == 200) { $response->body = (array)$response->body; if ($response->body['success']){ $this->deleteOption('boosts_email'); $this->deleteOption('boosts_token'); $this->deleteOption('boosts_checkout_id'); $this->deleteOption('boosts_subscription'); $this->deleteBoostedFeeds(); header('Location: ' . admin_url('admin.php?page=flow-flow-admin'), true, 301); die; } } else if ($this->isExpiredToken($response)){ $this->cancelSubscription(); } else { error_log($response->raw_body); } } error_log('FLOW-FLOW DEBUG: no subscription token' ); http_response_code(500); die; } /** * @throws Exception */ public function clearSubscriptionCache() { if (isset($_REQUEST['email'])){ $email = $_REQUEST['email']; $this->setOption( 'boosts_email', $email); } if (isset($_REQUEST['checkout_id'])){ $checkout_id = $_REQUEST['checkout_id']; $this->setOption( 'boosts_checkout_id', $checkout_id); } $this->deleteOption('boosts_token'); $this->deleteOption('boosts_subscription'); die; } public final function email_notification(){ $admin_email = get_option('admin_email'); if (!empty($admin_email)){ $conn = $this->conn(); $disabled_feeds = $conn->getAll('SELECT * FROM ?n WHERE enabled = 1 AND system_enabled = 0 AND send_email = 0', $this->cache_table_name); if (!empty($disabled_feeds)){ ob_start(); /** @noinspection PhpIncludeInspection */ include($this->context['root'] . 'views/email.php'); $message = ob_get_clean(); $headers = []; $headers[] = 'MIME-Version: 1.0'; $headers[] = 'Content-type: text/html; charset=iso-8859-1'; $headers[] = 'X-Mailer: PHP/' . phpversion(); // $headers[] = 'To: ' . $admin_email; $headers[] = 'From: Social Stream Apps <' . $admin_email . '>'; $blog_name = htmlspecialchars_decode(get_bloginfo('name')); $success = mail($admin_email, "[Flow-Flow] Broken feeds detected on " . $blog_name, $message, implode("\r\n", $headers)); if ($success) { try { $conn->beginTransaction(); foreach ( $disabled_feeds as $feed ) { $success = $this->saveSource($feed['feed_id'], [ 'send_email' => 1 ] ); if (!$success){ throw new Exception('Save source problem'); } } $conn->commit(); } catch ( Exception $e){ error_log('email_notification'); error_log($e->getMessage()); error_log($e->getTraceAsString()); $conn->rollbackAndClose(); } } else { $errorMessage = error_get_last(); error_log($errorMessage['message']); } } } } public function modifySource($source, $changed_content = true, $with_errors = false){ $errors = ''; $id = $source['id']; $enabled = $source['enabled']; $cache_lifetime = $source['cache_lifetime']; $status = isset($source['status']) ? intval($source['status']) : 0; $boosted = $source['boosted']; unset($source['id']); unset($source['enabled']); unset($source['last_update']); unset($source['cache_lifetime']); unset($source['boosted']); if ($with_errors && isset($source['errors'])){ $errors = serialize($source['errors']); } if (isset($source['errors'])) unset($source['errors']); if (isset($source['status'])) unset($source['status']); if (isset($source['system_enabled'])) unset($source['system_enabled']); $in = [ 'settings' => serialize((object)$source), 'enabled' => (int)LASettingsUtils::YepNope2ClassicStyle($enabled, true), 'system_enabled' => (int)LASettingsUtils::YepNope2ClassicStyle($enabled, true), 'last_update' => 0, 'changed_time' => time(), 'cache_lifetime' => $cache_lifetime, 'status' => $status, 'boosted' => $boosted ]; $up = [ 'settings' => serialize((object)$source), 'enabled' => (int)LASettingsUtils::YepNope2ClassicStyle($enabled, true), 'system_enabled' => (int)LASettingsUtils::YepNope2ClassicStyle($enabled, true), 'cache_lifetime' => $cache_lifetime, 'boosted' => $boosted ]; if ($changed_content) $up['last_update'] = '0'; if ($with_errors && !empty($errors)) $up['errors'] = $errors; $conn = $this->conn(); try { if ( false === $conn->query( 'INSERT INTO ?n SET `feed_id`=?s, ?u ON DUPLICATE KEY UPDATE ?u', $this->cache_table_name, $id, $in, $up ) ) { throw new Exception(); } $conn->commit(); } catch ( Exception $e){ $conn->rollback(); } } private function changedContent( $source, $old ) { foreach ( $source as $key => $value ) { $old_value = $old[$key]; if ($key == 'status' || $key == 'enabled' || $key == 'posts' || $key == 'errors' || $key == 'last_update' || $key == 'cache_lifetime' || $key == 'mod' || $key == 'posts') continue; if ($old_value !== $value) { return true; } } return false; } public function getGeneralSettings(){ return new LAGeneralSettings($this->getOption('options', true), $this->getOption('fb_auth_options', true)); } public function getOption( $optionName, $serialized = false, $lock_row = false, $without_cache = false ) { $options = LADB::getOption($this->conn(), $this->option_table_name, $this->plugin_slug_down . '_' . $optionName, $serialized, $lock_row, $without_cache); if ($optionName == 'options' && is_array($options)) { $options['general-uninstall'] = get_option($this->plugin_slug_down . '_general_uninstall', LASettingsUtils::NOPE); } return $options; } /** * @param $optionName * @param $optionValue * @param false $serialized * @param bool $cached * * @throws Exception */ public function setOption($optionName, $optionValue, $serialized = false, $cached = true){ LADB::setOption($this->conn(), $this->option_table_name, $this->plugin_slug_down . '_' . $optionName, $optionValue, $serialized, $cached); } /** * @param $optionName * * @throws Exception */ public function deleteOption($optionName){ LADB::deleteOption($this->conn(), $this->option_table_name, $this->plugin_slug_down . '_' . $optionName); } /** * @return array * @throws Exception */ public function streams(){ if ($this->init) return $this->streams; throw new Exception('Don`t init data manager'); } public function countFeeds(){ return LADB::countFeeds($this->conn(), $this->cache_table_name); } public function getStream($streamId){ return $this->streams[$streamId]; } public function delete_stream(){ if (FF_USE_WP) { if (!current_user_can('manage_options') || !check_ajax_referer( 'flow_flow_nonce', 'security', false ) ) { die( json_encode( [ 'error' => 'not_allowed' ] ) ); } } $conn = $this->conn(); try { $conn->beginTransaction(); $id = $_POST['stream-id']; LADB::deleteStream($conn, $this->streams_table_name, $this->streams_sources_table_name, $id); do_action('ff_after_delete_stream', $id); $conn->commit(); $this->proxyRequest($_POST); } catch (Exception $e){ error_log($e->getMessage()); error_log($e->getTraceAsString()); $conn->rollbackAndClose(); die(false); } wp_send_json([], 200); } public function canCreateCssFolder(){ $dir = WP_CONTENT_DIR . '/resources/' . $this->context['slug'] . '/css'; if(!file_exists($dir)){ return mkdir($dir, 0777, true); } return true; } public function generateCss($stream){ $dir = WP_CONTENT_DIR . '/resources/' . $this->context['slug'] . '/css'; if(!file_exists($dir)){ mkdir($dir, 0777, true); } $filename = $dir . "/stream-id" . $stream->id . ".css"; if (!is_main_site()){ $filename = $dir . '/stream-id' . $stream->id . '-'. get_current_blog_id() . '.css'; } ob_start(); /** @noinspection PhpIncludeInspection */ include($this->context['root'] . 'views/stream-template-css.php'); $output = ob_get_clean(); $a = fopen($filename, 'w'); fwrite($a, $output); fclose($a); chmod($filename, 0644); } public function clone_stream(){ if (FF_USE_WP) { if (!current_user_can('manage_options') || !check_ajax_referer( 'flow_flow_nonce', 'security', false ) ) { die( json_encode( [ 'error' => 'not_allowed' ] ) ); } } $stream = $_REQUEST['stream']; // cleaning if error was saved in database stream model, can be removed in future, now it's needed for affected users if ( isset( $stream['error'] ) ) unset( $stream['error'] ); $stream = (object)$stream; $conn = $this->conn(); try{ $conn->beginTransaction(); if (false !== ($count = LADB::maxIdOfStreams( $conn, $this->streams_table_name))) { $newId = (string) ($count + 1); $stream->id = $newId; $stream->name = "{$stream->name} copy"; $stream->last_changes = time(); LADB::setStream($conn, $this->streams_table_name, $this->streams_sources_table_name, $newId, $stream); $this->generateCss($stream); $this->proxyRequest($_POST); $conn->commit(); echo json_encode($stream); } else { throw new Exception('Can`t get a new id for the clone stream'); } }catch (Exception $e){ $conn->rollbackAndClose(); error_log('clone_stream error:'); error_log($e->getMessage()); error_log($e->getTraceAsString()); } $conn->close(); die(); } /** * @param $settings * * @return mixed * @throws Exception */ protected function saveGeneralSettings($settings){ if (isset($settings['flow_flow_options']['general-uninstall'])){ $general_uninstall_option_name = $this->plugin_slug_down . '_general_uninstall'; $value = ($settings['flow_flow_options']['general-uninstall'] === LASettingsUtils::YEP) ? LASettingsUtils::YEP : LASettingsUtils::NOPE; if ( get_option( $general_uninstall_option_name) !== false ) { update_option( $general_uninstall_option_name, $value ); } else { add_option( $general_uninstall_option_name, $value, '', 'no' ); } unset($settings['flow_flow_options']['general-uninstall']); } $this->setOption('options', $settings['flow_flow_options'], true); return $settings; } protected abstract function customizeResponse(&$response); protected abstract function clean_cache($options); protected abstract function refreshCache($streamId, $force_load_cache = false); protected function refreshCache4Source($id, $force_load_cache = false, $boosted = false){ if (!$boosted){ $this->saveSource($id, ['status' => '2']); $useIpv4 = $this->getGeneralSettings()->useIPv4(); $use = $this->getGeneralSettings()->useCurlFollowLocation(); $url = $this->getLoadCacheUrl( $id, $force_load_cache ); LASettingsUtils::get( $url, 1, false, false, $use, $useIpv4); } } /** * @return array|null * @throws Exception */ public function streamsWithStatus(){ if (false !== ($result = self::streams())){ return $result; } return []; } /** * @return array | null * @throws Exception */ public function sources(){ if ($this->init) return $this->sources; throw new Exception('Don`t init data manager'); } //TODO: refactor posts table does not have field with name stream_id public function clean(array $streams = null){ $conn = $this->conn(); $partOfSql = $streams == null ? '' : $conn->parse('WHERE `stream_id` IN (?a)', $streams); try{ if ($conn->beginTransaction()){ $conn->query('DELETE FROM ?n ?p', $this->posts_table_name, $partOfSql); $conn->query('DELETE FROM ?n', $this->image_cache_table_name); $conn->commit(); } $conn->rollback(); }catch ( Exception $e){ $conn->rollbackAndClose(); } } public function deleteFeed($feedId){ $conn = $this->conn(); try{ if ($conn->beginTransaction()){ $partOfSql = $conn->parse('WHERE `feed_id` = ?s', $feedId); $conn->query('DELETE FROM ?n ?p', $this->posts_table_name, $partOfSql); $conn->query('DELETE FROM ?n ?p', $this->post_media_table_name, $partOfSql); $conn->query('DELETE FROM ?n ?p', $this->cache_table_name, $partOfSql); $conn->query('DELETE FROM ?n ?p', $this->streams_sources_table_name, $partOfSql); $conn->commit(); } $conn->rollback(); }catch ( Exception $e){ $conn->rollbackAndClose(); } } public function cleanFeed($feedId){ $conn = $this->conn(); try{ if ($conn->beginTransaction()){ $partOfSql = $conn->parse('WHERE `feed_id` = ?s', $feedId); $conn->query('DELETE FROM ?n ?p', $this->posts_table_name, $partOfSql); $conn->query('DELETE FROM ?n ?p', $this->post_media_table_name, $partOfSql); $this->setCacheInfo($feedId, [ 'last_update' => 0, 'status' => 0 ] ); $conn->commit(); } $conn->rollback(); }catch (Exception $e){ $conn->rollbackAndClose(); } } public function cleanByFeedType($feedType){ $conn = $this->conn(); try{ if ($conn->beginTransaction()){ $feeds = $conn->getCol('SELECT DISTINCT `feed_id` FROM ?n WHERE `post_type` = ?s', $this->posts_table_name, $feedType); if (!empty($feeds)){ $conn->query("DELETE FROM ?n WHERE `feed_id` IN (?a)", $this->posts_table_name, $feeds); $conn->query("DELETE FROM ?n WHERE `feed_id` IN (?a)", $this->post_media_table_name, $feeds); $conn->commit(); } } $conn->rollback(); }catch (Exception $e){ $conn->rollbackAndClose(); } } /** * @param $only4insertPartOfSql * @param $imagePartOfSql * @param $mediaPartOfSql * @param $common * * @throws Exception */ public function addOrUpdatePost($only4insertPartOfSql, $imagePartOfSql, $mediaPartOfSql, $common){ $sql = "INSERT INTO ?n SET ?p, ?p ?p ?u ON DUPLICATE KEY UPDATE ?p ?p ?u"; if (false == $this->conn()->query($sql, $this->posts_table_name, $only4insertPartOfSql, $imagePartOfSql, $mediaPartOfSql, $common, $imagePartOfSql, $mediaPartOfSql, $common)){ throw new Exception($this->conn()->getError()); } } /** * @param $posts * * @throws Exception */ public function updateAdditionalInfo($posts){ $conn = $this->conn(); foreach ($posts as $post) { $sql = $conn->parse('UPDATE ?n SET `post_additional` = ?s WHERE `post_id` = ?s AND `feed_id` = ?s AND `post_type` = ?s', $this->posts_table_name, json_encode($post->additional), $post->id, $post->feed_id, $post->type); if (false == $conn->query($sql)){ throw new Exception($conn->getError()); } } } public function getCarousel($feed_id, $post_id){ return $this->conn(true)->getAll('SELECT `feed_id`, `post_id`, `media_url`, `media_width`, `media_height`, `media_type` FROM ?n WHERE `feed_id`=?s AND `post_id`=?s', $this->post_media_table_name, $feed_id, $post_id); } /** * @param $feed_id * @param $post_id * @param $post_type * @param $mediaPartOfSql4carousel * * @throws Exception */ public function addCarouselMedia($feed_id, $post_id, $post_type, $mediaPartOfSql4carousel){ $common = []; $common['feed_id'] = $feed_id; $common['post_id'] = $post_id; $common['post_type'] = $post_type; $conn = $this->conn(); $sql = $conn->parse('INSERT INTO ?n SET ?p ?u', $this->post_media_table_name, $mediaPartOfSql4carousel, $common); if (false == $conn->query($sql)){ throw new Exception($conn->getError()); } } /** * @param $post_id * @param $comment * * @throws Exception */ public function addComments($post_id, $comment){ $time = time(); $sql_insert = "INSERT INTO ?n SET `id` = ?s, `post_id` = ?s, `from` = ?s, `text` = ?s, `created_time` = ?s, `updated_time` = ?s ON DUPLICATE KEY UPDATE ?u"; $result = $this->conn()->query($sql_insert, $this->comments_table_name, $comment->id, $post_id, is_string($comment->from) ? $comment->from : (is_object($comment->from) ? $comment->from->name : 'Facebook user' ), $comment->text, $comment->created_time, $comment->created_time, [ 'updated_time' => $time, 'text' => $comment->text ] ); if (false === $result){ throw new Exception($this->conn()->getError()); } } public function removeComments($post_id){ $sql_delete = "DELETE FROM ?n WHERE `post_id` = ?s"; $this->conn()->query($sql_delete, $this->comments_table_name, $post_id); } /** * @param $feed_id * @param $post_id * * @throws Exception */ public function deleteCarousel4Post($feed_id, $post_id){ $sql = "delete from ?n where feed_id = ?s and post_id = ?s"; if (false == $this->conn()->query($sql, $this->post_media_table_name, $feed_id, $post_id)){ throw new Exception($this->conn()->getError()); } } /** * @param $feed_id * * @throws Exception */ public function deleteCarousel4Feed($feed_id){ $sql = "delete from ?n where feed_id = ?s"; if (false == $this->conn()->query($sql, $this->post_media_table_name, $feed_id)){ throw new Exception($this->conn()->getError()); } } /** * @param string $feedId * * @return array|false */ public function getIdPosts($feedId){ return $this->conn(true)->getCol('SELECT `post_id` FROM ?n WHERE `feed_id`=?s', $this->posts_table_name, $feedId); } public function getPostsIf($fields, $condition, $order, $offset = null, $limit = null){ $conn = $this->conn(); $limitPart = ($offset !== null) ? $conn->parse("LIMIT ?i, ?i", $offset, $limit) : ''; $sql = $conn->parse("SELECT ?p FROM ?n post INNER JOIN ?n stream ON stream.feed_id = post.feed_id INNER JOIN ?n cach ON post.feed_id = cach.feed_id WHERE ?p ORDER BY ?p ?p", $fields, $this->posts_table_name, $this->streams_sources_table_name, $this->cache_table_name, $condition, $order, $limitPart); return $conn->getAll($sql); } public function getPostsIf2($fields, $condition){ return $this->conn()->getAll("SELECT ?p FROM ?n post INNER JOIN ?n stream ON stream.feed_id = post.feed_id INNER JOIN ?n cach ON post.feed_id = cach.feed_id WHERE ?p ORDER BY post.post_timestamp DESC, post.post_id", $fields, $this->posts_table_name, $this->streams_sources_table_name, $this->cache_table_name, $condition); } public function countPostsIf($condition){ return $this->conn()->getOne('SELECT COUNT(*) FROM ?n post INNER JOIN ?n stream ON stream.feed_id = post.feed_id INNER JOIN ?n cach ON post.feed_id = cach.feed_id WHERE ?p', $this->posts_table_name, $this->streams_sources_table_name, $this->cache_table_name, $condition); } public function getLastUpdateHash($streamId){ return $this->getHashIf($this->conn()->parse('stream.`stream_id` = ?s', $streamId)); } public function getHashIf($condition){ return $this->conn()->getOne("SELECT MAX(post.creation_index) FROM ?n post INNER JOIN ?n stream ON stream.feed_id = post.feed_id INNER JOIN ?n cach ON post.feed_id = cach.feed_id WHERE cach.boosted = 'nope' AND ?p", $this->posts_table_name, $this->streams_sources_table_name, $this->cache_table_name, $condition); } public function getLastUpdateTime($streamId){ return $this->conn()->getOne('SELECT MAX(`last_update`) FROM ?n `cach` inner join ?n `st2src` on `st2src`.`feed_id` = `cach`.`feed_id` WHERE `stream_id` = ?s', $this->cache_table_name, $this->streams_sources_table_name, $streamId); } public function getLastUpdateTimeAllStreams(){ return $this->conn()->getIndCol('stream_id', 'SELECT MAX(`last_update`), `stream_id` FROM ?n `cach` inner join ?n `st2src` on `st2src`.`feed_id` = `cach`.`feed_id` GROUP BY `stream_id`', $this->cache_table_name, $this->streams_sources_table_name); } public function deleteEmptyRecordsFromCacheInfo($streamId){ //$this->conn()->query("DELETE FROM ?n where `stream_id`=?s", $this->cache_table_name, $streamId); } public function systemDisableSource($feedId, $enabled){ $values = [ 'system_enabled' => $enabled ]; if($enabled == 0){ $values['send_email'] = 0; } return $this->saveSource($feedId, $values); } public function saveSource( $feedId, $values ) { return LADB::saveFeed($this->conn(), $this->cache_table_name, $feedId, $values); } /** * @param $feedId * @param $values * * @return FALSE|mysqli|resource * @deprecated * Use \flow\db\LADBManager::saveSource */ public function setCacheInfo($feedId, $values){ $sql = 'INSERT INTO ?n SET `feed_id`=?s, ?u ON DUPLICATE KEY UPDATE ?u'; return $this->conn()->query( $sql, $this->cache_table_name, $feedId, $values, $values ); } public function setOrders($feedId){ $conn = $this->conn(); $conn->query('SET @ROW = -1;');//test mysql_query("SELECT @ROW = -1"); return $conn->query('UPDATE ?n SET `rand_order` = RAND(), `smart_order` = @ROW := @ROW+1 WHERE `feed_id`=?s ORDER BY post_timestamp DESC', $this->posts_table_name, $feedId); } public function removeOldRecords($c_count){ $conn = $this->conn(); $result = $conn->getAll('select count(*) as `count`, `feed_id` from ?n group by `feed_id` order by 1 desc', $this->posts_table_name); foreach ( $result as $row ) { $count = (int)$row['count']; if ($count > $c_count) { $feed = $row['feed_id']; $count = $count - $c_count; $sub_query = $conn->parse('select max(tmp.`post_timestamp`) from (select `post_timestamp` from ?n where `feed_id` = ?s order by `post_timestamp` limit 0, ?i) as tmp',$this->posts_table_name, $feed, $count); $sub_query2 = $conn->parse('select tmp2.post_id from ?n as tmp2 where tmp2.post_timestamp <= (?p)', $this->posts_table_name, $sub_query); $conn->query('delete from ?n where feed_id = ?s and post_id in (?p)', $this->post_media_table_name, $feed, $sub_query2); $conn->query('delete from ?n where feed_id = ?s and post_timestamp <= (?p)', $this->posts_table_name, $feed, $sub_query); continue; } } } /** * @param $status * @param $condition * @param null $creation_index * * @throws Exception */ public function setPostStatus($status, $condition, $creation_index = null){ $sql = "UPDATE ?n SET `post_status` = ?s"; $sql .= ($creation_index != null) ? ", `creation_index` = " . $creation_index . " ?p" : " ?p"; if (false == $this->conn()->query($sql, $this->posts_table_name, $status, $condition)){ throw new Exception($this->conn()->getError()); } } public abstract function getLoadCacheUrl($streamId = null, $force = false); /** * @return bool * @throws Exception */ public function registrationCheck(){ $activated = false; if (false !== ($registration_id = $this->getOption('registration_id'))){ if ((false !== ($registration_date = $this->getOption('registration_date'))) && (time() > $registration_date + 604800)){ $ch = curl_init( 'https://flow.looks-awesome.com/wp-admin/admin-ajax.php?action=la_check®istration_id=' . $registration_id); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 60); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, 5000); curl_setopt($ch, CURLOPT_POST, false); $result = curl_exec( $ch ); curl_close( $ch ); $result = json_decode($result); if (isset($result->registration_id) && $registration_id == $result->registration_id){ $settings = $this->getGeneralSettings(); $settings = $settings->original(); $current_subscription = $settings['news_subscription']; $remote_subscription = $result->subscription == "1" ? LASettingsUtils::YEP : LASettingsUtils::NOPE; if ($remote_subscription != $current_subscription){ $settings['news_subscription'] = $remote_subscription; $this->setOption('options', $settings, true); } $this->setOption('registration_id', $result->registration_id); $this->setOption('registration_date', time()); return true; } return false; } $activated = !empty($registration_id); } return $activated; } /** * @param $settings * * @return bool * @throws Exception */ private function activate($settings){ $activated = $this->registrationCheck(); $option_name = 'flow_flow_options'; if (!$activated && isset($settings[$option_name]['company_email']) && isset($settings[$option_name]['purchase_code']) && !empty($settings[$option_name]['company_email']) && !empty($settings[$option_name]['purchase_code'])){ $name = isset($settings[$option_name]['company_name']) ? $settings[$option_name]['company_name'] : 'Unnamed'; $subscription = 0; if (isset($settings[$option_name]['news_subscription']) && !empty($settings[$option_name]['news_subscription'])){ $subscription = $settings[$option_name]['news_subscription'] == LASettingsUtils::YEP ? 1 : 0; } $post = [ 'action' => 'la_activation', 'name' => $name, 'email' => @$settings[$option_name]['company_email'], 'purchase_code' => @$settings[$option_name]['purchase_code'], 'subscription' => $subscription, 'plugin_name' => $this->plugin_slug ]; list($result, $error) = $this->sendRequest2lo($post); if (false !== $result){ $result = json_decode($result); if (isset($result->registration_id)){ $this->setOption('registration_id', $result->registration_id); $this->setOption('registration_date', time()); return true; } else if (isset($result->error)){ throw new Exception(is_string($result->error) ? $result->error : print_r($result->error, true)); } } else { throw new Exception($error); } } if ($activated){ $registration_id = $this->getOption('registration_id'); $name = isset($settings[$option_name]['company_name']) ? $settings[$option_name]['company_name'] : 'Unnamed'; $post = [ 'action' => 'la_activation', 'registration_id' => $registration_id, 'name' => $name, 'email' => @$settings[$option_name]['company_email'], 'purchase_code' => @$settings[$option_name]['purchase_code'], 'subscription' => 1, 'plugin_name' => $this->plugin_slug ]; //subscribe if (isset($_POST['doSubcribe']) && $_POST['doSubcribe'] == 'true'){ $result = $this->sendRequest2lo($post); $result = json_decode($result[0]); if (isset($result->registration_id)){ $this->setOption('registration_id', $result->registration_id); $this->setOption('registration_date', time()); return true; } return false; } //remove registration if (!isset($settings[$option_name]['purchase_code']) || empty($settings[$option_name]['purchase_code'])){ $post['purchase_code'] = ''; $this->sendRequest2lo($post); $this->deleteOption('registration_id'); $this->deleteOption('registration_date'); return false; } } return true; } private function sendRequest2lo($data){ $ch = curl_init( 'https://flow.looks-awesome.com/wp-admin/admin-ajax.php' ); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_TIMEOUT, 60); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, 5000); $error = null; $result = curl_exec( $ch ); if ($result === false){ $error = curl_error($ch); } curl_close( $ch ); return [ $result, $error ]; } private function getStreamFromRequestWithoutErrors(){ $stream = $_POST['stream']; // cleaning if error was saved in database stream model, can be removed in future, now it's needed for affected users if ( isset( $stream['error'] ) ) unset( $stream['error'] ); // casting object return (object)$stream; } private function checkSecurity() { if (FF_USE_WP) { if (!current_user_can('manage_options') || !check_ajax_referer( 'flow_flow_nonce', 'security', false ) ) { die( json_encode( [ 'error' => 'not_allowed' ] ) ); } } } /** * @return array|mixed * @throws Exception */ public function getBoostSources(){ $token = $this->getToken(); if (!empty($token)){ Request::jsonOpts(true); Request::timeout(120); $response = Request::post(FF_BOOST_SERVER . 'flow-flow/ff', [ 'Content-Type: application/x-www-form-urlencoded' ], http_build_query(['action' => 'get_sources', 'token' => $token])); if ($response->code == 200) { foreach ($response->body as &$source){ LADB::prepareSource($source); } return $response->body; } else if ($this->isExpiredToken($response)){ return $this->getBoostSources(); } } return []; } /** * @param array $data * * @return array|mixed|Response * @throws Exception */ private function proxyRequest($data){ $response = []; if (null != ($token = $this->getToken())){ Request::jsonOpts(true); Request::timeout(120); $data['token'] = $token; $response = Request::post(FF_BOOST_SERVER . 'flow-flow/ff', [ 'Content-Type: application/x-www-form-urlencoded' ], http_build_query($data)); if ($this->isExpiredToken($response)){ $response = $this->proxyRequest($data); } } return $response; } /** * @param false $force * * @return array|false|mixed|string|null * @throws Exception */ public function getToken( $force = false ) { $email = $this->getOption('boosts_email'); if (!empty($email)){ $domain = $_SERVER['HTTP_HOST']; $token = $this->getOption('boosts_token'); if ($force || (false == $token)){ Request::jsonOpts(true); Request::timeout(120); $response = Request::post(FF_BOOST_SERVER . 'token', [ 'Content-Type: application/form-data' ], ['domain' => $domain, 'email' => $email]); if ($response->code == 200 && isset($response->body['token']) && is_string($response->body['token'])) { $token = $response->body['token']; $this->setOption('boosts_token', $token); $this->conn()->commit(); } else { return null; } } return $token; } return null; } /** * @param $response * * @return bool * @throws Exception */ private function isExpiredToken( $response ) { if ($response->code == 400 && ((isset($response->body->error) && $response->body->error == 'Provided token is expired.') || (isset($response->body['error']) && $response->body['error'] == 'Provided token is expired.')) ){ $this->deleteOption('boosts_token'); $this->deleteOption('boosts_subscription'); $this->conn()->commit(); return true; } return false; } private function deleteBoostedFeeds() { $conn = $this->conn(); $feeds = $conn->getCol('SELECT `feed_id` FROM ?n WHERE `boosted` = ?s', $this->cache_table_name, LASettingsUtils::YEP); $conn->query('DELETE FROM ?n WHERE `feed_id` IN (?a)', $this->streams_sources_table_name, $feeds); $values = ['system_enabled' => 0, 'boosted' => LASettingsUtils::NOPE]; $conn->query('UPDATE ?n SET ?u WHERE `boosted` = ?s', $this->cache_table_name, $values, LASettingsUtils::YEP); } }
•
Search:
•
Replace:
Function
Edit by line
Download
Information
Rename
Copy
Move
Delete
Chmod
List