<?php

/**
 * One class to rule them all
 *
 * @author mobilova UG (haftungsbeschränkt) <rsspostimporter@feedsapi.com>
 */

class rssPostImporter {

    /**
     * A var to store the options in
     * @var array
     */
    public $options = array();

    /**
     * A var to store the link to the plugin page
     * @var array
     */
    public $page_link = '';

    /**
     * To initialise the admin and cron classes
     *
     * @var object
     */
    private $admin, $cron;

    /**
     * Start
     */

    function __construct() {
        // populate the options first
        $this->load_options();

        // do any upgrade if needed
        $this->upgrade();

        $settings = array();
        $valid_api_key = '';
        if (isset($_POST['feeds_api_key'])) {
            $settings = array(
                'feeds_api_key' => sanitize_key($_POST['feeds_api_key'])
            );

            // check if submitted api key is valid
            $valid_api_key = $this->is_valid_key($settings['feeds_api_key']);
        }

        // determine the API type
        $api_type = $valid_api_key == '' ? 'normal' : 'premium';

        // setup this plugin options page link
        $this->page_link = admin_url(
            'options-general.php?page=rss_pi&version=' . RSS_PI_VERSION .
            '&type=' . $api_type
        );

        // hook translations
        add_action('plugins_loaded', array($this, 'localize'));

        add_filter(
            'plugin_action_links_' . RSS_PI_BASENAME,
            array($this, 'settings_link')
        );
    }

    /**
     * Load options from the db
     */
    public function load_options() {

        $default_settings = array(
            'enable_logging' => false,
            'feeds_api_key' => false,
            'frequency' => 0,
            'post_template' => "{\$content}\nSource: {\$feed_title}",
            'post_status' => 'publish',
            'author_id' => 1,
            'allow_comments' => 'open',
            'block_indexing' => false,
            'nofollow_outbound' => true,
            'keywords' => array(),
            'import_images_locally' => false,
            'disable_thumbnail' => false,
            'cache_deleted' => true,
        );

        $options = get_option('rss_pi_feeds', array());

        // prepare default options when there is no record in the database
        if (!isset($options['feeds'])) {
            $options['feeds'] = array();
        }
        if (!isset($options['settings'])) {
            $options['settings'] = array();
        }
        if (!isset($options['latest_import'])) {
            $options['latest_import'] = '';
        }
        if (!isset($options['imports'])) {
            $options['imports'] = 0;
        }
        if (!isset($options['upgraded'])) {
            $options['upgraded'] = array();
        }

        $options['settings'] = wp_parse_args($options['settings'], $default_settings);

        if (!array_key_exists('imports', $options)) {
            $options['imports'] = 0;
        }

        $this->options = $options;
    }

    /**
     * Upgrade plugin settings
     */
    public function upgrade() {

        global $wpdb;
        $upgraded = FALSE;
        $bail = FALSE;

        // migrate to rss_pi_deleted_posts only items from rss_pi_imported_posts that are actually deleted, discard the others
        // do this in iterations so not to degrade the UX
        if ( ! isset($this->options['upgraded']['deleted_posts']) ) {
            // get meta data for "deleted" and "imported" posts
            $rss_pi_deleted_posts = get_option( 'rss_pi_deleted_posts', array() );
            $rss_pi_imported_posts = get_option( 'rss_pi_imported_posts', array() );
            $rss_pi_imported_posts_migrated = get_option( 'rss_pi_imported_posts_migrated', array() );
            // limit execution time (in seconds)
            $_limit = ( ( defined('DOING_CRON') && DOING_CRON ) ? 20 : ( ( defined('DOING_AJAX') && DOING_AJAX ) ? 10 : 3 ) );
            $_start = microtime(TRUE);
            // iterate through all imported posts' source URLs
            foreach ( $rss_pi_imported_posts as $k => $source_url ) {
                // strip any params from the URL
                //$_source_url = explode('?', $source_url);
                //$_source_url = $_source_url[0];
                // hash the URL for storage
                $source_md5 = md5($source_url);
                // properly format the URL for comparison
                $source_url = esc_url($source_url);
                // skip if we already have "migrated" this item
                if ( in_array( $k, $rss_pi_imported_posts_migrated ) ) {
                    continue;
                }
                // skip if we already have "deleted" metadata for this item
                if ( in_array( $source_md5, $rss_pi_deleted_posts ) ) {
                    continue;
                }
                $rss_pi_imported_posts_migrated[] = $k;
                // check if there is a post with this source URL
                $post_id = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = 'rss_pi_source_url' and meta_value = %s", $source_url ) );
                // when there is no such post (it was deleted?)
                if ( ! $post_id ) {
                    // add this source URL to "deleted" metadata
                    $rss_pi_deleted_posts[] = $source_md5;
                } else {
                    // otherwise update the post metadata to include hashed URL
                    update_post_meta( $post_id, 'rss_pi_source_md5', $source_md5 );
                }
                // remove it from "imported" metadata
                $_curr = microtime(TRUE);
                if ( $_curr - $_start > $_limit ) {
                    // bail out when the "max execution time" limit is exhausted
                    $bail = TRUE;
                    break;
                }
            }
            // shed any duplicates
            $rss_pi_deleted_posts = array_unique($rss_pi_deleted_posts);
            update_option('rss_pi_deleted_posts', $rss_pi_deleted_posts);
            // keep record of migrated items
            update_option('rss_pi_imported_posts_migrated', $rss_pi_imported_posts_migrated);
            // are there still source URLs in the "imported" metadata?
            if ( count($rss_pi_imported_posts_migrated) < count($rss_pi_imported_posts) ) {
            } else {
                // remove the "imported" metadata from database
                delete_option('rss_pi_imported_posts_migrated');
                delete_option('rss_pi_imported_posts');
                // mark this upgrade as completed
                $this->options['upgraded']['deleted_posts'] = TRUE;
                $upgraded = TRUE;
            }
        }
        // check after each upgrade routine
        if ( $bail ) {
            return;
        }

        // if there is something to record as an upgrade
        if ( $upgraded ) {
            update_option('rss_pi_feeds', $this->options);
        }
    }

    /**
     * Load translations
     */
    public function localize() {

        load_plugin_textdomain('rss-post-importer', false, RSS_PI_PATH . 'app/lang/');
    }

    /**
     * Initialise
     */
    public function init() {

        // initialise admin and cron
        $this->cron = new rssPICron();
        $this->cron->init();

        $this->admin = new rssPIAdmin();
        $this->admin->init();

        $this->front = new rssPIFront();
        $this->front->init();
    }

    /**
     * Check if a given API key is valid
     *
     * @param string $key
     * @return boolean
     */
    public function is_valid_key($key) {

        if (empty($key)) {
            return false;
        }

        $url = "https://www.feedsapi.org/fetch.php?key=$key" .
            "&url=" . "http://dummyurl.com";

        $content = file_get_contents($url);
        $content = trim($content);

        if ($content == "A valid key must be supplied") {
            return false;
        }

        if ($content == "Invalid IP/DOMAIN") {
            return false;
        }

        if ($content == "No URL supplied") {
            return false;
        }

        return true;
    }

    /**
     * Adds a settings link
     *
     * @param array $links EXisting links
     * @return type
     */
    public function settings_link($links) {
        $settings_link = array(
            '<a href="' . $this->page_link . '">Settings</a>',
        );
        return array_merge($settings_link, $links);
    }

}
