Plugin Directory

Changeset 1137344


Ignore:
Timestamp:
04/17/2015 04:24:10 PM (11 years ago)
Author:
expresscurate
Message:

new version v2.0.11 with changes:

  • New Setting: Open Original Article Link in a New Window/Tab.
  • Next Content Feed update time now available.
  • Pull the Content Feed manually feature now available.
  • Other miscellaneous bug fixes and improvements.
Location:
expresscurate/trunk
Files:
33 edited

Legend:

Unmodified
Added
Removed
  • expresscurate/trunk/ExpressCurate.php

    r1129694 r1137344  
    55  Plugin URI: http://www.expresscurate.com/products
    66  Description: ExpressCurate plugin is a content curation tool for WordPress. It enables you to create and publish high quality content within minutes.
    7   Version: 2.0.10
     7  Version: 2.0.11
    88  Author: ExpressCurate
    99  Author URI: http://www.expresscurate.com
  • expresscurate/trunk/ExpressCurate_API.php

    r1106118 r1137344  
    44
    55/*
    6  * Returnes source urls of all posts if $post_id is not defined
    7  * @param int $post_id
    8  * @return array
     6  Author: ExpressCurate
     7  Author URI: http://www.expresscurate.com
     8  License: GPLv3 or later
     9  License URI: http://www.gnu.org/licenses/gpl.html
    910 */
    1011
  • expresscurate/trunk/ExpressCurate_Actions.php

    r1129694 r1137344  
    11<?php
     2
     3require_once(sprintf("%s/autoload.php", dirname(__FILE__)));
     4
    25/*
    36  Author: ExpressCurate
     
    69  License URI: http://www.gnu.org/licenses/gpl.html
    710 */
    8 require_once(sprintf("%s/autoload.php", dirname(__FILE__)));
    9 
    1011
    1112class ExpressCurate_Actions
     
    7576        add_action('manage_posts_custom_column', array(&$this, 'curated_column_display'), 10, 2);
    7677        add_filter('manage_edit-post_sortable_columns', array(&$this, 'curated_column_register_sortable'));
    77 
    7878
    7979        add_filter('request', array(&$this, 'curated_column_orderby'));
     
    137137        add_action('wp_ajax_expresscurate_save_sitemap_google_status', array(&$this->sitemap, 'saveSitemapGoogleStatus'));
    138138
    139 
    140139        add_action('wp_ajax_expresscurate_feed_add', array($this->feedManager, 'add_feed'));
    141140        add_action('wp_ajax_expresscurate_feed_delete', array($this->feedManager, 'delete_feed'));
     141        add_action('wp_ajax_expresscurate_show_content_feed_items', array($this->feedManager, 'show_content_feed_items'));
    142142        add_action('wp_ajax_expresscurate_bookmarks_add', array($this->feedManager, 'add_bookmarks'));
    143143        add_action('wp_ajax_expresscurate_bookmark_set', array($this->feedManager, 'set_bookmark'));
     
    200200        register_setting('expresscurate-keywords-group', 'expresscurate_defined_tags');
    201201        register_setting('expresscurate-group', 'expresscurate_curated_text');
     202        register_setting('expresscurate-group', 'expresscurate_curated_link_target');
    202203        register_setting('expresscurate-group', 'expresscurate_featured');
    203204        register_setting('expresscurate-group', 'expresscurate_seo');
     
    376377            return;
    377378        $curated = get_post_meta($post_id, '_is_expresscurate', true);
    378         if ($curated == 1) {
    379             $curated = '<em>' . __('Yes', self::PLUGIN_FOLDER) . '</em>';
    380         } else {
    381             $curated = '<em>' . __('No', self::PLUGIN_FOLDER) . '</em>';
    382         }
     379        //$cloned = get_post_meta($post_id, '_expresscurate_advanced_seo_post_copy', true);
     380        //if($cloned=='on'){
     381           // $curated = '<em>' . __('Cloned', self::PLUGIN_FOLDER) . '</em>';
     382       // }else{
     383            if ($curated == 1) {
     384                $curated = '<em>' . __('Yes', self::PLUGIN_FOLDER) . '</em>';
     385            } else {
     386                $curated = '<em>' . __('No', self::PLUGIN_FOLDER) . '</em>';
     387            }
     388       // }
    383389        echo $curated;
    384390    }
     
    697703            $expresscurate_advanced_seo_nofollow = isset($_POST['expresscurate_advanced_seo_nofollow_value']) ? $_POST['expresscurate_advanced_seo_nofollow_value'] : 'on';
    698704            $expresscurate_advanced_seo_noindex = isset($_POST['expresscurate_advanced_seo_noindex_value']) ? $_POST['expresscurate_advanced_seo_noindex_value'] : 'on';
     705            $expresscurate_advanced_seo_post_copy = isset($_POST['expresscurate_advanced_seo_post_copy_value']) ? $_POST['expresscurate_advanced_seo_post_copy_value'] : 'off';
    699706
    700707            update_post_meta($post_id, '_expresscurate_advanced_seo_title', esc_attr($expresscurate_advanced_seo_title));
     
    702709            update_post_meta($post_id, '_expresscurate_advanced_seo_nofollow', esc_attr($expresscurate_advanced_seo_nofollow));
    703710            update_post_meta($post_id, '_expresscurate_advanced_seo_noindex', esc_attr($expresscurate_advanced_seo_noindex));
     711            update_post_meta($post_id, '_expresscurate_advanced_seo_post_copy', esc_attr($expresscurate_advanced_seo_post_copy));
    704712
    705713            // social part
  • expresscurate/trunk/ExpressCurate_AjaxExportAPI.php

    r1129694 r1137344  
    11<?php
     2
    23require_once(sprintf("%s/autoload.php", dirname(__FILE__)));
    34
     
    3738        $data["smart_publishing"] = get_option('expresscurate_publish', '') == 'on' ? get_option('expresscurate_manually_approve_smart', 'off') : 'off';
    3839        $data["curated_from_prefix"] = get_option("expresscurate_curated_text", 'See full story on');
     40        $data["curated_link_target"] = get_option("expresscurate_curated_link_target", 'on');
    3941        if (current_user_can('edit_posts')) {
    4042            $categories = get_categories(array("hide_empty" => 0));
     
    186188            $domain = parse_url($data['url']);
    187189            $domain = $domain['host'];
    188             $data['content'] .= '<div class="curated_from"><p>' . get_option('expresscurate_curated_text') . ' <a href = "' . $data['url'] . '">' . $domain . '</a><span class="expresscurated" data-curated-url="' . $data['url'] . '">&nbsp;</span></p></div>';
     190            //$data['content'] .= '<div class="curated_from"><p>' . get_option('expresscurate_curated_text') . ' <a href = "' . $data['url'] . '">' . $domain . '</a><span class="expresscurated" data-curated-url="' . $data['url'] . '">&nbsp;</span></p></div>';
    189191            if (isset($data['terms'])) {
    190192                foreach ($data['terms'] as $i => $term) {
  • expresscurate/trunk/ExpressCurate_ContentManager.php

    r1129694 r1137344  
    11<?php
     2
     3require_once(sprintf("%s/autoload.php", dirname(__FILE__)));
    24
    35/*
     
    79  License URI: http://www.gnu.org/licenses/gpl.html
    810 */
    9 require_once(sprintf("%s/autoload.php", dirname(__FILE__)));
    1011
    1112class ExpressCurate_ContentManager {
  • expresscurate/trunk/ExpressCurate_CronManager.php

    r1111122 r1137344  
    11<?php
    22require_once(sprintf("%s/autoload.php", dirname(__FILE__)));
     3
     4/*
     5  Author: ExpressCurate
     6  Author URI: http://www.expresscurate.com
     7  License: GPLv3 or later
     8  License URI: http://www.gnu.org/licenses/gpl.html
     9 */
    310
    411class ExpressCurate_CronManager {
  • expresscurate/trunk/ExpressCurate_Date.php

    r1106118 r1137344  
    11<?php
     2
    23require_once(sprintf("%s/autoload.php", dirname(__FILE__)));
     4
     5/*
     6  Author: ExpressCurate
     7  Author URI: http://www.expresscurate.com
     8  License: GPLv3 or later
     9  License URI: http://www.gnu.org/licenses/gpl.html
     10 */
     11
    312/**
    413 * Class responsible for date formatting
  • expresscurate/trunk/ExpressCurate_Email.php

    r1106118 r1137344  
    11<?php
     2
    23require_once(sprintf("%s/autoload.php", dirname(__FILE__)));
     4
     5/*
     6  Author: ExpressCurate
     7  Author URI: http://www.expresscurate.com
     8  License: GPLv3 or later
     9  License URI: http://www.gnu.org/licenses/gpl.html
     10 */
    311
    412class ExpressCurate_Email
     
    1725        $headers = 'Content-type: text/html; charset=utf-8' . "\r\n";
    1826        foreach ($wpUsers as $user) {
     27            // don't sent alerts to subscribers
     28            if(in_array('subscriber', $user->roles)) {
     29                continue;
     30            }
    1931            @wp_mail($user->user_email, 'ExpressCurate Content Alert', $email, $headers);
    2032        }
  • expresscurate/trunk/ExpressCurate_FeedManager.php

    r1129694 r1137344  
    1111class ExpressCurate_FeedManager
    1212{
    13 
     13    const CONTENT_FEED_MAX_SIZE = 500;
    1414
    1515    private static $instance;
     
    3434        if(!ExpressCurate_HtmlParser::supportsDownload()){
    3535            $result = array("status"=>"You should activate either curl extension or allow_url_fopen setting.");
    36         }else{
     36        } else {
    3737            $url = isset($url) ? $url : $_REQUEST['url'];
    3838            $url = trim($url);
     
    4747                }
    4848
    49                 //$url = expresscurate_normalise_url($url, true);
    50                 $rssUrl = isset($rssUrl) ? $rssUrl : $this->getRssUrl($url);
    51 
    52                 if (!isset($curated_links_rss[$rssUrl])) {
     49                $rssUrl = $this->getRssUrl($url);
     50
     51                if ($rssUrl === null) {
     52                    $result['status'] = 'No RSS feed found at this URL.';
     53                } else if (isset($curated_links_rss[$rssUrl])) {
     54                    $result['status'] = 'URL already exists.';
     55                } else {
    5356                    if (filter_var($rssUrl, FILTER_VALIDATE_URL)) {
    5457                        $result['status'] = 'success';
     58                       
     59                        // retrieve the feed title
     60                        $feedMeta = $this->getFeedMeta($rssUrl);
     61                        $link = $feedMeta['link'];
     62                        $link = empty($link) ? $rssUrl : $link;
     63                       
     64                        // get the number of posts that are curated from this feed
    5565                        $metas = $wpdb->get_results(
    5666                            "SELECT post_id
    57                    FROM $wpdb->postmeta
    58                    WHERE meta_key LIKE  '%_expresscurate_link_%' AND meta_value LIKE '%" . $url . "%' GROUP BY post_id");
    59 
    60 
    61                         $curated_links_rss[$rssUrl]['feed_url'] = $result['feed_url'] = $rssUrl;
    62                         $curated_links_rss[$rssUrl]['post_count'] = $result['post_count'] = count($metas);
    63                         //  var_dump($curated_links_rss);die;
    64                         $curated_links_rss = json_encode($curated_links_rss);
    65                         update_option('expresscurate_links_rss', $curated_links_rss);
    66                     } elseif ($rssUrl === null) {
    67                         $result['status'] = 'No RSS feed found at this URL.';
     67                             FROM $wpdb->postmeta
     68                             WHERE meta_key LIKE  '%_expresscurate_link_%' AND meta_value LIKE '%" . $link . "%' GROUP BY post_id");
     69
     70                        // construct the rss data
     71                        $curated_links_rss[$link]['feed_url'] = $result['feed_url'] = $rssUrl;
     72                        $curated_links_rss[$link]['link'] = $result['link'] = $link;
     73                        $curated_links_rss[$link]['post_count'] = $result['post_count'] = count($metas);
     74                        $curated_links_rss[$link]['feed_title'] = $result['feed_title'] = $feedMeta['title'];
     75                       
     76                        // save
     77                        update_option('expresscurate_links_rss', json_encode($curated_links_rss));
    6878                    } else {
    6979                        $result['status'] = 'Invalid RSS URL.';
    7080                    }
    71                 } else {
    72                     $result['status'] = 'URL already exists.';
    7381                }
    7482            } else {
     
    7987
    8088        die;
     89    }
     90   
     91    private function getFeedMeta($feedURL) {
     92        $loadURL = "http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&q=" . urlencode($feedURL);
     93        $htmlparser = new ExpressCurate_HtmlParser($loadURL);
     94        $res = $htmlparser->download();
     95        $result = json_decode($res, true);
     96       
     97        if(isset($result['responseData']) && isset($result['responseData']['feed'])) {
     98            $meta = array();
     99            $meta['title'] = $result['responseData']['feed']['title'];
     100            $meta['feed']  = $result['responseData']['feed']['feedUrl'];
     101            $meta['link']  = $result['responseData']['feed']['link'];
     102            return $meta;
     103        } else {
     104            return null;
     105        }
    81106    }
    82107
     
    96121            } else {
    97122                unset($curated_links_rss[$data['url']]);
    98                 $curated_links_rss = json_encode($curated_links_rss);
    99                 update_option('expresscurate_links_rss', $curated_links_rss);
     123                update_option('expresscurate_links_rss', json_encode($curated_links_rss));
    100124                $result['status'] = 'success';
    101125            }
     
    127151        if ($curated_links_rss) {
    128152            $curated_links_rss = json_decode($curated_links_rss, true);
     153           
     154            $links = array();
     155            foreach($curated_links_rss as $link => $data) {
     156                $url = $data['feed_url'];
     157                $links[$url] = 1;
     158            }
     159            $curated_links_rss = $links;
    129160        } else {
    130161            $curated_links_rss = array();
     
    133164
    134165        if ($top_sources_rss) {
    135             $top_sources_rss = json_decode($top_sources_rss, true);
    136             $date_after = strtotime($top_sources_rss['date']) . "&";
     166            // check if migrated
     167            $migrated1 = (isset($top_sources_rss['migrated']) && $top_sources_rss['migrated']== 1);
     168            // if not migrated, clean the data up, calculate stats from scratch
     169            $top_sources_rss = $migrated1 ? json_decode($top_sources_rss, true) : array();
     170            $date_after = $migrated1 ? strtotime($top_sources_rss['date']) . "&" : '';
    137171        } else {
    138172            $top_sources_rss = array();
    139173            $top_sources_rss['links'] = array();
    140174        }
     175        $top_sources_rss['migrated'] = 1;
    141176
    142177        $curated_posts_query = new WP_Query("meta_key=_is_expresscurate&meta_value=1&posts_per_page=-1&" . $date_after . "order=DESC");
     
    151186                    if (preg_match('/_expresscurate_link_\d/', $key)) {
    152187                        if ($meta_values[$key][0]) {
    153                             $normalised_url = expresscurate_normalise_url($meta_values[$key][0]);
    154                             $domain = parse_url($normalised_url);
    155                             if (preg_match('/(?P<subdomain>.<domain>[a-z0-9][a-z0-9\-]{1,63}\.[a-z\.]{2,6})$/i', $domain['host'], $regs)) {
    156                                 $curated_links[$i]['link'] = expresscurate_normalise_url($regs['domain']);
    157                             } else {
    158                                 $curated_links[$i]['link'] = $normalised_url;
     188                            // parse the host
     189                            $url = parse_url($meta_values[$key][0]);
     190                            $host = $url['host'];
     191                           
     192                            // get only the main domain
     193                            preg_match('/([a-z0-9\-_]{1,63})\.([a-z]{2,6})$/i', $host, $regs);
     194                            $link = $regs[1] . '.' . $regs[2];
     195                           
     196                            // filter
     197                            if(empty($link) || $link == '.') {
     198                                continue;
    159199                            }
     200                           
     201                            // add
     202                            $curated_links[$i]['host'] = $host;
     203                            $curated_links[$i]['link'] = $link;
    160204                            $curated_links[$i]['post_id'] = get_the_ID();
     205                            $i++;
    161206                        }
    162                         $i++;
    163207                    }
    164208                }
     
    166210        }
    167211        wp_reset_postdata();
    168         if(ExpressCurate_HtmlParser::supportsDownload()){
     212       
     213        $rssLinks = array();
     214       
     215        if(ExpressCurate_HtmlParser::supportsDownload()) {
    169216            foreach ($curated_links as $key => $top_link) {
    170                 $websiteUrl = $top_link['link'];
    171                 $rssUrl = $this->getRssUrl($websiteUrl);
     217                $websiteHost = $top_link['host'];
     218                $website = $top_link['link'];
     219               
     220                if(isset($rssLinks[$websiteHost])) {
     221                    $rssUrl = $rssLinks[$websiteHost];
     222                } else {
     223                    $rssUrl = $this->getRssUrl($websiteHost);
     224                    $rssLinks[$websiteHost] = $rssUrl;
     225                }
     226               
    172227                if ($rssUrl && isset($curated_links_rss[$rssUrl])) {
    173228                    $feed_status = 'rssStatusYes';
     
    179234                    }
    180235                }
    181                 $top_sources_rss['links'][$websiteUrl] = array(
     236               
     237                $top_sources_rss['links'][$website] = array(
    182238                    'post_ids' => array($top_link['post_id']),
    183239                    'feed_options' => array(
     
    186242                        'type' => 'feed')
    187243                );
    188                 $top_sources_rss['links'][$websiteUrl]['post_ids'] = array_unique($top_sources_rss['links'][$websiteUrl]['post_ids']);
    189                 $top_sources_rss['links'][$websiteUrl]['post_count'] = count($top_sources_rss['links'][$websiteUrl]['post_ids']);
     244                $top_sources_rss['links'][$website]['post_ids'] = array_unique($top_sources_rss['links'][$website]['post_ids']);
     245                $top_sources_rss['links'][$website]['post_count'] = count($top_sources_rss['links'][$website]['post_ids']);
    190246            }
    191247
     
    211267    public function get_rss_list()
    212268    {
     269        global $wpdb;
     270       
    213271        $curated_links_rss = get_option('expresscurate_links_rss', '');
    214272        if ($curated_links_rss) {
    215273            $curated_links_rss = json_decode($curated_links_rss, true);
     274           
     275            $save = false;
     276            foreach($curated_links_rss as $rss => $data) {
     277                if(isset($data['feed_title']) && strlen(trim($data['feed_title'])) > 0) {
     278                    continue;
     279                }
     280               
     281                // correct the url and get the meta data
     282                $rssUrl = $this->getRssUrl($rss);
     283                $feedMeta = $this->getFeedMeta($rssUrl);
     284                $link = $feedMeta['link'];
     285                $link = empty($link) ? $rssUrl : $link;
     286               
     287                $data = array();
     288                $data['feed_title'] = $feedMeta['title'];
     289                $data['feed_url'] = $rssUrl;
     290                $data['link'] = $link;
     291               
     292                // remove the old row and add the new one
     293                unset($curated_links_rss[$rss]);
     294                $curated_links_rss[$link] = $data;
     295               
     296                // make sure to save in the end
     297                $save = true;
     298            }
     299           
     300            // update the post count
     301            foreach($curated_links_rss as $link => $data) {
     302                // get the number of posts that are curated from this feed
     303                $posts = $wpdb->get_results(
     304                            "SELECT post_id
     305                             FROM $wpdb->postmeta
     306                             WHERE meta_key LIKE  '%_expresscurate_link_%' AND meta_value LIKE '%" . $link . "%' GROUP BY post_id");
     307               
     308                $curated_links_rss[$link]['post_count'] = count($posts);
     309            }
     310           
     311            // save
     312            update_option('expresscurate_links_rss', json_encode($curated_links_rss));
    216313        } else {
    217314            $curated_links_rss = array();
    218315        }
     316       
     317        unset($curated_links_rss['']);
    219318        return $curated_links_rss;
    220319    }
     
    253352
    254353        $lookup_url = "http://ajax.googleapis.com/ajax/services/feed/lookup?v=1.0&q=" . urlencode($url);
    255         /*$options = array('http' => array('user_agent' => USER_AGENT,'request_fulluri '=>TRUE));
    256         if(preg_match("/(^https:\/\/)/i", $url)!=false){
    257             $options['ssl']=array('verify_peer'=> false,"verify_peer_name"=>false);
    258         }
    259         $context = stream_context_create($options);
    260         $res = file_get_contents($lookup_url,false,$context);*/
    261354        $htmlparser = new ExpressCurate_HtmlParser($lookup_url);
    262355        $res = $htmlparser->download();
     
    269362        return false;
    270363    }
     364   
     365   
    271366
    272367    public function get_feed_content()
    273368    {
    274         $feed_array = array();
     369        // read the existing feed to modify below
     370        $feedContent = get_option('expresscurate_feed_content');
     371        if (empty($feedContent)) {
     372            $feed_array = array();
     373        } else {
     374            $feedContent = json_decode($feedContent, true);
     375            $feed_array = $feedContent['content'];
     376        }
     377
     378        // blabla
    275379        $data = $_REQUEST;
    276         $date = urldecode($date["date"]);
     380        $pull_feed_interval = (get_option('expresscurate_pull_hours_interval')) ? get_option('expresscurate_pull_hours_interval') : 1;
     381        $date = ($data["date"]) ? urldecode($data["date"]) : date('Y-m-d H:i:s', strtotime("-" . $pull_feed_interval . " hour"));
    277382        $curated_links_rss = get_option('expresscurate_links_rss', '');
    278383        if ($curated_links_rss) {
     384            // get the deleted suggestions
     385            $deleted_urls = array();
     386            $feed_content_deleted = get_option('expresscurate_feed_content_deleted', '');
     387            if (empty($feed_content_deleted)) {
     388                $feed_content_deleted = array();
     389            } else {
     390                $feed_content_deleted = json_decode($feed_content_deleted, true);
     391            }
     392            if (is_array($feed_content_deleted)) {
     393                foreach ($feed_content_deleted as $deletet_item) {
     394                    $deleted_urls[] = $deletet_item;
     395                }
     396            }
     397           
     398            // go over the feeds and try to pull
    279399            $curated_links_rss = json_decode($curated_links_rss, true);
    280             $deleted_urls = array();
    281             if (!isset($date)) {
    282                 $feed_content_deleted = get_option('expresscurate_feed_content_deleted', '');
    283                 if ($feed_content_deleted) {
    284                     $feed_content_deleted = json_decode($feed_content_deleted, true);
    285                 }
    286                 if (is_array($feed_content_deleted)) {
    287                     foreach ($feed_content_deleted as $deletet_item) {
    288                         $deleted_urls[] = $deletet_item['link'];
    289                     }
    290                 }
    291             }
    292400            if (count($curated_links_rss)) {
    293401                foreach ($curated_links_rss as $url => $feed_url) {
     402                    // pull content
    294403                    $lookup_url = "http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&q=" . urlencode($feed_url['feed_url']);
    295                     //$result= json_decode(file_get_contents($lookup_url), true);
    296404                    $htmlparser = new ExpressCurate_HtmlParser($lookup_url);
    297405                    $res = $htmlparser->download();
     406                    // decode and collect
    298407                    $result = json_decode($res, true);
    299408                    $this->collect_feed($result, $deleted_urls, $feed_array, 'feed', $date);
     
    301410            }
    302411
    303             @uasort($feed_array, array($this, "feedSortByDate"));
    304 
     412            // check if the feed is empty and sort
     413            if(!empty($feed_array)) {
     414                @uasort($feed_array, array($this, "feedSortByDate"));
     415               
     416                // check if the feed is full or not
     417                if(count($feed_array) > self::CONTENT_FEED_MAX_SIZE) {
     418                    // remove the last elements
     419                    $feed_array = array_slice($feed_array,0,self::CONTENT_FEED_MAX_SIZE);
     420                    // TODO implement
     421
     422                }
     423            }
     424           
     425            // save the latest feed
    305426            $feed_content = json_encode(array('date' => date('Y-m-d H:i:s'), 'content' => $feed_array));
    306             update_option('expresscurate_feed_content', $feed_content);
     427           // update_option('expresscurate_feed_content', $feed_content);
    307428            return $feed_content;
    308429        }
    309 
    310 
    311     }
    312 
    313     public function manual_pull_feed(){
    314         $feeds = json_decode($this->get_feed_content(),true);
    315         if(!empty($feeds['content'])){
    316             wp_clear_scheduled_hook('expresscurate_pull_feeds');
    317             $pull_feed_interval = (get_option('expresscurate_pull_hours_interval'))?get_option('expresscurate_pull_hours_interval'):1;
    318             wp_schedule_event(strtotime("+".$pull_feed_interval." hour"), 'hourly', 'expresscurate_pull_feeds');
    319             $feeds["minutes_to_next_pull"]= human_time_diff(wp_next_scheduled('expresscurate_pull_feeds'),time());
    320         }
    321         echo json_encode($feeds);
    322         die;
    323     }
    324 
    325     public function filter_feeds_by_date(){
    326         $data = $_REQUEST;
    327         $feed_content = json_decode(get_option('expresscurate_feed_content', ''), true);
    328         $filtered_feeds = array();
    329         if(isset($data['date']) && !empty($feed_content['content'])){
    330             foreach($feed_content['content'] as $link => $feed){
    331                 if((strtotime($feed['date']) - $data['date']) >= 0){
    332                     $filtered_feeds[$link] = $feed;
    333                 }
    334             }
    335         }
    336         return $filtered_feeds;
    337     }
    338 
    339     public function send_content_alert()
    340     {
    341 
    342         if (get_option('expresscurate_enable_content_alert') == 'on') {
    343             $feed_content = json_decode(get_option('expresscurate_feed_content', ''), true);
    344 
    345             if ($this->date_diff(date('Y-m-d H:i:s'), get_option('expresscurate_content_alert_lastDate', true)) > get_option('expresscurate_content_alert_frequency', true)
    346                 && isset($feed_content['content']) && $feed_content['content'] !== NULL
    347             ) {
    348 
    349                 $emailStories = array();
    350                 foreach ($feed_content['content'] as $link => $story) {
    351                     if (isset($story['keywords'])) {
    352                         if ($this->date_diff(get_option('expresscurate_content_alert_lastDate', true), $story['date'], false) < 0) {
    353                             $emailStories[$link] = $story;
    354                         }
    355                     }
    356                 }
    357                 if (!empty($emailStories)) {
    358                     $expressCurateEmail = new ExpressCurate_Email();
    359                     $expressCurateEmail->sendContentAlertEmail($emailStories);
    360 
    361                 }
    362 
    363             }
    364         }
    365 
    366     }
    367 
    368     public function collect_feed($result, $deleted_urls, &$feed_array, $type = 'feed', $date = false)
     430    }
     431   
     432    private function collect_feed($result, $deleted_urls, &$feed_array, $type = 'feed', $date = false)
    369433    {
    370434        $feeds = array();
     
    377441        }
    378442        foreach ($feeds as $story) {
    379             if ((isset($story['link']) && !in_array($story['link'], $deleted_urls)) || (isset($story['address']) && !in_array($story['address'], $deleted_urls))) {
    380                 $link = isset($story['link']) ? $story['link'] : $story['address'];
     443            // get the post url
     444            $link = isset($story['link']) ? $story['link'] : $story['address'];
     445            if(empty($link) || isset($deleted_urls[$link])) {
     446                continue;
     447            }
     448           
     449            // parse the post url
     450            $parsedLink = parse_url($link);
     451           
     452            // google alerts support
     453            // check for google redirect urls and pick up the original post link
     454            $protocol = $parsedLink['scheme'];
     455            if (strpos($protocol . "://www.google.com/url", $url) == 0) {
     456                $url_query = explode("&", $query);
     457                foreach ($url_query as $param) {
     458                    if (strpos($param, 'url=') === 0) {
     459                        $link = str_replace("url=", "", $param);
     460                        $link = urldecode($link);
     461                        $parsedLink = parse_url($link);
     462                        break;
     463                    }
     464                }
     465            }
     466           
     467            // check if this link is already in the feed
     468            if(isset($feed_array[$link])) {
     469                continue;
     470            }
     471           
    381472                $domain = parse_url($link);
    382                 if (preg_match('/(?P<subdomain>.<domain>[a-z0-9][a-z0-9\-]{1,63}\.[a-z\.]{2,6})$/i', $domain['host'], $regs)) {
     473                if (preg_match('/(?P<subdomain>.<domain>[a-z0-9][a-z0-9\-]{1,63}\.[a-z\.]{2,6})$/i', $parsedLink['host'], $regs)) {
    383474                    $domain = $regs['domain'];
    384475                } else {
    385476                    $domain = $domain['host'];
    386477                }
     478               
     479                // download and analyze
    387480                $html_parser = new ExpressCurate_HtmlParser($link);
     481                $link = $html_parser->getRealURL();
     482                // check if the final page (initial or redirected address) is already in feed
     483                if(isset($feed_array[$link])) {
     484                    continue;
     485                }
     486               
    388487                $keywords = $html_parser->analyzeKeywords();
    389488                $media = $html_parser->containsMedia();
     489               
    390490                $publishDate = isset($story['publishedDate']) ? $story['publishedDate'] : $story['date'];
    391491                $expressCurateDate = new ExpressCurate_Date();
    392492                $publishDate = $expressCurateDate->dateWithTimeUtc(strtotime($publishDate));
     493               
    393494                $story_array = array(
    394495                    'title' => $story['title'],
     
    416517                    $feed_array[$link] = $story_array;
    417518                }
    418 
    419             }
    420         }
     519        }
     520    }
     521
     522    public function manual_pull_feed() {
     523        // get feed data
     524        $feeds = json_decode($this->get_feed_content(), true);
     525       
     526        // reschedule the cronjob
     527        if(!empty($feeds['content'])) {
     528            wp_clear_scheduled_hook('expresscurate_pull_feeds');
     529            $pull_feed_interval = (get_option('expresscurate_pull_hours_interval')) ? get_option('expresscurate_pull_hours_interval') : 1;
     530            wp_schedule_event(strtotime("+" . $pull_feed_interval . " hour"), 'hourly', 'expresscurate_pull_feeds');
     531            $feeds["minutes_to_next_pull"] = human_time_diff(wp_next_scheduled('expresscurate_pull_feeds'), time());
     532        }
     533       
     534        // return
     535        echo json_encode($feeds);
     536        die;
     537    }
     538
     539    public function show_content_feed_items()
     540    {
     541        include(sprintf("%s/templates/feed_list.php", dirname(__FILE__)));
     542        die;
     543    }
     544   
     545    public function filter_feeds_by_date() {
     546        $data = $_REQUEST;
     547        $feed_content = json_decode(get_option('expresscurate_feed_content', ''), true);
     548        $filtered_feeds = array();
     549        if(isset($data['date']) && !empty($feed_content['content'])){
     550            foreach($feed_content['content'] as $link => $feed){
     551                if((strtotime($feed['date']) - $data['date']) >= 0){
     552                    $filtered_feeds[$link] = $feed;
     553                }
     554            }
     555        }
     556        return $filtered_feeds;
     557    }
     558
     559    public function send_content_alert()
     560    {
     561
     562        if (get_option('expresscurate_enable_content_alert') == 'on') {
     563            $feed_content = json_decode(get_option('expresscurate_feed_content', ''), true);
     564
     565            if ($this->date_diff(date('Y-m-d H:i:s'), get_option('expresscurate_content_alert_lastDate', true)) > get_option('expresscurate_content_alert_frequency', true)
     566                && isset($feed_content['content']) && $feed_content['content'] !== NULL
     567            ) {
     568
     569                $emailStories = array();
     570                foreach ($feed_content['content'] as $link => $story) {
     571                    if (!empty($story['keywords'])) {
     572                        if ($this->date_diff(get_option('expresscurate_content_alert_lastDate', true), $story['date'], false) < 0) {
     573                            $emailStories[$link] = $story;
     574                        }
     575                    }
     576                }
     577                if (!empty($emailStories)) {
     578                    $expressCurateEmail = new ExpressCurate_Email();
     579                    $expressCurateEmail->sendContentAlertEmail($emailStories);
     580
     581                }
     582
     583            }
     584        }
     585
    421586    }
    422587
  • expresscurate/trunk/ExpressCurate_GoogleAuth.php

    r1106118 r1137344  
    11<?php
     2
    23require_once(sprintf("%s/autoload.php", dirname(__FILE__)));
     4
     5/*
     6  Author: ExpressCurate
     7  Author URI: http://www.expresscurate.com
     8  License: GPLv3 or later
     9  License URI: http://www.gnu.org/licenses/gpl.html
     10 */
    311
    412class ExpressCurate_GoogleAuth
  • expresscurate/trunk/ExpressCurate_HtmlParser.php

    r1129694 r1137344  
    11<?php
     2
    23require_once(sprintf("%s/autoload.php", dirname(__FILE__)));
    34
     
    910 */
    1011
    11 class ExpressCurate_HtmlParser {
    12   // resource details
    13   private $url;
    14   private $domain;
    15   private $fragment;
    16   private $protocol;
    17   private $path;
    18   private $raw;
    19   private $referer;
    20  
    21   // may be an html or a raw data (used for images, etc)
    22   private $data = null;
    23   private $dataHTTPStatus = null;
    24   private $dataUTF8 = null;
    25  
    26   // html dom details
    27   private $dom = null;
    28   private $article = null;
    29   private $xpath = null;
    30  
    31   // article details
    32   private $title = null;
    33   private $keywords = null;
    34   private $description = null;
    35  
    36   // asynch download settings
    37   private $asynchHandle = null;
    38   private static $ASYNC_SUPPORT_CURL_MULTI_HANDLER = null;
    39   private static $REQUEST_TIMEOUT = 10;
    40 
    41   public static function supportsAsynch() {
     12class ExpressCurate_HtmlParser
     13{
     14    // resource details
     15    private $url;
     16    private $domain;
     17    private $fragment;
     18    private $protocol;
     19    private $path;
     20    private $raw;
     21    private $referer;
     22
     23    // may be an html or a raw data (used for images, etc)
     24    private $data = null;
     25    private $dataHTTPStatus = null;
     26    private $dataUTF8 = null;
     27
     28    // html dom details
     29    private $dom = null;
     30    private $article = null;
     31    private $xpath = null;
     32
     33    // article details
     34    private $title = null;
     35    private $keywords = null;
     36    private $description = null;
     37
     38    // asynch download settings
     39    private $asynchHandle = null;
     40    private static $ASYNC_SUPPORT_CURL_MULTI_HANDLER = null;
     41    private static $REQUEST_TIMEOUT = 10;
     42
     43    public static function supportsAsynch()
     44    {
    4245        return is_callable('curl_init');
    43   }
    44  
    45   public static function supportsDownload() {
    46       return is_callable('curl_init') || preg_match('/1|yes|on|true/i', ini_get('allow_url_fopen'));
    47   }
    48 
    49   public function __construct($url, $raw = false, $referer = null) {
    50     if($url) {
    51         $parsedURL = parse_url($url);
    52        
    53         $path = $parsedURL['path'];
    54         $lastof = strrpos($path, "/");
    55         $path = substr($path, 0, $lastof);
    56        
    57         $this->domain = 'http://' . $parsedURL['host'];
    58         $this->path = 'http://' . $parsedURL['host'] . "/" . $path . "/";
    59         $this->fragment = $parsedURL['fragment'];
    60         $this->protocol = $parsedURL['scheme'];
    61         $query = $parsedURL['query'];
    62        
    63         // google redirection fix
    64         if(strpos($this->protocol . "://www.google.com/url", $url)==0) {
    65             $url_query = explode("&", $query);
    66             foreach($url_query as $param) {
    67                 if(strpos($param, 'url=') === 0) {
    68                     $url = str_replace("url=", "", $param);
    69                     $url = urldecode($url);
    70                     break;
    71                 }
    72             }
    73          }
    74          $this->url = html_entity_decode($url);
    75     }
    76     $this->raw = $raw;
    77     $this->referer = $referer;
    78   }
    79  
    80   public function getFile() {
    81       if(self::supportsAsynch()) {
    82           $this->downloadAsynch();
    83           self::ensureAsynchData();
    84           return $this->getAsynchData();
    85       } else {
    86           return $this->download();
    87       }
    88   }
    89  
    90   public function getHTTPStatus() {
    91       return $this->dataHTTPStatus;
    92   }
    93  
    94   public function isHTTPStatusOK() {
    95       if ((is_array($this->dataHTTPStatus) && ($this->dataHTTPStatus[0] == "HTTP/1.1 200 OK" || strpos($this->dataHTTPStatus[0], '200'))) || $this->dataHTTPStatus == "HTTP/1.1 200 OK" || $this->dataHTTPStatus == 200 || $this->dataHTTPStatus == 'HTTP\/1.1 200 OK') {
    96           return true;
    97       }
    98       return false;
    99   }
    100  
    101   public function getHTTPStatusCode() {
    102       if($this->isHTTPStatusOK()) {
    103           return 200;
    104       }
    105      
    106       if ((is_array($this->dataHTTPStatus) && ($this->dataHTTPStatus[0] == "HTTP/1.1 403 Forbidden" || strpos($this->dataHTTPStatus[0], '403'))) || $this->dataHTTPStatus == "HTTP/1.1 403 Forbidden" || $this->dataHTTPStatus == 403) {
    107           return 403;
    108       }
    109      
    110       return $http_response_header[0];
    111   }
    112  
    113   public function downloadAsynch() {
    114       if($this->data != null) {
    115           return;
    116       }
    117      
    118       if(self::supportsAsynch() == false) {
    119           return $this->download();
    120       }
    121      
    122       if(self::$ASYNC_SUPPORT_CURL_MULTI_HANDLER == null) {
    123           $mh = curl_multi_init();
    124           set_time_limit(0);
    125          
    126           self::$ASYNC_SUPPORT_CURL_MULTI_HANDLER = $mh;
    127       }
    128      
    129       // setup the single curl
    130       $ch = $this->createCURL($this->url);
    131      
    132       // add the single handle to the multi handle
    133       curl_multi_add_handle(self::$ASYNC_SUPPORT_CURL_MULTI_HANDLER, $ch);
    134       // start the download
    135       curl_multi_exec(self::$ASYNC_SUPPORT_CURL_MULTI_HANDLER, $running);
    136      
    137       // keep the handle for later
    138       $this->asynchHandle = $ch;
    139   }
    140  
    141   private function createCURL($url) {
    142       $ch = curl_init();
    143       curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    144       curl_setopt($ch, CURLOPT_URL, $url);
    145       curl_setopt($ch, CURLOPT_USERAGENT, ExpressCurate_Actions::USER_AGENT);
    146       if($this->referer) {
    147           curl_setopt($ch, CURLOPT_REFERER, $this->referer);
    148       }
    149       curl_setopt($ch, CURLOPT_HTTPHEADER, array("Accept: application/xhtml+xml, application/xml", "Accept-Charset: utf-8"));
    150       curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    151       curl_setopt($ch, CURLOPT_TIMEOUT, self::$REQUEST_TIMEOUT);
    152       curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    153       curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
    154       curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
    155   }
    156  
    157   private static function ensureAsynchData() {
    158       do {
    159           curl_multi_exec(self::$ASYNC_SUPPORT_CURL_MULTI_HANDLER, $running);
    160       } while($running > 0);
    161   }
    162  
    163   private function getAsyncData() {
    164       $content = curl_multi_getcontent($this->asynchHandle);
    165       $this->dataHTTPStatus = curl_getinfo($this->asynchHandle, CURLINFO_HTTP_CODE);
    166       $contentType = curl_getinfo($this->asynchHandle, CURLINFO_CONTENT_TYPE);
    167      
    168       curl_multi_remove_handle(self::$ASYNC_SUPPORT_CURL_MULTI_HANDLER, $this->asynchHandle);
    169      
    170       if(!$this->raw) {
    171           $content = self::sanitizeContent($content);
    172      
    173           if($contentType) {
    174               list($charset, $encoding) = explode("=", $contentType);
    175               $encoding = strtoupper(trim($encoding));
    176                              
    177               $supportedEncoding = array_search($encoding, mb_list_encodings()) !== false;
    178                              
    179               if(!$supportedEncoding) {
    180                   $encoding = mb_detect_encoding($content);
    181               }
    182              
    183               $content = mb_convert_encoding($content, 'UTF-8', $encoding); 
    184               $content = mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8');
    185           }
    186       }
    187      
    188       $this->data = $content;
    189      
    190       return $this->data;
    191   }
    192  
    193   public function download() {
    194       if($this->data != null) {
    195           return;
    196       }
    197      
     46    }
     47
     48    public static function supportsDownload()
     49    {
     50        return is_callable('curl_init') || preg_match('/1|yes|on|true/i', ini_get('allow_url_fopen'));
     51    }
     52
     53    public function __construct($url, $raw = false, $referer = null)
     54    {
     55        if ($url) {
     56            $parsedURL = parse_url($url);
     57
     58            $path = $parsedURL['path'];
     59            $lastof = strrpos($path, "/");
     60            $path = substr($path, 0, $lastof);
     61
     62            $this->domain = 'http://' . $parsedURL['host'];
     63            $this->path = 'http://' . $parsedURL['host'] . "/" . $path . "/";
     64            $this->fragment = $parsedURL['fragment'];
     65            $this->protocol = $parsedURL['scheme'];
     66            $query = $parsedURL['query'];
     67
     68            // google redirection fix
     69            if (strpos($this->protocol . "://www.google.com/url", $url) == 0) {
     70                $url_query = explode("&", $query);
     71                foreach ($url_query as $param) {
     72                    if (strpos($param, 'url=') === 0) {
     73                        $url = str_replace("url=", "", $param);
     74                        $url = urldecode($url);
     75                        break;
     76                    }
     77                }
     78            }
     79            $this->url = html_entity_decode($url);
     80        }
     81        $this->raw = $raw;
     82        $this->referer = $referer;
     83    }
     84
     85    public function getFile()
     86    {
     87        if (self::supportsAsynch()) {
     88            $this->downloadAsynch();
     89            self::ensureAsynchData();
     90            return $this->getAsynchData();
     91        } else {
     92            return $this->download();
     93        }
     94    }
     95
     96    public function getHTTPStatus()
     97    {
     98        return $this->dataHTTPStatus;
     99    }
     100
     101    public function isHTTPStatusOK()
     102    {
     103        if ((is_array($this->dataHTTPStatus) && ($this->dataHTTPStatus[0] == "HTTP/1.1 200 OK" || strpos($this->dataHTTPStatus[0], '200'))) || $this->dataHTTPStatus == "HTTP/1.1 200 OK" || $this->dataHTTPStatus == 200 || $this->dataHTTPStatus == 'HTTP\/1.1 200 OK') {
     104            return true;
     105        }
     106        if (is_array($this->dataHTTPStatus) && ($this->dataHTTPStatus[0] == "HTTP/1.1 301 Moved Permantenly" || strpos($this->dataHTTPStatus[0], '301')) || ($this->dataHTTPStatus[0] == "HTTP/1.1 302 Found" || strpos($this->dataHTTPStatus[0], '302')) || ($this->dataHTTPStatus[0] == "HTTP/1.1 303 See Other" || strpos($this->dataHTTPStatus[0], '303')) || ($this->dataHTTPStatus[0] == "HTTP/1.1 307 Temporary Redirect" || strpos($this->dataHTTPStatus[0], '307')) || ($this->dataHTTPStatus[0] == "HTTP/1.1 308 Permanent Redirect" || strpos($this->dataHTTPStatus[0], '308'))){
     107            return true;
     108        }
     109        return false;
     110    }
     111
     112    public function getHTTPStatusCode()
     113    {
     114        if ($this->isHTTPStatusOK()) {
     115            return 200;
     116        }
     117
     118        if ((is_array($this->dataHTTPStatus) && ($this->dataHTTPStatus[0] == "HTTP/1.1 403 Forbidden" || strpos($this->dataHTTPStatus[0], '403'))) || $this->dataHTTPStatus == "HTTP/1.1 403 Forbidden" || $this->dataHTTPStatus == 403) {
     119            return 403;
     120        }
     121
     122        return $http_response_header[0];
     123    }
     124
     125    public function downloadAsynch()
     126    {
     127        if ($this->data != null) {
     128            return;
     129        }
     130
     131        if (self::supportsAsynch() == false) {
     132            return $this->download();
     133        }
     134
     135        if (self::$ASYNC_SUPPORT_CURL_MULTI_HANDLER == null) {
     136            $mh = curl_multi_init();
     137            set_time_limit(0);
     138
     139            self::$ASYNC_SUPPORT_CURL_MULTI_HANDLER = $mh;
     140        }
     141
     142        // setup the single curl
     143        $ch = $this->createCURL($this->url);
     144
     145        // add the single handle to the multi handle
     146        curl_multi_add_handle(self::$ASYNC_SUPPORT_CURL_MULTI_HANDLER, $ch);
     147        // start the download
     148        curl_multi_exec(self::$ASYNC_SUPPORT_CURL_MULTI_HANDLER, $running);
     149
     150        // keep the handle for later
     151        $this->asynchHandle = $ch;
     152    }
     153
     154    private function createCURL($url)
     155    {
     156        $ch = curl_init();
     157        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
     158        curl_setopt($ch, CURLOPT_URL, $url);
     159        curl_setopt($ch, CURLOPT_USERAGENT, ExpressCurate_Actions::USER_AGENT);
     160        if ($this->referer) {
     161            curl_setopt($ch, CURLOPT_REFERER, $this->referer);
     162        }
     163        curl_setopt($ch, CURLOPT_HTTPHEADER, array("Accept: application/xhtml+xml, application/xml", "Accept-Charset: utf-8"));
     164        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
     165        curl_setopt($ch, CURLOPT_TIMEOUT, self::$REQUEST_TIMEOUT);
     166        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
     167        curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
     168        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
     169    }
     170
     171    private static function ensureAsynchData()
     172    {
     173        do {
     174            curl_multi_exec(self::$ASYNC_SUPPORT_CURL_MULTI_HANDLER, $running);
     175        } while ($running > 0);
     176    }
     177
     178    private function getAsyncData()
     179    {
     180        $content = curl_multi_getcontent($this->asynchHandle);
     181        $this->dataHTTPStatus = curl_getinfo($this->asynchHandle, CURLINFO_HTTP_CODE);
     182        $contentType = curl_getinfo($this->asynchHandle, CURLINFO_CONTENT_TYPE);
     183
     184        curl_multi_remove_handle(self::$ASYNC_SUPPORT_CURL_MULTI_HANDLER, $this->asynchHandle);
     185
     186        if (!$this->raw) {
     187            $content = self::sanitizeContent($content);
     188
     189            if ($contentType) {
     190                list($charset, $encoding) = explode("=", $contentType);
     191                $encoding = strtoupper(trim($encoding));
     192
     193                $supportedEncoding = array_search($encoding, mb_list_encodings()) !== false;
     194
     195                if (!$supportedEncoding) {
     196                    $encoding = mb_detect_encoding($content);
     197                }
     198
     199                $content = mb_convert_encoding($content, 'UTF-8', $encoding);
     200                $content = mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8');
     201            }
     202        }
     203
     204        $this->data = $content;
     205
     206        return $this->data;
     207    }
     208
     209
     210    public function getRealURL(){
     211        foreach(get_headers($this->url) as $header) {
     212            if (strpos($header, "Location:") === 0) {
     213                $this->url = trim(substr($header, 9));
     214            }
     215        }
     216        return $this->url;
     217    }
     218
     219    public function download()
     220    {
     221        if ($this->data != null) {
     222            return;
     223        }
     224
    198225//      if (self::supportsAsynch()) {
    199226//          // setup the single curl
     
    204231//          curl_close($ch);
    205232//      } else {
    206           $header = '';
    207           if($this->referer) {
    208               $header .= 'Referer: ' . $this->referer . '\r\n';
    209           }
    210           if(!$this->raw) {
    211               $header .= 'Accept: application/xhtml+xml, application/xml, text/html\r\n';
    212               $header .= 'Accept-Charset: UTF-8';
    213           }
    214           $options = array('http' => array(
    215                 'user_agent' => ExpressCurate_Actions::USER_AGENT,
    216                 'follow_location' => 1,
    217                 'max_redirects' => 5,
    218                 'request_fulluri '=> TRUE,
    219                 'timeout' => self::$REQUEST_TIMEOUT,
    220                 'header' => $header));
    221           if(strpos($this->url, 'https://') === 0) {
    222              $options['ssl'] = array('verify_peer' => false, 'verify_peer_name' => false);
    223           }
    224           $context = stream_context_create($options);
    225           $content = file_get_contents($this->url, false, $context);
    226           // $http_response_header gets loaded once file get contents is called, php native stuff
    227           $this->dataHTTPStatus = $http_response_header;
    228          
    229           // try to resolve the content encoding if text/html content
    230           if(!$this->raw) {
    231               if(!empty($http_response_header)) {
    232                   foreach ($http_response_header as $header) {
    233                       if (substr(strtolower($header), 0, 13) == "content-type:") {
    234                           $contentTypeData = explode(";", $header);
    235                           if (count($contentTypeData) == 2) {
    236                               list($contentTypeKey, $contentType) = $contentTypeData;
    237                           }
    238                       }
    239                   }
    240               }
    241           }
     233        set_time_limit(0);
     234        $header = '';
     235        if ($this->referer) {
     236            $header .= 'Referer: ' . $this->referer . '\r\n';
     237        }
     238        if (!$this->raw) {
     239            $header .= 'Accept: application/xhtml+xml, application/xml, text/html\r\n';
     240            $header .= 'Accept-Charset: UTF-8';
     241        }
     242        $options = array('http' => array(
     243            'user_agent' => ExpressCurate_Actions::USER_AGENT,
     244            'follow_location' => 1,
     245            'max_redirects' => 5,
     246            'request_fulluri ' => TRUE,
     247            'timeout' => self::$REQUEST_TIMEOUT,
     248            'header' => $header));
     249        if (strpos($this->url, 'https://') === 0) {
     250            $options['ssl'] = array('verify_peer' => false, 'verify_peer_name' => false);
     251        }
     252        $context = stream_context_create($options);
     253        $content = @file_get_contents($this->url, false, $context);
     254
     255        // $http_response_header gets loaded once file get contents is called, php native stuff
     256        $this->dataHTTPStatus = $http_response_header;
     257
     258        // try to resolve the content encoding if text/html content
     259        if (!$this->raw) {
     260            if (!empty($http_response_header)) {
     261                foreach ($http_response_header as $header) {
     262                    if (substr(strtolower($header), 0, 13) == "content-type:") {
     263                        $contentTypeData = explode(";", $header);
     264                        if (count($contentTypeData) == 2) {
     265                            list($contentTypeKey, $contentType) = $contentTypeData;
     266                        }
     267                    }
     268                }
     269            }
     270        }
    242271//      }
    243272
    244       // make sure if there is a response at all
    245       if($this->isHTTPStatusOK() === false) {
    246           // terminate
    247           $this->data = null;
    248           return null;
    249       }
    250      
    251       // there is data with OK code, process if required
    252       if(!$this->raw) {
    253           $content = self::sanitizeContent($content);
    254      
    255           if($contentType) {
    256               list($charset, $encoding) = explode("=", $contentType);
    257               $encoding = strtoupper(trim($encoding));
    258                              
    259               $supportedEncoding = array_search($encoding, mb_list_encodings()) !== false;
    260                              
    261               if(!$supportedEncoding) {
    262                   $encoding = mb_detect_encoding($content);
    263               }
    264              
    265               $content = mb_convert_encoding($content, 'UTF-8', $encoding); 
    266               $content = mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8');
    267           }
    268       }
    269      
    270       // save and return
    271       $this->data = $content;
    272       return $this->data;
    273   }
    274  
    275   private static function sanitizeContent($content) {
    276       $content = preg_replace('#<script(.*?)>(.*?)</script>#is', '', $content);
    277       $content = preg_replace('/<--[\S\s]*?-->/msi', '', $content);
    278       $content = preg_replace('/(<noscript[^>]*>|<\/noscript>)/msi', '', $content);
    279       $content = preg_replace('~>\s+<~', '><', $content);
    280       $content = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $content);
    281      
    282       $content = preg_replace('/^.*(?=<html>)/i', '', $content);
    283       $content = str_replace("\0", " ", $content);
     273        // make sure if there is a response at all
     274        if ($this->isHTTPStatusOK() === false) {
     275            // terminate
     276            $this->data = null;
     277            return null;
     278        }
     279
     280        // there is data with OK code, process if required
     281        if (!$this->raw) {
     282            $content = self::sanitizeContent($content);
     283
     284            if ($contentType) {
     285                list($charset, $encoding) = explode("=", $contentType);
     286                $encoding = strtoupper(trim($encoding));
     287
     288                $supportedEncoding = array_search($encoding, mb_list_encodings()) !== false;
     289
     290                if (!$supportedEncoding) {
     291                    $encoding = mb_detect_encoding($content);
     292                }
     293
     294                $content = mb_convert_encoding($content, 'UTF-8', $encoding);
     295                $content = mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8');
     296            }
     297        }
     298
     299        // save and return
     300        $this->data = $content;
     301        return $this->data;
     302    }
     303
     304    private static function sanitizeContent($content)
     305    {
     306        $content = preg_replace('#<script(.*?)>(.*?)</script>#is', '', $content);
     307        $content = preg_replace('/<--[\S\s]*?-->/msi', '', $content);
     308        $content = preg_replace('/(<noscript[^>]*>|<\/noscript>)/msi', '', $content);
     309        $content = preg_replace('~>\s+<~', '><', $content);
     310        $content = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $content);
     311
     312        $content = preg_replace('/^.*(?=<html>)/i', '', $content);
     313        $content = str_replace("\0", " ", $content);
     314
     315        return $content;
     316    }
     317
     318    private function parseDom()
     319    {
     320        if ($this->dom == null) {
     321            // initialize
     322            $dom = new DOMDocument('1.0', 'UTF-8');
     323            @$dom->loadHTML($this->data);
     324
     325            // cleanup
     326            $this->removeElementsByTagName('script', $dom);
     327            $this->removeElementsByTagName('style', $dom);
     328            $this->removeElementsByTagName('link', $dom);
     329
     330            // assign
     331            $this->dom = $dom;
     332            $this->xpath = new DomXPath($dom);
     333        }
     334    }
     335
     336    private function removeElementsByTagName($tagName, $document)
     337    {
     338        $nodeList = $document->getElementsByTagName($tagName);
     339        for ($nodeIdx = $nodeList->length; --$nodeIdx >= 0;) {
     340            $node = $nodeList->item($nodeIdx);
     341            $node->parentNode->removeChild($node);
     342        }
     343    }
     344
     345    private function parseArticle()
     346    {
     347        if ($this->article == null) {
     348            // TODO check the xpath object problem, the final article shall support the same query method
     349
     350            $article = $this->dom->getElementsByTagName('article')->item(0);
     351
     352            if (empty($article)) {
     353                $article = $this->xpath->query("//*[contains(@class, 'hentry')]")->item(0);
     354            }
     355
     356            if (empty($article)) {
     357                $article = $this->xpath->query("//*[contains(@itemtype, 'http://schema.org/Article')]")->item(0);
     358            }
     359
     360            if (empty($article)) {
     361                $article = $this->xpath->query("//*[contains(@itemtype, 'http://schema.org/TechArticle')]")->item(0);
     362            }
     363
     364            if (empty($article)) {
     365                $article = $this->xpath->query("//*[contains(@itemtype, 'http://schema.org/ScholarlyArticle')]")->item(0);
     366            }
     367
     368            if (empty($article)) {
     369                $article = $this->dom->getElementsByTagName('body')->item(0);
     370            }
     371
     372            $this->article = $article;
     373        }
     374    }
     375
     376    public function file_get_contents_utf8($url, $get_http_status = false, $set_utf8 = true)
     377    {
     378        $content = '';
     379        $charset = '';
     380        $utf8 = false;
     381        $timeout = 10;
     382        set_time_limit(0);
     383        $user_agent = ExpressCurate_Actions::USER_AGENT;
     384        $file_get_enabled = preg_match('/1|yes|on|true/i', ini_get('allow_url_fopen'));
     385        if (strpos(parse_url($url, PHP_URL_SCHEME) . "://www.google.com/url", $url) == 0) {
     386            $url_query = explode("&", parse_url($url, PHP_URL_QUERY));
     387            foreach ($url_query as $param) {
     388                if (strpos($param, 'url=') === 0) {
     389                    $url = str_replace("url=", "", $param);
     390                    $url = urldecode($url);
     391                    break;
     392                }
     393            }
     394        }
     395        $normalized_url = html_entity_decode($url);
     396        if (self::supportsAsynch()) {
     397            $ch = curl_init();
     398            //curl_setopt($ch, CURLOPT_HEADER, 1);
     399            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
     400            curl_setopt($ch, CURLOPT_URL, $normalized_url);
     401            curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
     402
     403            // TODO fix the accepts header
     404            curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-type: text/xml;charset=\"utf-8\""));
     405
     406            // TODO configure the return transfer based on asynch choice
     407            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
     408            curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
     409            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
     410            curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
     411            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
     412            $content = curl_exec($ch);
     413
     414            // TODO check if the content shall be transformed to UTF8
     415
     416            $http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
     417            curl_close($ch);
     418        } elseif ($file_get_enabled) {
     419            /*$options = (preg_match("/(^https:\/\/)/i", $url, $options)!=false)?array('ssl' => array('verify_peer'=> false,"verify_peer_name"=>false)):array('http' => array('user_agent' => $user_agent));*/
     420            $options = array('http' => array('user_agent' => $user_agent, ' follow_location' => 1, 'max_redirects' => 5, 'request_fulluri ' => TRUE, 'timeout' => $timeout));
     421            if (preg_match("/(^https:\/\/)/i", $url) != false) {
     422                $options['ssl'] = array('verify_peer' => false, "verify_peer_name" => false);
     423            }
     424            $context = stream_context_create($options);
     425            $content = file_get_contents($normalized_url, false, $context);
     426            // $content = mb_convert_encoding($content, 'HTML-ENTITIES', "UTF-8");
     427            $http_status = $http_response_header;
     428
     429            if (!empty($http_response_header)) {
     430                foreach ($http_response_header as $header) {
     431                    if (substr(strtolower($header), 0, 13) == "content-type:") {
     432                        if (count(explode(";", $header)) > 1) {
     433                            list($contentType, $charset) = explode(";", $header);
     434                        }
     435                    }
     436                }
     437            }
     438
     439            $headers = headers_list();
     440            // get the content type header
     441            foreach ($headers as $header) {
     442                if (substr(strtolower($header), 0, 13) == "content-type:") {
     443                    list($contentType, $charset) = explode(";", trim(substr($header, 14), 2));
     444                    if (strtolower(trim($charset)) == "charset=utf-8") {
     445                        $utf8 = true;
     446                    }
     447                }
     448            }
     449            if ($charset && strpos(strtolower($charset), 'utf-8')) {
     450                $utf8 = true;
     451            } else {
     452                $charset = mb_detect_encoding($content);
     453                if (strpos(strtolower($charset), 'utf-8')) {
     454                    $utf8 = true;
     455                }
     456            }
     457            if (!$utf8 && $set_utf8) {
     458                $content = utf8_encode($content);
     459            }
     460        } else {
     461            $data = array('status' => 'warning', 'msg' => 'Content from this page cannot be loaded.  Please enable \"allow_url_open\" in php.ini.');
     462            echo json_encode($data);
     463            die();
     464        }
     465        if (!$get_http_status) {
     466            return $content;
     467        } else {
     468            return array('content' => $content, 'http_status' => $http_status);
     469        }
     470    }
     471
     472    public function getContents()
     473    {
     474        $this->download();
     475
     476        if (strlen($this->data) > 3) {
     477            // prepare some data before getting contents
     478            $this->title = $this->getTitle();
     479            $this->keywords = $this->getKeywords();
     480            $this->description = $this->getDescription();
     481
     482            // get the contents
     483            return $this->getElementsByTags();
     484        } else {
     485            return false;
     486        }
     487    }
    284488   
    285       return $content;
    286   }
    287  
    288   private function parseDom() {
    289       if($this->dom == null) {
    290           // initialize
    291           $dom = new DOMDocument('1.0', 'UTF-8');
    292           @$dom->loadHTML($this->data);
    293      
    294           // cleanup
    295           $this->removeElementsByTagName('script', $dom);
    296           $this->removeElementsByTagName('style', $dom);
    297           $this->removeElementsByTagName('link', $dom);
    298          
    299           // assign
    300           $this->dom = $dom;
    301           $this->xpath = new DomXPath($dom);
    302       }
    303   }
    304  
    305   private function removeElementsByTagName($tagName, $document) {
    306       $nodeList = $document->getElementsByTagName($tagName);
    307       for ($nodeIdx = $nodeList->length; --$nodeIdx >= 0;) {
    308           $node = $nodeList->item($nodeIdx);
    309           $node->parentNode->removeChild($node);
    310       }
    311   }
    312  
    313   private function parseArticle() {
    314       if($this->article == null) {
    315           // TODO check the xpath object problem, the final article shall support the same query method
    316      
    317           $article = $this->dom->getElementsByTagName('article')->item(0);
    318          
    319           if(empty($article)) {
    320               $article = $this->xpath->query("//*[contains(@class, 'hentry')]")->item(0);
    321           }
    322 
    323           if(empty($article)) {
    324               $article = $this->xpath->query("//*[contains(@itemtype, 'http://schema.org/Article')]")->item(0);
    325           }
    326 
    327           if(empty($article)) {
    328               $article = $this->xpath->query("//*[contains(@itemtype, 'http://schema.org/TechArticle')]")->item(0);
    329           }
    330 
    331           if(empty($article)) {
    332               $article = $this->xpath->query("//*[contains(@itemtype, 'http://schema.org/ScholarlyArticle')]")->item(0);
    333           }
    334 
    335           if(empty($article)) {
    336               $article = $this->dom->getElementsByTagName('body')->item(0);
    337           }
    338          
    339           $this->article = $article;
    340       }
    341   }
    342  
    343   public function file_get_contents_utf8($url, $get_http_status = false, $set_utf8 = true) {
    344       $content = '';
    345       $charset = '';
    346       $utf8 = false;
    347       $timeout=10;
    348       set_time_limit(0);
    349       $user_agent = ExpressCurate_Actions::USER_AGENT;
    350       $file_get_enabled = preg_match('/1|yes|on|true/i', ini_get('allow_url_fopen'));
    351       if(strpos(parse_url($url,PHP_URL_SCHEME)."://www.google.com/url",$url)==0) {
    352           $url_query = explode("&",parse_url($url,PHP_URL_QUERY));
    353           foreach($url_query as $param) {
    354               if(strpos($param, 'url=') === 0) {
    355                   $url = str_replace("url=", "", $param);
    356                   $url = urldecode($url);
    357                   break;
    358               }
    359           }
    360       }
    361       $normalized_url = html_entity_decode($url);
    362       if (self::supportsAsynch()) {
    363           $ch = curl_init();
    364           //curl_setopt($ch, CURLOPT_HEADER, 1);
    365           curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    366           curl_setopt($ch, CURLOPT_URL, $normalized_url);
    367           curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
    368          
    369           // TODO fix the accepts header
    370           curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-type: text/xml;charset=\"utf-8\""));
    371          
    372           // TODO configure the return transfer based on asynch choice
    373           curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    374           curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
    375           curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    376           curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
    377           curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
    378           $content = curl_exec($ch);
    379          
    380           // TODO check if the content shall be transformed to UTF8
    381          
    382           $http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    383           curl_close($ch);
    384       } elseif($file_get_enabled) {
    385           /*$options = (preg_match("/(^https:\/\/)/i", $url, $options)!=false)?array('ssl' => array('verify_peer'=> false,"verify_peer_name"=>false)):array('http' => array('user_agent' => $user_agent));*/
    386           $options = array('http' => array('user_agent' => $user_agent,' follow_location'=>1,'max_redirects'=>5,'request_fulluri '=>TRUE,'timeout' => $timeout));
    387           if(preg_match("/(^https:\/\/)/i", $url)!=false){
    388              $options['ssl']=array('verify_peer'=> false,"verify_peer_name"=>false);
    389           }
    390           $context = stream_context_create($options);
    391           $content = file_get_contents($normalized_url, false, $context);
    392           // $content = mb_convert_encoding($content, 'HTML-ENTITIES', "UTF-8");
    393           $http_status = $http_response_header;
    394 
    395           if(!empty($http_response_header)) {
    396               foreach ($http_response_header as $header) {
    397                   if (substr(strtolower($header), 0, 13) == "content-type:") {
    398                       if (count(explode(";", $header)) > 1) {
    399                           list($contentType, $charset) = explode(";", $header);
    400                       }
    401                   }
    402               }
    403           }
    404 
    405           $headers = headers_list();
    406           // get the content type header
    407           foreach ($headers as $header) {
    408             if (substr(strtolower($header), 0, 13) == "content-type:") {
    409               list($contentType, $charset) = explode(";", trim(substr($header, 14), 2));
    410               if (strtolower(trim($charset)) == "charset=utf-8") {
    411                 $utf8 = true;
    412               }
    413             }
    414           }
    415           if ($charset && strpos(strtolower($charset), 'utf-8')) {
    416             $utf8 = true;
    417           } else {
    418             $charset = mb_detect_encoding($content);
    419             if (strpos(strtolower($charset), 'utf-8')) {
    420               $utf8 = true;
    421             }
    422           }
    423           if (!$utf8 && $set_utf8) {
    424             $content = utf8_encode($content);
    425           }
    426       } else {
    427           $data = array('status' => 'warning', 'msg' => 'Content from this page cannot be loaded.  Please enable \"allow_url_open\" in php.ini.');
    428           echo json_encode($data);
    429           die();
    430       }
    431       if (!$get_http_status) {
    432          return $content;
    433       } else {
    434          return array('content' => $content, 'http_status' => $http_status);
    435       }
    436   }
    437 
    438   public function getContents() {
    439     $this->download();
     489    public function getCloneContents()
     490    {
     491        $this->download();
     492
     493        if (strlen($this->data) > 3) {
     494            // prepare some data before getting contents
     495            $this->title = $this->getTitle();
     496            $this->keywords = $this->getKeywords();
     497
     498            // get the contents
     499            return $this->cloneElements();
     500        } else {
     501            return false;
     502        }
     503    }
     504
     505    private function getTitle()
     506    {
     507        $this->parseDom();
     508
     509        $title = $this->xpath->query('//title')->item(0)->nodeValue;
     510
     511        return $title;
     512    }
     513
     514    private function getKeywords()
     515    {
     516        // Get the 'content' attribute value in a <meta name="keywords" ... />
     517        $matches = array();
     518        $max_count = get_option("expresscurate_max_tags", 3);
     519        // Search for <meta name="keywords" content="keyword1, keword2" />
     520        preg_match('/<meta.*?name=("|\')keywords("|\').*?content=("|\')(.*?)("|\')/i', $this->data, $matches);
     521        if (count($matches) > 4) {
     522            return array_filter(explode(",", trim($matches[4])));
     523        }
     524
     525        // Order of attributes could be swapped around: <meta content="keyword1, keword2" name="keywords" />
     526        preg_match('/<meta.*?content=("|\')(.*?)("|\').*?name=("|\')keywords("|\')/i', $this->data, $matches);
     527        if (count($matches) > 2) {
     528            return array_filter(explode(",", trim($matches[2])));
     529        }
     530
     531        // No match
     532        return null;
     533    }
     534
     535    private function getDescription()
     536    {
     537        // Get the 'content' attribute value in a <meta name="description" ... />
     538        $matches = array();
     539
     540        // Search for <meta name="description" content="Buy my stuff" />
     541        preg_match('/<meta.*?name=("|\')description("|\').*?content=("|\')(.*?)("|\')/i', $this->data, $matches);
     542        if (count($matches) > 4) {
     543            return $matches[4];
     544        }
     545
     546        // Order of attributes could be swapped around: <meta content="Buy my stuff" name="description" />
     547        preg_match('/<meta.*?content=("|\')(.*?)("|\').*?name=("|\')description("|\')/i', $this->data, $matches);
     548        if (count($matches) > 2) {
     549            return $matches[2];
     550        }
     551
     552        // No match
     553        return null;
     554    }
     555
     556    private function getElementsByTags()
     557    {
     558        $this->parseDom();
     559        $this->parseArticle();
     560
     561        // TODO make sure this cleanup can be done earlier or later, or maybe shall not affect the base dom with original html at all
     562
     563        $result_images = array();
     564        $result_paragraphs = array();
     565        $result_h1 = '';
     566        $result_h2 = '';
     567        $result_h3 = '';
     568
     569
     570        // TODO this is a new xpath with the new modified dom, not sure if this is required if dom is passed with a reference
     571        $imgTags = $this->xpath->query(".//img",$this->article);
     572        $i = 0;
     573        foreach ($imgTags as $t) {
     574            $src = $t->getAttribute('src');
     575            if (strlen($src) > 3) {
     576                if (strpos($src, 'http://') !== false || strpos($src, 'https://') !== false) {
     577                    $src = $src;
     578                } else if (strpos($src, '//') === 0) {
     579                    if (isset($this->fragment)) {
     580                        $src = $this->fragment . $src;
     581                    } else {
     582                        $src = $this->protocol . ":" . $src;
     583                    }
     584                } elseif (strpos($src, '/') === 0) {
     585                    $src = $this->domain . $src;
     586                } else {
     587                    $src = $this->path . $src;
     588                }
     589
     590                $src = preg_replace('%([^:])([/]{2,})%', '\\1/', $src);
     591
     592                if (!in_array($src, $result_images)) {
     593                    $result_images[] = ($src);
     594                }
     595                $i++;
     596            }
     597            $t->parentNode->removeChild($t);
     598        }
     599        //get H1
     600        $h1Tag = $this->xpath->query(".//h1",$this->article);
     601        foreach ($h1Tag as $h1) {
     602            if (strlen($h1->nodeValue) > 3) {
     603                $result_h1 .= $h1->nodeValue . "\n";
     604            }
     605            $h1->parentNode->removeChild($h1);
     606        }
     607        //get H2
     608        $h2Tag = $this->xpath->query(".//h2",$this->article);
     609        foreach ($h2Tag as $h2) {
     610            if (strlen($h2->nodeValue) > 3) {
     611                $result_h2 .= $h2->nodeValue . "\n";
     612            }
     613            $h2->parentNode->removeChild($h2);
     614        }
     615        //get H3
     616        $h3Tag = $this->xpath->query(".//h3",$this->article);
     617        foreach ($h3Tag as $h3) {
     618            if (strlen($h3->nodeValue) > 3) {
     619                $result_h3 .= $h3->nodeValue . "\n";
     620            }
     621            $h3->parentNode->removeChild($h3);
     622        }
     623        //get text
     624        /*$i = 0;
     625        $articleTags = $this->xpath->query('/html/body/article');
     626        foreach ($articleTags as $t) {
     627            $result_paragraphs[$i]['value'] = strip_tags(trim($t->nodeValue));
     628            $result_paragraphs[$i]['tag'] = 'article';
     629            $t->parentNode->removeChild($t);
     630            $i++;
     631        }*/
     632
     633
     634        $textTags = $this->xpath->query('//text()',$this->article);
     635        foreach ($textTags as $t) {
     636            if ($t->length > 15 && $t->parentNode->tagName != 'a' && $t->parentNode->tagName != 'h1' && $t->parentNode->tagName != 'h2' && $t->parentNode->tagName != 'h3') {
     637                if ($t->parentNode->nodeName == "blockquote" || $t->parentNode->parentNode->nodeName == "blockquote" || $t->parentNode->parentNode->parentNode->nodeName == "blockquote") {
     638                    if ($t->parentNode->nodeName == "blockquote") {
     639                        $result_paragraphs[$i]['value'] = strip_tags($t->parentNode->nodeValue);
     640                    } elseif ($t->parentNode->parentNode && $t->parentNode->parentNode->nodeName == "blockquote") {
     641                        $result_paragraphs[$i]['value'] = strip_tags($t->parentNode->parentNode->nodeValue);
     642                    } elseif ($t->parentNode->parentNode->parentNode && $t->parentNode->parentNode->parentNode->nodeName == "blockquote") {
     643                        $result_paragraphs[$i]['value'] = strip_tags($t->parentNode->parentNode->parentNode->nodeValue);
     644                    }
     645                    $result_paragraphs[$i]['tag'] = "blockquote";
     646                } else {
     647                    $result_paragraphs[$i]['value'] = strip_tags($t->nodeValue);
     648                    $result_paragraphs[$i]['tag'] = $t->parentNode->nodeName;
     649                }
     650                $i++;
     651            }
     652        }
     653
     654        //author
     655        $article_author = '';
     656        $author = $this->xpath->query('.//*[@rel="author"][1]',$this->article)->item(0);
     657        if ($author) {
     658            $article_author = $author->nodeValue;
     659        }
     660        //date
     661        $article_date = '';
     662        $date = $this->xpath->query('.//*[@datetime][1]',$this->article)->item(0);
     663        if ($date) {
     664            $article_date = $date->nodeValue;
     665        }
     666
     667
     668        //smart tags
     669        $max_count = get_option("expresscurate_max_tags", 3);
     670        $smart_tags = array();
     671
     672        $defined_tags = get_option("expresscurate_defined_tags", '');
     673        if ($defined_tags) {
     674            $defined_tags = explode(",", $defined_tags);
     675            foreach ($defined_tags as $tag) {
     676                $tag = trim($tag);
     677                $count = $this->countMatches($tag);
     678                if ($count > 0) {
     679                    $smart_tags[$tag] = $count;
     680                }
     681            }
     682        }
     683
     684        if (count($this->keywords)) {
     685            foreach ($this->keywords as $key => $keyword) {
     686                $count = $this->countMatches($key);
     687                if ($count > 0) {
     688                    $smart_tags[$keyword] = $count;
     689                }
     690            }
     691        }
     692
     693        if (count($smart_tags) > 0) {
     694            arsort($smart_tags);
     695            $smart_tags = array_slice(array_keys(array_reverse($smart_tags)), 0, $max_count);
     696        }
     697
     698        $result_paragraphs_unique = $this->arrayUnique($result_paragraphs);
     699        $media = $this->containsMedia();
     700
     701        $result = array(
     702            'title' => $this->title,
     703            'headings' => array('h1' => $result_h1, 'h2' => $result_h2, 'h3' => $result_h3),
     704            'metas' => array('description' => $this->description, 'keywords' => $smart_tags),
     705            'images' => $result_images,
     706            'media' => $media,
     707            'paragraphs' => $result_paragraphs_unique,
     708            'author' => $article_author,
     709            'date' => $article_date,
     710            'domain' => $this->domain);
     711        $data = array('status' => 'success', 'result' => $result);
     712        return $data;
     713    }
    440714   
    441     if (strlen($this->data) > 3) {
    442       // prepare some data before getting contents
    443       $this->title = $this->getTitle();
    444       $this->keywords = $this->getKeywords();
    445       $this->description = $this->getDescription();
    446      
    447       // get the contents
    448       return $this->getElementsByTags();
    449     } else {
    450       return false;
    451     }
    452   }
    453  
    454   private function getTitle() {
    455     $this->parseDom();
    456    
    457     $title = $this->xpath->query('//title')->item(0)->nodeValue;
    458    
    459     return $title;
    460   }
    461  
    462   private function getKeywords() {
    463     // Get the 'content' attribute value in a <meta name="keywords" ... />
    464     $matches = array();
    465     $max_count = get_option("expresscurate_max_tags", 3);
    466     // Search for <meta name="keywords" content="keyword1, keword2" />
    467     preg_match('/<meta.*?name=("|\')keywords("|\').*?content=("|\')(.*?)("|\')/i', $this->data, $matches);
    468     if (count($matches) > 4) {
    469       return array_filter(explode(",", trim($matches[4])));
    470     }
    471 
    472     // Order of attributes could be swapped around: <meta content="keyword1, keword2" name="keywords" />
    473     preg_match('/<meta.*?content=("|\')(.*?)("|\').*?name=("|\')keywords("|\')/i', $this->data, $matches);
    474     if (count($matches) > 2) {
    475         return array_filter(explode(",", trim($matches[2])));
    476     }
    477 
    478     // No match
    479     return null;
    480   }
    481  
    482   private function getDescription() {
    483     // Get the 'content' attribute value in a <meta name="description" ... />
    484     $matches = array();
    485 
    486     // Search for <meta name="description" content="Buy my stuff" />
    487     preg_match('/<meta.*?name=("|\')description("|\').*?content=("|\')(.*?)("|\')/i', $this->data, $matches);
    488     if (count($matches) > 4) {
    489       return $matches[4];
    490     }
    491 
    492     // Order of attributes could be swapped around: <meta content="Buy my stuff" name="description" />
    493     preg_match('/<meta.*?content=("|\')(.*?)("|\').*?name=("|\')description("|\')/i', $this->data, $matches);
    494     if (count($matches) > 2) {
    495       return $matches[2];
    496     }
    497 
    498     // No match
    499     return null;
    500   }
    501 
    502   private function getElementsByTags() {
    503     $this->parseDom();
    504 
    505     // TODO make sure this cleanup can be done earlier or later, or maybe shall not affect the base dom with original html at all
    506    
    507     $result_images = array();
    508     $result_paragraphs = array();
    509     $result_h1 = '';
    510     $result_h2 = '';
    511     $result_h3 = '';
    512    
    513     // TODO this is a new xpath with the new modified dom, not sure if this is required if dom is passed with a reference
    514     $imgTags = $this->xpath->query("//img");
    515     $i = 0;
    516     foreach ($imgTags as $t) {
    517       $src = $t->getAttribute('src');
    518       if (strlen($src) > 3) {
    519         if (strpos($src, 'http://') !== false || strpos($src, 'https://') !== false) {
    520           $src = $src;
    521         } else if (strpos($src, '//') === 0) {
    522           if(isset($this->fragment)) {
    523               $src = $this->fragment . $src;
    524           }
    525           else{
    526               $src = $this->protocol . ":" . $src;
    527           }
    528         } elseif (strpos($src, '/') === 0) {
    529           $src = $this->domain . $src;
    530         } else {
    531           $src = $this->path . $src;
    532         }
    533 
    534         $src = preg_replace('%([^:])([/]{2,})%', '\\1/', $src);
    535 
    536         if (!in_array($src, $result_images)) {
    537           $result_images[] = ($src);
    538         }
    539         $i++;
    540       }
    541       $t->parentNode->removeChild($t);
    542     }
    543     //get H1
    544     $h1Tag = $this->xpath->query('//h1');
    545     foreach ($h1Tag as $h1) {
    546       if (strlen($h1->nodeValue) > 3) {
    547         $result_h1 .= $h1->nodeValue . "\n";
    548       }
    549       $h1->parentNode->removeChild($h1);
    550     }
    551     //get H2
    552     $h2Tag = $this->xpath->query('//h2');
    553     foreach ($h2Tag as $h2) {
    554       if (strlen($h2->nodeValue) > 3) {
    555         $result_h2 .= $h2->nodeValue . "\n";
    556       }
    557       $h2->parentNode->removeChild($h2);
    558     }
    559     //get H3
    560     $h3Tag = $this->xpath->query('//h3');
    561     foreach ($h3Tag as $h3) {
    562       if (strlen($h3->nodeValue) > 3) {
    563         $result_h3 .= $h3->nodeValue . "\n";
    564       }
    565       $h3->parentNode->removeChild($h3);
    566     }
    567     //get text
    568     $i = 0;
    569     $articleTags = $this->xpath->query('/html/body/article');
    570     foreach ($articleTags as $t) {
    571       $result_paragraphs[$i]['value'] = strip_tags(trim($t->nodeValue));
    572       $result_paragraphs[$i]['tag'] = 'article';
    573       $t->parentNode->removeChild($t);
    574       $i++;
    575     }
    576 
    577 
    578     $textTags = $this->xpath->query('/html/body//text()');
    579 
    580     foreach ($textTags as $t) {
    581       if ($t->length > 15 && $t->parentNode->tagName != 'a' && $t->parentNode->tagName != 'h1' && $t->parentNode->tagName != 'h2' && $t->parentNode->tagName != 'h3') {
    582         if ($t->parentNode->nodeName == "blockquote" || $t->parentNode->parentNode->nodeName == "blockquote" || $t->parentNode->parentNode->parentNode->nodeName == "blockquote") {
    583           if ($t->parentNode->nodeName == "blockquote") {
    584             $result_paragraphs[$i]['value'] = strip_tags($t->parentNode->nodeValue);
    585           } elseif ($t->parentNode->parentNode && $t->parentNode->parentNode->nodeName == "blockquote") {
    586             $result_paragraphs[$i]['value'] = strip_tags($t->parentNode->parentNode->nodeValue);
    587           } elseif ($t->parentNode->parentNode->parentNode && $t->parentNode->parentNode->parentNode->nodeName == "blockquote") {
    588             $result_paragraphs[$i]['value'] = strip_tags($t->parentNode->parentNode->parentNode->nodeValue);
    589           }
    590           $result_paragraphs[$i]['tag'] = "blockquote";
    591         } else {
    592           $result_paragraphs[$i]['value'] = strip_tags($t->nodeValue);
    593           $result_paragraphs[$i]['tag'] = $t->parentNode->nodeName;
    594         }
    595         $i++;
    596       }
    597     }
    598     //author
    599     $article_author = '';
    600     $author = $this->xpath->query('//*[@rel="author"][1]')->item(0);
    601     if ($author) {
    602       $article_author = $author->nodeValue;
    603     }
    604     //date
    605     $article_date = '';
    606     $date = $this->xpath->query('//*[@datetime][1]')->item(0);
    607     if ($date) {
    608       $article_date = $date->nodeValue;
    609     }
    610 
    611 
    612     //smart tags
    613     $max_count = get_option("expresscurate_max_tags", 3);
    614     $smart_tags = array();
    615 
    616     $defined_tags = get_option("expresscurate_defined_tags", '');
    617     if ($defined_tags) {
    618       $defined_tags = explode(",", $defined_tags);
    619       foreach ($defined_tags as $tag) {
    620         $tag = trim($tag);
    621         $count = $this->countMatches($tag);
    622         if ($count > 0) {
    623           $smart_tags[$tag] = $count;
    624         }
    625       }
    626     }
    627 
    628     if (count($this->keywords)) {
    629       foreach ($this->keywords as $key => $keyword) {
    630         $count = $this->countMatches($key);
    631         if ($count > 0) {
    632           $smart_tags[$keyword] = $count;
    633         }
    634       }
    635     }
    636 
    637     if (count($smart_tags) > 0) {
    638       arsort($smart_tags);
    639       $smart_tags = array_slice(array_keys(array_reverse($smart_tags)), 0, $max_count);
    640     }
    641    
    642     $result_paragraphs_unique = $this->arrayUnique($result_paragraphs);
    643     $media = $this->containsMedia();
    644    
    645     $result = array(
    646         'title'      => $this->title,
    647         'headings'   => array('h1' => $result_h1, 'h2' => $result_h2, 'h3' => $result_h3),
    648         'metas'      => array('description' => $this->description, 'keywords' => $smart_tags),
    649         'images'     => $result_images,
    650         'media'      => $media,
    651         'paragraphs' => $result_paragraphs_unique,
    652         'author'     => $article_author,
    653         'date'       => $article_date,
    654         'domain'     => $this->domain);
    655     $data = array('status' => 'success', 'result' => $result);
    656     return $data;
    657   }
    658 
    659   private function countMatches($keyword) {
    660       $total_occurrence = 0;
    661       $tag_in_title = array();
    662       $tag_in_content = array();
    663       preg_match_all("/(?<!\w)(?=[^>]*(<|$))" . $keyword . "/i", $this->title, $tag_in_title);
    664       preg_match_all("/(?<!\w)(?=[^>]*(<|$))" . $keyword . "/i", $this->data, $tag_in_content);
    665       $total_occurrence = count($tag_in_title[0]) + count($tag_in_content[0]);
    666       return $total_occurrence;
    667   }
    668 
    669   private function arrayUnique($array, $preserveKeys = false) {
    670     // Unique Array for return
    671     $arrayRewrite = array();
    672     // Array with the md5 hashes
    673     $arrayHashes = array();
    674     foreach ($array as $key => $item) {
    675       // Serialize the current element and create a md5 hash
    676       $hash = md5(serialize($item));
    677       // If the md5 didn't come up yet, add the element to
    678       // to arrayRewrite, otherwise drop it
    679       if (!isset($arrayHashes[$hash])) {
    680         // Save the current element hash
    681         $arrayHashes[$hash] = $hash;
    682         // Add element to the unique Array
    683         if ($preserveKeys) {
    684           $arrayRewrite[$key] = $item;
    685         } else {
    686           $arrayRewrite[] = $item;
    687         }
    688       }
    689     }
    690     return $arrayRewrite;
    691   }
    692 
    693   public function analyzeKeywords() {
    694       $keywordsString =  get_option('expresscurate_defined_tags');
    695       $blogKeywords = !empty($keywordsString) ? explode(', ', $keywordsString) : array();
    696      
    697       $this->download();
    698       $this->parseDom();
    699       $this->parseArticle();
    700      
    701       $title = $this->dom->getElementsByTagName('h1')->item(0)->nodeValue;
    702       $titleArray = preg_split('/\s+/u', $title);
    703 
    704       $article = strip_tags($this->article->nodeValue);
    705       $articleFiltered = preg_replace('/\b(a|able|about|above|abroad|according|accordingly|across|actually|adj|after|afterwards|again|against|ago|ahead|ain\'t|all|allow|allows|almost|alone|along|alongside|already|also|although|always|am|amid|amidst|among|amongst|an|and|another|any|anybody|anyhow|anyone|anything|anyway|anyways|anywhere|apart|appear|appreciate|appropriate|are|aren\'t|around|as|a\'s|aside|ask|asking|associated|at|available|away|awfully|b|back|backward|backwards|be|became|because|become|becomes|becoming|been|before|beforehand|begin|behind|being|believe|below|beside|besides|best|better|between|beyond|both|brief|but|by|c|came|can|cannot|cant|can\'t|caption|cause|causes|certain|certainly|changes|clearly|c\'mon|co|co.|com|come|comes|concerning|consequently|consider|considering|contain|containing|contains|corresponding|could|couldn\'t|course|c\'s|currently|d|dare|daren\'t|definitely|described|despite|did|didn\'t|different|directly|do|does|doesn\'t|doing|done|don\'t|down|downwards|during|e|each|edu|eg|eight|eighty|either|else|elsewhere|end|ending|enough|entirely|especially|et|etc|even|ever|evermore|every|everybody|everyone|everything|everywhere|ex|exactly|example|except|f|fairly|far|farther|few|fewer|fifth|first|five|followed|following|follows|for|forever|former|formerly|forth|forward|found|four|from|further|furthermore|g|get|gets|getting|given|gives|go|goes|going|gone|got|gotten|greetings|h|had|hadn\'t|half|happens|hardly|has|hasn\'t|have|haven\'t|having|he|he\'d|he\'ll|hello|help|hence|her|here|hereafter|hereby|herein|here\'s|hereupon|hers|herself|he\'s|hi|him|himself|his|hither|hopefully|how|howbeit|however|hundred|i|i\'d|ie|if|ignored|i\'ll|i\'m|immediate|in|inasmuch|inc|inc.|indeed|indicate|indicated|indicates|inner|inside|insofar|instead|into|inward|is|isn\'t|it|it\'d|it\'ll|its|it\'s|itself|i\'ve|j|just|k|keep|keeps|kept|know|known|knows|l|last|lately|later|latter|latterly|least|less|lest|let|let\'s|like|liked|likely|likewise|little|look|looking|looks|low|lower|ltd|m|made|mainly|make|makes|many|may|maybe|mayn\'t|me|mean|meantime|meanwhile|merely|might|mightn\'t|mine|minus|miss|more|moreover|most|mostly|mr|mrs|much|must|mustn\'t|my|myself|n|name|namely|nd|near|nearly|necessary|need|needn\'t|needs|neither|never|neverf|neverless|nevertheless|new|next|nine|ninety|no|nobody|non|none|nonetheless|noone|no-one|nor|normally|not|nothing|notwithstanding|novel|now|nowhere|o|obviously|of|off|often|oh|ok|okay|old|on|once|one|ones|one\'s|only|onto|opposite|or|other|others|otherwise|ought|oughtn\'t|our|ours|ourselves|out|outside|over|overall|own|p|particular|particularly|past|per|perhaps|placed|please|plus|possible|presumably|probably|provided|provides|q|que|quite|qv|r|rather|rd|re|really|reasonably|recent|recently|regarding|regardless|regards|relatively|respectively|right|round|s|said|same|saw|say|saying|says|second|secondly|see|seeing|seem|seemed|seeming|seems|seen|self|selves|sensible|sent|serious|seriously|seven|several|shall|shan\'t|she|she\'d|she\'ll|she\'s|should|shouldn\'t|since|six|so|some|somebody|someday|somehow|someone|something|sometime|sometimes|somewhat|somewhere|soon|sorry|specified|specify|specifying|still|sub|such|sup|sure|t|take|taken|taking|tell|tends|th|than|thank|thanks|thanx|that|that\'ll|thats|that\'s|that\'ve|the|their|theirs|them|themselves|then|thence|there|thereafter|thereby|there\'d|therefore|therein|there\'ll|there\'re|theres|there\'s|thereupon|there\'ve|these|they|they\'d|they\'ll|they\'re|they\'ve|thing|things|think|third|thirty|this|thorough|thoroughly|those|though|three|through|throughout|thru|thus|till|to|together|too|took|toward|towards|tried|tries|truly|try|trying|t\'s|twice|two|u|un|under|underneath|undoing|unfortunately|unless|unlike|unlikely|until|unto|up|upon|upwards|us|use|used|useful|uses|using|usually|v|value|various|versus|very|via|viz|vs|w|want|wants|was|wasn\'t|way|we|we\'d|welcome|well|we\'ll|went|were|we\'re|weren\'t|we\'ve|what|whatever|what\'ll|what\'s|what\'ve|when|whence|whenever|where|whereafter|whereas|whereby|wherein|where\'s|whereupon|wherever|whether|which|whichever|while|whilst|whither|who|who\'d|whoever|whole|who\'ll|whom|whomever|who\'s|whose|why|will|willing|wish|with|within|without|wonder|won\'t|would|wouldn\'t|x|y|yes|yet|you|you\'d|you\'ll|your|you\'re|yours|yourself|yourselves|you\'ve|z|zero, replacement)\\b/','', $article);
    706       $articleFiltered = preg_replace('/\p{P}+/u',' ',$articleFiltered);
    707       $articleArray = preg_split('/\s+/u', $articleFiltered);
    708       $articleWordsCount = count($articleArray);
    709 
    710       $result = array();
    711 
    712       foreach($blogKeywords as $keyword) {
    713           $count = 0;
    714           $inTitle = 'No';
    715 
    716           if (in_array(mb_strtolower($keyword), $articleArray)) {
    717               $count++;
    718           }
    719           foreach($titleArray as $titleWord) {
    720               if (mb_strtolower($titleWord) == mb_strtolower($keyword)) {
    721                   $inTitle = 'Yes';
    722                   break;
    723               }
    724           }
    725           if($count !== 0) {
    726               $result[$keyword] = array('percent' => round($count/$articleWordsCount, 4), 'title' => $inTitle);
    727           }
    728       }
    729 
    730       return $result;
    731   }
    732 
    733    public function containsMedia() {
    734        $this->parseDom();
    735        
    736        $imgTags = $this->xpath->query("//img");
    737        $img_array = array();
    738        foreach ($imgTags as $t) {
    739            $src = $t->getAttribute('src');
    740            $img_array[] = $src;
    741        }
    742        $obj = $this->xpath->query("//node()[(name()='iframe' or name()='video' or name()='source' or name()= 'object' or name()='embed') and (contains(@src,'youtube.com') or contains(@src ,'vimeo.com') or contains(@src,'youtu.be'))]");
    743        $videoArrays = array();
    744        foreach($obj as $objs) {
    745            array_push($videoArrays,$objs->getAttribute('src'));
    746        }
    747        $mediaTags = array("images"=>count($img_array),"videos"=>count($videoArrays));
    748        return $mediaTags;
    749    }
     715    private function cloneElements()
     716    {
     717        $this->parseDom();
     718        $this->parseArticle();
     719
     720        // TODO make sure this cleanup can be done earlier or later, or maybe shall not affect the base dom with original html at all
     721
     722        $result_images = array();
     723        $imgTags = $this->xpath->query(".//img", $this->article);
     724        $i = 0;
     725        foreach ($imgTags as $t) {
     726            $src = $t->getAttribute('src');
     727            if (strlen($src) > 3) {
     728                if (strpos($src, 'http://') !== false || strpos($src, 'https://') !== false) {
     729                    $src = $src;
     730                } else if (strpos($src, '//') === 0) {
     731                    if (isset($this->fragment)) {
     732                        $src = $this->fragment . $src;
     733                    } else {
     734                        $src = $this->protocol . ":" . $src;
     735                    }
     736                } elseif (strpos($src, '/') === 0) {
     737                    $src = $this->domain . $src;
     738                } else {
     739                    $src = $this->path . $src;
     740                }
     741
     742                $src = preg_replace('%([^:])([/]{2,})%', '\\1/', $src);
     743
     744                if (!in_array($src, $result_images)) {
     745                    $result_images[] = ($src);
     746                }
     747                $i++;
     748            }
     749            $t->parentNode->removeChild($t);
     750        }
     751       
     752        //smart tags
     753        $max_count = get_option("expresscurate_max_tags", 3);
     754        $smart_tags = array();
     755
     756        $defined_tags = get_option("expresscurate_defined_tags", '');
     757        if ($defined_tags) {
     758            $defined_tags = explode(",", $defined_tags);
     759            foreach ($defined_tags as $tag) {
     760                $tag = trim($tag);
     761                $count = $this->countMatches($tag);
     762                if ($count > 0) {
     763                    $smart_tags[$tag] = $count;
     764                }
     765            }
     766        }
     767
     768        if (count($this->keywords)) {
     769            foreach ($this->keywords as $key => $keyword) {
     770                $count = $this->countMatches($key);
     771                if ($count > 0) {
     772                    $smart_tags[$keyword] = $count;
     773                }
     774            }
     775        }
     776
     777        if (count($smart_tags) > 0) {
     778            arsort($smart_tags);
     779            $smart_tags = array_slice(array_keys(array_reverse($smart_tags)), 0, $max_count);
     780        }
     781
     782        $comments = $this->xpath->query(".//comment()",$this->article);
     783        foreach($comments as $cmnt){
     784            $cmnt->parentNode->removeChild($cmnt);
     785        }
     786        $h1Tag = $this->xpath->query(".//h1",$this->article);
     787        foreach ($h1Tag as $h1) {
     788            $h1->parentNode->removeChild($h1);
     789        }
     790        $input = $this->xpath->query(".//node()[name()='iframe' or name()='input' or name()='button' or name='textarea' or name()='form']",$this->article);
     791        foreach ($input as $inp) {
     792            $inp->parentNode->removeChild($inp);
     793        }
     794
     795
     796        $articleContent = $this->dom->saveXML($this->article);
     797        $result = array(
     798            'title' => $this->title,
     799            'content'=> $articleContent,
     800            'metas' => array('keywords' => $smart_tags),
     801            'images' => $result_images,
     802            'domain' => $this->domain);
     803        $data = array('status' => 'success', 'result' => $result);
     804        return $data;
     805    }
     806
     807    private function countMatches($keyword)
     808    {
     809        $total_occurrence = 0;
     810        $tag_in_title = array();
     811        $tag_in_content = array();
     812        preg_match_all("/(?<!\w)(?=[^>]*(<|$))" . $keyword . "/i", $this->title, $tag_in_title);
     813        preg_match_all("/(?<!\w)(?=[^>]*(<|$))" . $keyword . "/i", $this->data, $tag_in_content);
     814        $total_occurrence = count($tag_in_title[0]) + count($tag_in_content[0]);
     815        return $total_occurrence;
     816    }
     817
     818    private function arrayUnique($array, $preserveKeys = false)
     819    {
     820        // Unique Array for return
     821        $arrayRewrite = array();
     822        // Array with the md5 hashes
     823        $arrayHashes = array();
     824        foreach ($array as $key => $item) {
     825            // Serialize the current element and create a md5 hash
     826            $hash = md5(serialize($item));
     827            // If the md5 didn't come up yet, add the element to
     828            // to arrayRewrite, otherwise drop it
     829            if (!isset($arrayHashes[$hash])) {
     830                // Save the current element hash
     831                $arrayHashes[$hash] = $hash;
     832                // Add element to the unique Array
     833                if ($preserveKeys) {
     834                    $arrayRewrite[$key] = $item;
     835                } else {
     836                    $arrayRewrite[] = $item;
     837                }
     838            }
     839        }
     840        return $arrayRewrite;
     841    }
     842
     843    public function analyzeKeywords()
     844    {
     845        $keywordsString = get_option('expresscurate_defined_tags');
     846        $blogKeywords = !empty($keywordsString) ? explode(', ', $keywordsString) : array();
     847
     848        $this->download();
     849        $this->parseDom();
     850        $this->parseArticle();
     851
     852        $title = $this->dom->getElementsByTagName('h1')->item(0)->nodeValue;
     853        $titleArray = preg_split('/\s+/u', $title);
     854
     855        $article = strip_tags($this->article->nodeValue);
     856        $articleFiltered = preg_replace('/\b(a|able|about|above|abroad|according|accordingly|across|actually|adj|after|afterwards|again|against|ago|ahead|ain\'t|all|allow|allows|almost|alone|along|alongside|already|also|although|always|am|amid|amidst|among|amongst|an|and|another|any|anybody|anyhow|anyone|anything|anyway|anyways|anywhere|apart|appear|appreciate|appropriate|are|aren\'t|around|as|a\'s|aside|ask|asking|associated|at|available|away|awfully|b|back|backward|backwards|be|became|because|become|becomes|becoming|been|before|beforehand|begin|behind|being|believe|below|beside|besides|best|better|between|beyond|both|brief|but|by|c|came|can|cannot|cant|can\'t|caption|cause|causes|certain|certainly|changes|clearly|c\'mon|co|co.|com|come|comes|concerning|consequently|consider|considering|contain|containing|contains|corresponding|could|couldn\'t|course|c\'s|currently|d|dare|daren\'t|definitely|described|despite|did|didn\'t|different|directly|do|does|doesn\'t|doing|done|don\'t|down|downwards|during|e|each|edu|eg|eight|eighty|either|else|elsewhere|end|ending|enough|entirely|especially|et|etc|even|ever|evermore|every|everybody|everyone|everything|everywhere|ex|exactly|example|except|f|fairly|far|farther|few|fewer|fifth|first|five|followed|following|follows|for|forever|former|formerly|forth|forward|found|four|from|further|furthermore|g|get|gets|getting|given|gives|go|goes|going|gone|got|gotten|greetings|h|had|hadn\'t|half|happens|hardly|has|hasn\'t|have|haven\'t|having|he|he\'d|he\'ll|hello|help|hence|her|here|hereafter|hereby|herein|here\'s|hereupon|hers|herself|he\'s|hi|him|himself|his|hither|hopefully|how|howbeit|however|hundred|i|i\'d|ie|if|ignored|i\'ll|i\'m|immediate|in|inasmuch|inc|inc.|indeed|indicate|indicated|indicates|inner|inside|insofar|instead|into|inward|is|isn\'t|it|it\'d|it\'ll|its|it\'s|itself|i\'ve|j|just|k|keep|keeps|kept|know|known|knows|l|last|lately|later|latter|latterly|least|less|lest|let|let\'s|like|liked|likely|likewise|little|look|looking|looks|low|lower|ltd|m|made|mainly|make|makes|many|may|maybe|mayn\'t|me|mean|meantime|meanwhile|merely|might|mightn\'t|mine|minus|miss|more|moreover|most|mostly|mr|mrs|much|must|mustn\'t|my|myself|n|name|namely|nd|near|nearly|necessary|need|needn\'t|needs|neither|never|neverf|neverless|nevertheless|new|next|nine|ninety|no|nobody|non|none|nonetheless|noone|no-one|nor|normally|not|nothing|notwithstanding|novel|now|nowhere|o|obviously|of|off|often|oh|ok|okay|old|on|once|one|ones|one\'s|only|onto|opposite|or|other|others|otherwise|ought|oughtn\'t|our|ours|ourselves|out|outside|over|overall|own|p|particular|particularly|past|per|perhaps|placed|please|plus|possible|presumably|probably|provided|provides|q|que|quite|qv|r|rather|rd|re|really|reasonably|recent|recently|regarding|regardless|regards|relatively|respectively|right|round|s|said|same|saw|say|saying|says|second|secondly|see|seeing|seem|seemed|seeming|seems|seen|self|selves|sensible|sent|serious|seriously|seven|several|shall|shan\'t|she|she\'d|she\'ll|she\'s|should|shouldn\'t|since|six|so|some|somebody|someday|somehow|someone|something|sometime|sometimes|somewhat|somewhere|soon|sorry|specified|specify|specifying|still|sub|such|sup|sure|t|take|taken|taking|tell|tends|th|than|thank|thanks|thanx|that|that\'ll|thats|that\'s|that\'ve|the|their|theirs|them|themselves|then|thence|there|thereafter|thereby|there\'d|therefore|therein|there\'ll|there\'re|theres|there\'s|thereupon|there\'ve|these|they|they\'d|they\'ll|they\'re|they\'ve|thing|things|think|third|thirty|this|thorough|thoroughly|those|though|three|through|throughout|thru|thus|till|to|together|too|took|toward|towards|tried|tries|truly|try|trying|t\'s|twice|two|u|un|under|underneath|undoing|unfortunately|unless|unlike|unlikely|until|unto|up|upon|upwards|us|use|used|useful|uses|using|usually|v|value|various|versus|very|via|viz|vs|w|want|wants|was|wasn\'t|way|we|we\'d|welcome|well|we\'ll|went|were|we\'re|weren\'t|we\'ve|what|whatever|what\'ll|what\'s|what\'ve|when|whence|whenever|where|whereafter|whereas|whereby|wherein|where\'s|whereupon|wherever|whether|which|whichever|while|whilst|whither|who|who\'d|whoever|whole|who\'ll|whom|whomever|who\'s|whose|why|will|willing|wish|with|within|without|wonder|won\'t|would|wouldn\'t|x|y|yes|yet|you|you\'d|you\'ll|your|you\'re|yours|yourself|yourselves|you\'ve|z|zero, replacement)\\b/', '', $article);
     857        $articleFiltered = preg_replace('/\p{P}+/u', ' ', $articleFiltered);
     858        $articleArray = preg_split('/\s+/u', $articleFiltered);
     859        $articleWordsCount = count($articleArray);
     860
     861        $result = array();
     862
     863        foreach ($blogKeywords as $keyword) {
     864            $count = 0;
     865            $inTitle = 'No';
     866
     867            if (in_array(mb_strtolower($keyword), $articleArray)) {
     868                $count++;
     869            }
     870            foreach ($titleArray as $titleWord) {
     871                if (mb_strtolower($titleWord) == mb_strtolower($keyword)) {
     872                    $inTitle = 'Yes';
     873                    break;
     874                }
     875            }
     876            if ($count !== 0) {
     877                $result[$keyword] = array('percent' => round($count / $articleWordsCount, 4), 'title' => $inTitle);
     878            }
     879        }
     880
     881        return $result;
     882    }
     883
     884    public function containsMedia()
     885    {
     886        $this->parseDom();
     887
     888        $imgTags = $this->xpath->query("//img");
     889        $img_array = array();
     890        foreach ($imgTags as $t) {
     891            $src = $t->getAttribute('src');
     892            $img_array[] = $src;
     893        }
     894        $obj = $this->xpath->query("//node()[(name()='iframe' or name()='video' or name()='source' or name()= 'object' or name()='embed') and (contains(@src,'youtube.com') or contains(@src ,'vimeo.com') or contains(@src,'youtu.be'))]");
     895        $videoArrays = array();
     896        foreach ($obj as $objs) {
     897            array_push($videoArrays, $objs->getAttribute('src'));
     898        }
     899        $mediaTags = array("images" => count($img_array), "videos" => count($videoArrays));
     900        return $mediaTags;
     901    }
    750902}
    751903
  • expresscurate/trunk/ExpressCurate_Keywords.php

    r1129694 r1137344  
    11<?php
     2
    23require_once(sprintf("%s/autoload.php", dirname(__FILE__)));
    34
  • expresscurate/trunk/ExpressCurate_Sitemap.php

    r1106118 r1137344  
    11<?php
     2
    23require_once(sprintf("%s/autoload.php", dirname(__FILE__)));
    3 /**
    4  * Created by PhpStorm.
    5  * User: armen
    6  * Date: 10/9/14
    7  * Time: 2:39 PM
     4
     5/*
     6  Author: ExpressCurate
     7  Author URI: http://www.expresscurate.com
     8  License: GPLv3 or later
     9  License URI: http://www.gnu.org/licenses/gpl.html
    810 */
     11 
    912class ExpressCurate_Sitemap
    1013{
  • expresscurate/trunk/ExpressCurate_Tags.php

    r1106118 r1137344  
    33require_once(sprintf("%s/autoload.php", dirname(__FILE__)));
    44
     5/*
     6  Author: ExpressCurate
     7  Author URI: http://www.expresscurate.com
     8  License: GPLv3 or later
     9  License URI: http://www.gnu.org/licenses/gpl.html
     10 */
     11
    512class Expresscurate_Tags
    613{
    7 
    814    private function checkOpenTag($matches)
    915    {
     
    4753        return preg_replace($spans, '$1', $html);
    4854    }
    49 
    50 
    5155}
  • expresscurate/trunk/autoload.php

    r1106118 r1137344  
    11<?php
     2
     3/*
     4  Author: ExpressCurate
     5  Author URI: http://www.expresscurate.com
     6  License: GPLv3 or later
     7  License URI: http://www.gnu.org/licenses/gpl.html
     8 */
     9
    210function expresscurate_autoload($className) {
    311    $classFile =  sprintf("%s/$className", dirname(__FILE__));
  • expresscurate/trunk/css/dialog-style-3.9.css

    r1106118 r1137344  
     1div[aria-describedby="expresscurate_clone_dialog"],
    12div[aria-describedby="expresscurate_dialog"]{
    23    padding: 0 !important;
     
    1213    z-index: 100090;
    1314}
     15div[aria-describedby="expresscurate_clone_dialog"] .ui-dialog-titlebar,
    1416div[aria-describedby="expresscurate_dialog"] .ui-dialog-titlebar{
    1517    padding: 0;
     
    2224    background-color: #222222;
    2325}
     26div[aria-describedby="expresscurate_clone_dialog"] .ui-dialog-title,
    2427div[aria-describedby="expresscurate_dialog"] .ui-dialog-title{
    2528    display: block;
     
    3538}
    3639
     40div[aria-describedby="expresscurate_clone_dialog"] .ui-button-icon-primary,
     41div[aria-describedby="expresscurate_clone_dialog"] .ui-dialog-titlebar-close span,
    3742div[aria-describedby="expresscurate_dialog"] .ui-button-icon-primary,
    3843div[aria-describedby="expresscurate_dialog"] .ui-dialog-titlebar-close span{
     
    4045}
    4146
     47div[aria-describedby="expresscurate_clone_dialog"] .ui-dialog-titlebar-close:before,
    4248div[aria-describedby="expresscurate_dialog"] .ui-dialog-titlebar-close:before{
    4349    line-height: 13px;
    4450}
     51div[aria-describedby="expresscurate_clone_dialog"] .ui-button.ui-dialog-titlebar-close,
    4552div[aria-describedby="expresscurate_dialog"] .ui-button.ui-dialog-titlebar-close{
    4653    padding: 0;
     
    5360    margin: 0 !important;
    5461}
     62div[aria-describedby="expresscurate_clone_dialog"] .ui-dialog-titlebar-close:before,
    5563div[aria-describedby="expresscurate_dialog"] .ui-dialog-titlebar-close:before{
    5664    line-height: 20px !important;
     
    5866    height: 30px !important;
    5967}
     68div[aria-describedby="expresscurate_clone_dialog"] .ui-button.ui-dialog-titlebar-close:hover,
    6069div[aria-describedby="expresscurate_dialog"] .ui-button.ui-dialog-titlebar-close:hover{
    6170    color: #9d9d9d;
    6271}
    6372
    64 #expresscurate_dialog {
     73.expresscurate_dialog {
    6574    padding: 0;
    6675    border:none;
     
    7685    display: none;
    7786}
     87#expresscurate_dialog_content_clone_editor{
     88    height: 190px;
     89    resize: none;
     90    max-height: 190px;
     91    overflow-y: scroll;
     92}
  • expresscurate/trunk/css/expresscurate.css

    r1129694 r1137344  
    801801        color:#303030;
    802802        position: relative;
    803 
    804803        box-sizing: border-box;
    805804        -moz-box-sizing: border-box;
     
    807806        width: 100%;
    808807    }
     808    .expresscurate_feedSettingsList li{
     809        line-height: 16px;
     810        height: 45px;
     811    }
     812
    809813    .expresscurate_feedSettingsList li:hover,
    810814    .expresscurate_URL li:hover,
     
    828832.expresscurate_feedSettingsList a{
    829833    width: 65%;
     834    margin-top: 5px;
     835    font-family: OpenSans-Regular, Verdana, Geneva, sans-serif;
     836}
     837.expresscurate_feedSettingsList a small {
     838    font-family: OpenSans-Light, Verdana, Geneva, sans-serif;
    830839}
    831840        @media (max-width: 720px){
     
    852861            width: 150px;
    853862            text-align: center;
     863            margin-top: 2px;
    854864        }
    855865        .expresscurate_URL .rssStatus{
     
    15971607}
    15981608
    1599 #expresscurate_dialog {
     1609.expresscurate_dialog {
    16001610    display: none;
    16011611}
     
    18561866}
    18571867
    1858 #expresscurate_dialog div.mce-toolbar-grp {
     1868.expresscurate_dialog div.mce-toolbar-grp {
    18591869    background-color: #dbdbdb !important;
    18601870}
     
    19171927}
    19181928.expresscurate_dialog .footer button.curate {
    1919     margin-top: 10px;
    19201929    border: 1px solid #27cfae;
    19211930    border-radius: 3px;
     
    26162625    content: ' index';
    26172626    margin-left: 25px;
     2627}
     2628.expresscurate_advancedSEO_widget input[id="expresscurate_advanced_seo_post_copy"] +label:after{
     2629    content: ' no';
     2630    margin-left: 59px;
     2631}
     2632.expresscurate_advancedSEO_widget input[id="expresscurate_advanced_seo_post_copy"]:checked +label:after{
     2633    content: ' yes';
     2634    margin-left: 33px;
    26182635}
    26192636.expresscurate_advancedSEO_widget input[type="checkbox"]:checked+label{
     
    35543571                display: none;
    35553572                right: 25px;
     3573                margin-top: 9px;
    35563574            }
    35573575        .expresscurate_feed_dashboard .expresscurate_feedSettingsList li:hover .close{
     
    36903708                border: solid 1px #25bfa1;
    36913709            }
     3710.expresscurate_controls .check.disabled{
     3711    background-position: -104px 6px;
     3712    cursor: default;
     3713    border: solid 1px #dddddd;
     3714}
    36923715.expresscurate_controls .check.active{
    36933716    background-position: -104px -75px;
     
    37193742                background-position: -50px 8px;
    37203743            }
     3744            .expresscurate_feed_list .feedListControls .pull.disabled:hover,
     3745            .expresscurate_feed_list .feedListControls .pull.disabled{
     3746                background: transparent !important;
     3747            }
    37213748            .expresscurate_feed_list .feedListControls .pull{
    3722                 background-position: -144px 6px;
     3749                /*background-position: -144px 6px;*/
    37233750                background-size: auto 99px;
    37243751                margin-right: 10px;
    37253752            }
     3753                .expresscurate_feed_list .feedListControls .pull .loading.expresscurate_startRotate{
     3754                    background: url("../images/refresh.svg") no-repeat transparent center;
     3755                    height: 100%;
     3756                    width: 100%;
     3757                    display: block;
     3758                    -webkit-animation: rotate 1.2s infinite linear;
     3759                    -moz-animation: rotate 1.2s infinite linear;
     3760                    -o-animation: rotate 1.2s infinite linear;
     3761                    animation: rotate 1.2s infinite linear;
     3762                }
     3763                @-webkit-keyframes rotate{
     3764                    from {-webkit-transform: rotate(0deg);}
     3765                    to   {-webkit-transform: rotate(-359deg);}
     3766                }
     3767                @-moz-keyframes rotate{
     3768                    from {-moz-transform: rotate(0deg);}
     3769                    to   {-moz-transform: rotate(-359deg);}
     3770                }
     3771                @-o-keyframes rotate{
     3772                    from {-o-transform: rotate(0deg);}
     3773                    to   {-o-transform: rotate(-359deg);}
     3774                }
     3775                @keyframes rotate{
     3776                    from {transform: rotate(0deg);}
     3777                    to   {transform: rotate(-359deg);}
     3778                }
    37263779            .expresscurate_feed_list .feedListControls .pullTime{
    37273780                background-image: none;
     
    37383791                -webkit-box-sizing: border-box;
    37393792                cursor: default;
     3793                border-color: #1cbb9f;
    37403794            }
    37413795                .expresscurate_feed_list .feedListControls .pullTime p{
     
    37493803                background: transparent;
    37503804                cursor: default;
     3805                border-color: #1cbb9f;
    37513806            }
    37523807            .expresscurate_controls .quotes.active:hover{
     
    37653820                border-color: #1cbb9f;
    37663821            }
    3767             .expresscurate_feed_list .feedListControls .pull.active:hover{
     3822            .expresscurate_feed_list .feedListControls .pull:hover{
    37683823                background-position: -144px -74px;
    37693824                background-color: #1cbb9f;
    3770                 border-color: #1cbb9f;
    37713825            }
    37723826
     
    37803834                background-position: -50px -25px;
    37813835            }
    3782             .expresscurate_feed_list .feedListControls .pull.active{
     3836            .expresscurate_feed_list .feedListControls .pull{
    37833837                background-position: -144px -33px;
     3838                border-color: #1cbb9f;
    37843839            }
    37853840
     
    49054960    display: block;
    49064961}
    4907 #wp-expresscurate_content_editor-editor-container .mce-container.mce-edit-area {
     4962#wp-expresscurate_dialog_content_clone_editor-editor-container .mce-container.mce-edit-area ,
     4963#wp-expresscurate_dialog_content_editor-editor-container .mce-container.mce-edit-area {
    49084964    max-height: 140px;
    49094965    overflow-y: auto;
  • expresscurate/trunk/js/Dialog.js

    r1129694 r1137344  
    100100                if (index < count && !shortPar) {
    101101                    generateTags(value);
    102                     tinyMCE.get('expresscurate_content_editor').execCommand('mceInsertContent', false, "<p>" + value + "<p>");
     102                    tinyMCE.get('expresscurate_dialog_content_editor').execCommand('mceInsertContent', false, "<p>" + value + "<p>");
    103103                }
    104104            }
     
    223223        }
    224224        generateTags(paragraph);
    225         tinyMCE.get('expresscurate_content_editor').execCommand('mceInsertContent', false, paragraph);
     225        tinyMCE.get('expresscurate_dialog_content_editor').execCommand('mceInsertContent', false, paragraph);
    226226    }
    227227
     
    232232
    233233    function clearExpresscurateForm() {
    234         var $dialog = $('#expresscurate_dialog');
     234        var $dialog = $('#expresscurate_dialog'),
     235            $imageCounter = $dialog.find('.imageCount');
    235236        $dialog.find('div.error').remove();
    236237        $dialog.find('div.updated').remove();
    237238        $dialog.find('ul').html('');
    238         $("#expresscurate_content_editor").val('');
     239        $dialog.find('#curated_title').val('');
     240        $imageCounter.text('0/0');
    239241        $('.content .img').attr('style', '').addClass("noimage");
    240242        $('.controls').hide();
    241243        $("#curated_paragraphs").empty();
    242         if (typeof(tinyMCE) === "object" && typeof(tinyMCE.execCommand) === "function" && tinyMCE.get('expresscurate_content_editor')) {
    243             tinyMCE.get('expresscurate_content_editor').setContent('');
     244        if (typeof(tinyMCE) === "object" && typeof(tinyMCE.execCommand) === "function" && tinyMCE.get('expresscurate_dialog_content_editor')) {
     245            tinyMCE.get('expresscurate_dialog_content_editor').setContent('');
     246            tinyMCE.get('expresscurate_dialog_content_clone_editor').setContent('');
    244247        }
    245248        $('#expresscurate_source').focus();
     
    311314    }
    312315
    313     function submitExpresscurateForm() {
    314         ExpressCurateUtils.track('/post/content-dialog/loadpage');
    315 
     316    function submitExpresscurateForm(clone) {
    316317        var $dialog = $('#expresscurate_dialog');
    317318        //remove autoComplete
     
    323324        var errorHTML = '',
    324325            notifHTML = '',
    325             $url = $('#expresscurate_post_form').find('input');
     326            $url = clone ? $('#expresscurate_post_form').find('#expresscurate_clone_source') : $('#expresscurate_post_form').find('#expresscurate_source');
    326327        $.ajax({
    327328            type: 'POST',
     
    340341            data: $url.serialize()
    341342        }).done(function (res) {
    342 
    343             var data = $.parseJSON(res);
    344             if (data) {
    345                 if (data.status === 'error') {
    346                     errorHTML = '<div class="error">' + data.error + '</div>';
     343                var data = $.parseJSON(res);
     344                if (data) {
     345                    if (data.status === 'error') {
     346                        errorHTML = '<div class="error">' + data.error + '</div>';
     347                        $('#expresscurate_post_form').before(errorHTML);
     348                        $("#expresscurate_loading").fadeOut('fast');
     349                    } else if (data.status === 'success') {
     350                        clearExpresscurateForm();
     351                        if (data.result.title && data.result.title.length > 0) {
     352                            $("#curated_title").val(data.result.title);
     353                        }
     354                        if (data.result.images.length > 0) {
     355                            errorHTML = exportAPICheckImages(data.result.images);
     356                        } else {
     357                            $("#expresscurate_loading").fadeOut('fast');
     358                        }
     359                        keywords = data.result.metas.keywords;
     360                        if (data.result.metas.keywords && data.result.metas.keywords.length > 0) {
     361                            displayCuratedTags(data.result.metas.keywords);
     362                        }
     363                        if (clone) {
     364                            if (data.result.paragraphs.length > 0) {
     365                                tinyMCE.get('expresscurate_dialog_content_clone_editor').execCommand('mceInsertContent', false, data.result.content);
     366                            }
     367                            ExpressCurateUtils.track('/post/content-dialog/clonepage');
     368                        } else {
     369                            $(".controls").show();
     370                            displaySpecials(data.result);
     371                            if (data.result.paragraphs.length > 0) {
     372                                $curatedParagraphs = data.result.paragraphs;
     373                                displayCuratedParagraphs(data.result.paragraphs, $("#expresscurate_autosummary").val(), false);
     374                            }
     375                            ExpressCurateUtils.track('/post/content-dialog/loadpage');
     376                        }
     377                        $('#expresscurate_source').focus();
     378                    }
     379                }
     380                else {
     381                    errorHTML = '<div class="error">Can\'t curate from this page</div>';
    347382                    $('#expresscurate_post_form').before(errorHTML);
    348383                    $("#expresscurate_loading").fadeOut('fast');
    349                 } else if (data.status === 'success') {
    350                     clearExpresscurateForm();
    351                     $(".controls").show();
    352                     if (data.result.title && data.result.title.length > 0) {
    353                         $("#curated_title").val(data.result.title);
    354                     }
    355                     if (data.result.images.length > 0) {
    356                         errorHTML = exportAPICheckImages(data.result.images);
    357                     } else {
    358                         $("#expresscurate_loading").fadeOut('fast');
    359                     }
    360                     if (data.result.metas.keywords && data.result.metas.keywords.length > 0) {
    361                         displayCuratedTags(data.result.metas.keywords);
    362                     }
    363                     keywords = data.result.metas.keywords;
    364                     displaySpecials(data.result);
    365 
    366                     if (data.result.paragraphs.length > 0) {
    367                         $curatedParagraphs = data.result.paragraphs;
    368                         displayCuratedParagraphs(data.result.paragraphs, $("#expresscurate_autosummary").val(), false);
    369                     }
    370                     $('#expresscurate_source').focus();
    371                 }
    372             } else {
    373                 errorHTML = '<div class="error">Can\'t curate from this page</div>';
    374                 $('#expresscurate_post_form').before(errorHTML);
    375                 $("#expresscurate_loading").fadeOut('fast');
    376             }
    377 
    378         });
     384                }
     385
     386            }
     387        );
    379388    }
    380389
     
    402411        });
    403412        $dialog.on('click', function (e) {
    404             if(!$(e.target).is('.autoComplete li')){
     413            if (!$(e.target).is('.autoComplete li')) {
    405414                $dialog.find('.autoComplete').remove();
    406415            }
     
    482491            }
    483492
    484             $("#expresscurate_content_editor").addClass("mceEditor");
     493            $("#expresscurate_dialog_content_editor").addClass("mceEditor");
    485494
    486495            var currentImage = 0;
     
    523532                openDialog();
    524533            });
    525             $("#expresscurate_insert").click(function () {
    526                 var ed = tinyMCE.activeEditor,
     534            $("#expresscurate_open-modal-clone").click(function (event) {
     535                event.preventDefault();
     536                openDialog(false, true);
     537            });
     538            $dialog.on('click', '#expresscurate_insert , #expresscurate_cloneInsert', function () {
     539                var clone = $(this).is('#expresscurate_cloneInsert') ? true : false,
     540                    ed = tinyMCE.activeEditor,
    527541                    highlightedElems = $(ed.getBody()).find('span.expresscurate_keywordsHighlight');
     542                if (clone) {
     543                    ExpressCurateUtils.track('/post/content-dialog/cloneintopost', true);
     544                } else {
     545                    ExpressCurateUtils.track('/post/content-dialog/curateintopost', true);
     546                }
    528547                if (highlightedElems.length > 0) {
    529548                    highlightedElems.each(function (index, val) {
     
    543562                ExpressCurateSourceCollection.addNew();
    544563                var html = "",
    545                     insiteHTML = '',
    546564                    bg = $('.img').css('background-image');
    547565
     
    550568                    html += '<img class="' + alignImg + ' ' + imgSize + '" src="' + bg + '" data-img-curated-from="' + sourceVal + '">'
    551569                }
    552                 if (tinyMCE.get('expresscurate_content_editor').getContent().length > 0) {
    553                     html += '<blockquote cite = "' + sourceVal + '">' + tinyMCE.get('expresscurate_content_editor').getContent() + '<br />';
    554                 }
    555                 html += insiteHTML;
     570
     571                if (clone) {
     572                    html += tinyMCE.get('expresscurate_dialog_content_clone_editor').getContent() + '<br />';
     573                } else {
     574                    html += '<blockquote cite = "' + sourceVal + '">' + tinyMCE.get('expresscurate_dialog_content_editor').getContent() + '<br />';
     575                }
     576
    556577                if (html.length > 0) {
    557578                    if (sourceVal.length > 0) {
     
    562583                        var title = $("#curated_title").val();
    563584                        domain = domain.match(/^(http|https)/) ? domain : 'http://' + domain;
     585
    564586                        if (domain) {
    565                             html += '<footer><p class="expresscurate_source">' + $("#expresscurate_from").val() + ' <cite><a class="expresscurated" rel="nofollow" data-curated-url="' + domain + '"  href = "' + domain + '">' + title + '</a></cite></p></footer><br/>';
     587                            if (clone) {
     588                                html += '<footer><p class="expresscurate_source">Originally published at <cite><a class="expresscurated" rel="nofollow" data-cloned-url="' +
     589                                domain + '"  href = "' + domain +
     590                                '"' + ($("#expresscurate_from_target").val() == 'on' ? ' target="_blank"' : '') + '>' +
     591                                title + '</a></cite></p></footer><br/>';
     592                            } else {
     593                                html += '<footer><p class="expresscurate_source">' + $("#expresscurate_from").val() +
     594                                ' <cite><a class="expresscurated" rel="nofollow" data-curated-url="' + domain + '"  href = "' + domain +
     595                                '"' + ($("#expresscurate_from_target").val() == 'on' ? ' target="_blank"' : '') + '>' +
     596                                title + '</a></cite></p></footer><br/>';
     597                            }
    566598                        }
    567599                    }
    568                     html += '</blockquote><br />';
     600
     601                    if (clone) {
     602                        var $canonicalURL = $('#expresscurate_advanced_seo_canonical_url'),
     603                            $noFollow = $('#expresscurate_advanced_seo_nofollow'),
     604                            $noIndex = $('#expresscurate_advanced_seo_noindex'),
     605                            $copyCheck = $('#expresscurate_advanced_seo_post_copy'),
     606                            $copyCheckVal = $('#expresscurate_advanced_seo_post_copy_value'),
     607                            $noIndexVal = $('#expresscurate_advanced_seo_noindex_value'),
     608                            $noFollowVal = $('#expresscurate_advanced_seo_nofollow_value'),
     609                            $copyControlWrap = $('#expresscurate_ClonePostWrap');
     610                        if ($canonicalURL.length) {
     611                            $copyControlWrap.removeClass('expresscurate_displayNone');
     612                            $copyCheckVal.val('on');
     613                            $canonicalURL.attr('value', domain).attr('readonly', true);
     614                            $noFollow.add($noIndex).attr('checked', false).attr('disabled', true);
     615                            $noFollowVal.add($noIndexVal).val('off');
     616                            $copyCheck.attr('checked', true).attr('disabled', false);
     617                        }
     618                    } else {
     619                        html += '</blockquote><br />';
     620                    }
    569621                    var $title = $('#titlewrap').find('#title');
    570622                    if ($title.val().length === 0) {
     
    577629                    return false;
    578630                }
    579                 ExpressCurateUtils.track('/post/content-dialog/curateintopost', true);
    580631            });
    581632        }
     
    583634        $('#expresscurate_submit').click(function () {
    584635            $("#expresscurate_loading").show();
    585             submitExpresscurateForm();
     636            submitExpresscurateForm(false);
    586637        });
    587638        $('#expresscurate_source').keypress(function (e) {
    588639            if (e.keyCode === 13 || e.keyCode === 40) {
    589640                $("#expresscurate_loading").show();
    590                 submitExpresscurateForm();
     641                submitExpresscurateForm(false);
     642                return false;
     643            }
     644        });
     645        $dialog.on('click', '#expresscurate_clone', function () {
     646            $("#expresscurate_loading").show();
     647            submitExpresscurateForm(true);
     648        });
     649        $('#expresscurate_clone_source').keypress(function (e) {
     650            if (e.keyCode === 13 || e.keyCode === 40) {
     651                $("#expresscurate_loading").show();
     652                submitExpresscurateForm(true);
    591653                return false;
    592654            }
     
    666728    }
    667729
    668     function openDialog(source) {
    669         var $dialog = $("#expresscurate_dialog");
     730    function openDialog(source, clone) {
     731        var $dialog = $("#expresscurate_dialog"),
     732            $load = $dialog.find('#expresscurate_submit'),
     733            $clone = $dialog.find('#expresscurate_clone'),
     734            $insert = $dialog.find('#expresscurate_insert'),
     735            $insertClone = $dialog.find('#expresscurate_cloneInsert'),
     736            $contenttextarea = $dialog.find('#expresscurate_dialog_content_editor_container'),
     737            $cloneContentTextarea = $dialog.find('#expresscurate_dialog_content_clone_editor_container'),
     738            $source = $dialog.find('#expresscurate_source'),
     739            $cloneSource = $dialog.find('#expresscurate_clone_source');
    670740        $dialog.dialog({
    671741            'dialogClass': 'wp-dialog',
     
    684754            'close': clearExpresscurateForm
    685755        });
     756        if (clone) {
     757            $load.add($insert).add($contenttextarea).add($source).addClass('expresscurate_displayNone');
     758            $clone.add($insertClone).add($cloneContentTextarea).add($cloneSource).removeClass('expresscurate_displayNone');
     759            tinyMCE.get('expresscurate_dialog_content_clone_editor').getBody().setAttribute('contenteditable', false);
     760            ExpressCurateUtils.track('/post/content-dialog/startclone');
     761        } else {
     762            $load.add($insert).add($contenttextarea).add($source).removeClass('expresscurate_displayNone');
     763            $clone.add($insertClone).add($cloneContentTextarea).add($cloneSource).addClass('expresscurate_displayNone');
     764            ExpressCurateUtils.track('/post/content-dialog/startcurate');
     765        }
    686766        $dialog.dialog('open');
    687 
    688         ExpressCurateUtils.track('/post/content-dialog/startcurate');
    689767    }
    690768
     
    710788        delCuratedTag: delCuratedTag
    711789    }
    712 })(window.jQuery);
     790})
     791(window.jQuery);
    713792
    714793ExpresscurateDialog.setup();
  • expresscurate/trunk/js/Utils.js

    r1129694 r1137344  
    1919            message.addClass('expresscurate_displayNone');
    2020            if (pageWithControls) {
    21                 $controls.removeClass('expresscurate_displayNone');
     21                $('.expresscurate_controls li.check').removeClass('disabled');
     22                //$('.expresscurate_controls li.layout').removeClass('expresscurate_displayNone');
    2223                ExpressCurateBookmarks.fixedMenu();
    2324            }
     
    2526            message.removeClass('expresscurate_displayNone');
    2627            if (pageWithControls) {
    27                 $('.expresscurate_controls li.check').removeClass('active');
    28                 $controls.addClass('expresscurate_displayNone');
     28                $controls.removeClass('active');
     29                //$('.expresscurate_controls li.layout').addClass('expresscurate_displayNone');
     30                $('.expresscurate_controls li.check').addClass('disabled');
     31                $('.expresscurate_controls li.pull').add($('.expresscurate_controls li.pullTime')).addClass('active');
    2932            }
    3033        }
  • expresscurate/trunk/js/feed/contentFeed.js

    r1129694 r1137344  
    7171
    7272    function pullFeedManualy() {
     73        var $loading = $feedControls.find('.loading'),
     74            $control = $('.feedListControls li.pull');
     75        $loading.addClass('expresscurate_startRotate');
     76        $control.addClass('disabled');
    7377        $.ajax({
    7478            type: 'POST',
    7579            url: 'admin-ajax.php?action=expresscurate_manual_pull_feed'
    7680        }).done(function (res) {
    77             //console.log(res);
     81            var data = $.parseJSON(res);
     82            if (data) {
     83                $.each(data.content, function (index, value) {
     84                    $("#expresscurate_feedBoxes").load("admin-ajax.php?action=expresscurate_show_content_feed_items #expresscurate_feedBoxes > li", function () {
     85                        $('.pullTime p').text('in ' + data.minutes_to_next_pull);
     86                        $masonryWrap.masonry('destroy').masonry({
     87                            itemSelector: '.expresscurate_masonryItem',
     88                            isResizable: true,
     89                            isAnimated: true,
     90                            columnWidth: '.expresscurate_masonryItem',
     91                            gutter: 10
     92                        });
     93                        ExpressCurateUtils.notDefinedMessage($notDefFeed, $feedBoxes.find(' > li'));
     94                    });
     95                });
     96            }
     97        }).always(function () {
     98            $loading.removeClass('expresscurate_startRotate');
     99            $control.removeClass('disabled');
    78100        });
    79101    }
     
    114136        });
    115137        /*pull*/
    116         $('.expresscurate_feed_list .pull').on('click',function(){
     138        $('.expresscurate_feed_list .pull').on('click', function () {
    117139            pullFeedManualy();
    118140        });
  • expresscurate/trunk/js/keywords/SEOControlCenter.js

    r1129694 r1137344  
    120120        $('html').on('click', function (e) {
    121121            if ($widgetWraper.length) {
    122                 var $suggestions=$widgetWraper.find('.suggestion li');
     122                var $suggestions = $widgetWraper.find('.suggestion li');
    123123                if ($(e.target).is('.suggestion li')) {
    124124                    var newKeyword = $(e.target).text();
     
    250250        });
    251251        $('#expresscurate_widget_wrapper .mark').on('click', function (e) {
    252                 ExpressCurateKeywords.markEditorKeywords();
     252            ExpressCurateKeywords.markEditorKeywords();
    253253        });
    254254
     
    269269            }
    270270        });
    271         $('.expresscurate_moveToAdvanced').on('click',function(){
     271        $('#expresscurate_advanced_seo_post_copy').on('change', function () {
     272            var $this = $(this),
     273                $hiddenInput = $this.parent().find('input[type=hidden]'),
     274                $canonicalURL = $('#expresscurate_advanced_seo_canonical_url'),
     275                $noFollow = $('#expresscurate_advanced_seo_nofollow'),
     276                $noIndex = $('#expresscurate_advanced_seo_noindex');
     277            if ($this.is(':checked')) {
     278                $hiddenInput.val('on');
     279                $canonicalURL.attr('readonly',true);
     280                $noFollow.add($noIndex).attr('disabled',true);
     281            } else {
     282                $hiddenInput.val('off');
     283                $canonicalURL.attr('readonly',false);
     284                $noFollow.add($noIndex).attr('disabled',false);
     285            }
     286        });
     287        $('.expresscurate_moveToAdvanced').on('click', function () {
    272288            $('html, body').animate({
    273289                scrollTop: $("#expresscurate_advanced_seo").offset().top - 40
  • expresscurate/trunk/js/sourceCollection.js

    r1106118 r1137344  
    8989                content = (($contentWrap.css("display") === "block") ? $contentWrap.val() : tinyMCE.get("content").getContent()),
    9090            /*find curated post's url*/
    91                 myRegExp = new RegExp('((cite=)|(data-curated-url=))["\']' + url + '["\' ]', 'gmi');
     91                myRegExp = new RegExp('((cite=)|(data-curated-url=)|(data-cloned-url=))["\']' + url + '["\' ]', 'gmi');
    9292
    9393            if (content.match(myRegExp)) {
  • expresscurate/trunk/readme.txt

    r1129694 r1137344  
    55Requires at least: 3.9
    66Tested up to: 4.1
    7 Stable tag: 2.0.10
     7Stable tag: 2.0.11
    88License: GPLv3 or later
    99License URI: http://www.gnu.org/licenses/gpl.html
     
    8181
    8282= How To Get Started =
    83 [Download ExpressCurate plugin](http://downloads.wordpress.org/plugin/expresscurate.2.0.10.zip "Your favorite content marketing tools") for WordPress. 
     83[Download ExpressCurate plugin](http://downloads.wordpress.org/plugin/expresscurate.2.0.11.zip "Your favorite content marketing tools") for WordPress. 
    8484You can also [download](http://www.expresscurate.com/p/products/wordpress-theme "Your favorite WordPress Theme") a **free** [ExpressCurate WordPress theme](http://www.expresscurate.com/p/products/wordpress-theme "Your favorite WordPress Theme"). It will give your curated content a modern online news look.
    8585
     
    129129== Changelog ==
    130130
     131= 2.0.11 =
     132* New Setting: Open Original Article Link in a New Window/Tab.
     133* Next Content Feed update time now available.
     134* Pull the Content Feed manually feature now available.
     135* Other miscellaneous bug fixes and improvements.
     136
    131137= 2.0.10 =
    132138* Embed function: you can now embed Facebook, Twitter, YouTube, and Vimeo. Use the "Embed" button, paste the embed code and get the social post in your article.
  • expresscurate/trunk/templates/advanced_seo_widget.php

    r1129694 r1137344  
    22global $post;
    33$sitemap = new ExpressCurate_Sitemap();
    4 $sitemapFrequencyArray =$sitemap->getSitemapFrequencyTagArray();
     4$sitemapFrequencyArray = $sitemap->getSitemapFrequencyTagArray();
     5
     6$postCopy = (get_post_meta($post->ID, '_expresscurate_advanced_seo_post_copy', true) == 'on') ? true : false;
    57?>
    68
    79<div class="container expresscurate_Styles expresscurate_advancedSEO_widget">
    8     <input type="hidden" name="expresscurate_post_analysis_notification" value="0" id="expresscurate_post_analysis_notification"/>
    9 <ul class="tabs">
    10     <li class="tab-link expresscurate_preventTextSelection green current" data-tab="tab-1">General</li>
    11     <li class="tab-link expresscurate_preventTextSelection red <?php if(get_option('expresscurate_sitemap_update_permission') == 'error') echo 'disabled';?>" data-tab="tab-2">Sitemap</li>
    12     <li class="tab-link expresscurate_preventTextSelection blue" data-tab="tab-3">Social</li>
    13     <li class="tab-link postAnalysisLink expresscurate_preventTextSelection yellow" data-tab="tab-4">Post Analysis</li>
    14 </ul>
    15 
    16 <div id="tab-1" class="tab-content current">
    17     <a name="expresscurate" id="expresscurate" xmlns="http://www.w3.org/1999/html"></a>
    18 
    19     <div id="expresscurate_advancedSEO_widget">
    20         <div class="info">
    21             <label for="expresscurate_advanced_seo_title" class="label">SEO Title</label>
    22         </div>
    23         <div class="value">
    24             <input id="expresscurate_advanced_seo_title" class="expresscurate_disableInputStyle" type="text"
    25                    name='expresscurate_advanced_seo_title'
    26                    value="<?php echo get_post_meta($post->ID, '_expresscurate_advanced_seo_title', true); ?>">
    27         </div>
    28         <div class="expresscurate_clear"></div>
    29         <div class="info">
    30             <label for="expresscurate_advanced_seo_canonical_url" class="label">Cannonical URL</label>
    31         </div>
    32         <div class="value">
    33             <input id="expresscurate_advanced_seo_canonical_url" class="expresscurate_disableInputStyle" type="text"
    34                    name='expresscurate_advanced_seo_canonical_url'
    35                    value="<?php echo get_post_meta($post->ID, '_expresscurate_advanced_seo_canonical_url', true); ?>">
    36         </div>
    37         <div class="expresscurate_clear"></div>
    38         <div class="info">
    39             <label class="robotsLabel">Robots must follow links </label>
    40         </div>
    41         <div class="value">
    42             <input class="expresscurate_displayNone" id="expresscurate_advanced_seo_nofollow" type='checkbox'
    43                    name='expresscurate_advanced_seo_nofollow'
    44                 <?php echo (get_post_meta($post->ID, '_expresscurate_advanced_seo_nofollow', true) == 'on' || !get_post_meta($post->ID, '_expresscurate_advanced_seo_nofollow', true)) ? 'checked' : '' ?>>
    45             <label class="expresscurate_preventTextSelection" for="expresscurate_advanced_seo_nofollow"></label>
    46             <input type="hidden" id="expresscurate_advanced_seo_nofollow_value" name="expresscurate_advanced_seo_nofollow_value"  value="<?php echo (get_post_meta($post->ID, '_expresscurate_advanced_seo_nofollow', true))?get_post_meta($post->ID, '_expresscurate_advanced_seo_nofollow', true):"on"; ?>">
    47         </div>
    48         <div class="expresscurate_clear"></div>
    49         <div class="info">
    50             <label class="robotsLabel">Robots must index this page </label>
    51         </div>
    52         <div class="value">
    53             <input class="expresscurate_displayNone" id="expresscurate_advanced_seo_noindex" type='checkbox'
    54                    name='expresscurate_advanced_seo_noindex'
    55                 <?php echo (get_post_meta($post->ID, '_expresscurate_advanced_seo_noindex', true) == 'on' || !get_post_meta($post->ID, '_expresscurate_advanced_seo_nofollow', true)) ? 'checked' : '' ?>>
    56             <label class="expresscurate_preventTextSelection" for="expresscurate_advanced_seo_noindex"></label>
    57             <input type="hidden" id="expresscurate_advanced_seo_noindex_value" name="expresscurate_advanced_seo_noindex_value" value="<?php echo (get_post_meta($post->ID, '_expresscurate_advanced_seo_noindex', true))?get_post_meta($post->ID, '_expresscurate_advanced_seo_noindex', true):"on"; ?>">
    58         </div>
    59         <div class="expresscurate_clear"></div>
    60     </div>
    61 </div>
    62 <div id="tab-2" class="tab-content">
    63     <div id="expresscurate_sitemap_widget">
    64         <ul class="expresscurate_sitemap_widget">
    65             <li>
     10    <input type="hidden" name="expresscurate_post_analysis_notification" value="0"
     11           id="expresscurate_post_analysis_notification"/>
     12    <ul class="tabs">
     13        <li class="tab-link expresscurate_preventTextSelection green current" data-tab="tab-1">General</li>
     14        <li class="tab-link expresscurate_preventTextSelection red <?php if (get_option('expresscurate_sitemap_update_permission') == 'error') echo 'disabled'; ?>"
     15            data-tab="tab-2">Sitemap
     16        </li>
     17        <li class="tab-link expresscurate_preventTextSelection blue" data-tab="tab-3">Social</li>
     18        <li class="tab-link postAnalysisLink expresscurate_preventTextSelection yellow" data-tab="tab-4">Post Analysis
     19        </li>
     20    </ul>
     21
     22    <div id="tab-1" class="tab-content current">
     23        <a name="expresscurate" id="expresscurate" xmlns="http://www.w3.org/1999/html"></a>
     24
     25        <div id="expresscurate_advancedSEO_widget">
     26            <div id="expresscurate_ClonePostWrap" class="<?php if(!$postCopy) {echo 'expresscurate_displayNone';} ?>">
    6627                <div class="info">
    67                     <span class="label">Configure Sitemap Manually</span>
     28                    <label for="expresscurate_advanced_seo_canonical_url" class="label">Content cloned</label>
    6829                </div>
    6930                <div class="value">
    70                     <input class="expresscurate_displayNone" type="checkbox"
    71                            id="expresscurate_sitemap_post_configure_manually"
    72                            name="expresscurate_sitemap_post_configure_manually" <?php if (get_post_meta($post->ID, '_expresscurate_sitemap_post_configure_manually', true) == 'on') echo 'checked'; ?>>
    73                     <label for="expresscurate_sitemap_post_configure_manually"></label>
     31                    <input class="expresscurate_displayNone" id="expresscurate_advanced_seo_post_copy"
     32                           type='checkbox' <?php if(!$postCopy) {
     33                        echo 'disabled="disabled"';
     34                    } ?>
     35                           name='expresscurate_advanced_seo_post_copy'
     36                        <?php echo ($postCopy) ? 'checked' : '' ?>>
     37                    <label class="expresscurate_preventTextSelection" for="expresscurate_advanced_seo_post_copy"></label>
     38                    <input type="hidden" id="expresscurate_advanced_seo_post_copy_value"
     39                           name="expresscurate_advanced_seo_post_copy_value"
     40                           value="<?php echo ($postCopy) ? "on" : "off"; ?>">
    7441                </div>
    75                 <div class="expresscurate_clear"></div>
    76             </li>
    77             <li class="hiddenOptions <?php if (get_post_meta($post->ID, '_expresscurate_sitemap_post_configure_manually', true) != 'on') echo 'expresscurate_displayNone'; ?>">
    78                 <ul>
    79                     <li>
    80                         <div class="info">
    81                             <span class="label">Exclude from sitemap</span>
    82                         </div>
    83                         <div class="value">
    84                             <input class="expresscurate_displayNone" type="checkbox"
    85                                    id="expresscurate_sitemap_post_exclude_from_sitemap"
    86                                    name="expresscurate_sitemap_post_exclude_from_sitemap"  <?php if (get_post_meta($post->ID, '_expresscurate_sitemap_post_exclude_from_sitemap', true) == 'on') echo 'checked'; ?>>
    87                             <label for="expresscurate_sitemap_post_exclude_from_sitemap"></label>
    88                         </div>
    89                         <div class="expresscurate_clear"></div>
    90                     </li>
    91 
    92                     <ul class="sitemapOption <?php if (get_post_meta($post->ID, '_expresscurate_sitemap_post_exclude_from_sitemap', true) == 'on') echo 'expresscurate_displayNone'; ?>">
     42            </div>
     43            <div class="info">
     44                <label for="expresscurate_advanced_seo_title" class="label">SEO Title</label>
     45            </div>
     46            <div class="value">
     47                <input id="expresscurate_advanced_seo_title" class="expresscurate_disableInputStyle" type="text"
     48                       name='expresscurate_advanced_seo_title'
     49                       value="<?php echo get_post_meta($post->ID, '_expresscurate_advanced_seo_title', true); ?>">
     50            </div>
     51            <div class="expresscurate_clear"></div>
     52            <div class="info">
     53                <label for="expresscurate_advanced_seo_canonical_url" class="label">Canonical URL</label>
     54            </div>
     55            <div class="value">
     56                <input id="expresscurate_advanced_seo_canonical_url" class="expresscurate_disableInputStyle" type="text"
     57                    <?php if ($postCopy) {
     58                        echo 'readonly="true"';
     59                    } ?>
     60                       name='expresscurate_advanced_seo_canonical_url'
     61                       value="<?php echo get_post_meta($post->ID, '_expresscurate_advanced_seo_canonical_url', true); ?>">
     62            </div>
     63            <div class="expresscurate_clear"></div>
     64            <div class="info">
     65                <label class="robotsLabel">Robots must follow links </label>
     66            </div>
     67            <div class="value">
     68                <input class="expresscurate_displayNone" id="expresscurate_advanced_seo_nofollow" type='checkbox'
     69                    <?php if ($postCopy) {
     70                        echo 'disabled="disabled"';
     71                    } ?>
     72                       name='expresscurate_advanced_seo_nofollow'
     73                    <?php echo (get_post_meta($post->ID, '_expresscurate_advanced_seo_nofollow', true) == 'on' || !get_post_meta($post->ID, '_expresscurate_advanced_seo_nofollow', true)) ? 'checked' : '' ?>>
     74                <label class="expresscurate_preventTextSelection" for="expresscurate_advanced_seo_nofollow"></label>
     75                <input type="hidden" id="expresscurate_advanced_seo_nofollow_value"
     76                       name="expresscurate_advanced_seo_nofollow_value"
     77                       value="<?php echo (get_post_meta($post->ID, '_expresscurate_advanced_seo_nofollow', true)) ? get_post_meta($post->ID, '_expresscurate_advanced_seo_nofollow', true) : "on"; ?>">
     78            </div>
     79            <div class="expresscurate_clear"></div>
     80            <div class="info">
     81                <label class="robotsLabel">Robots must index this page </label>
     82            </div>
     83            <div class="value">
     84                <input class="expresscurate_displayNone" id="expresscurate_advanced_seo_noindex" type='checkbox'
     85                    <?php if ($postCopy) {
     86                        echo 'disabled="disabled"';
     87                    } ?>
     88                       name='expresscurate_advanced_seo_noindex'
     89                    <?php echo (get_post_meta($post->ID, '_expresscurate_advanced_seo_noindex', true) == 'on' || !get_post_meta($post->ID, '_expresscurate_advanced_seo_nofollow', true)) ? 'checked' : '' ?>>
     90                <label class="expresscurate_preventTextSelection" for="expresscurate_advanced_seo_noindex"></label>
     91                <input type="hidden" id="expresscurate_advanced_seo_noindex_value"
     92                       name="expresscurate_advanced_seo_noindex_value"
     93                       value="<?php echo (get_post_meta($post->ID, '_expresscurate_advanced_seo_noindex', true)) ? get_post_meta($post->ID, '_expresscurate_advanced_seo_noindex', true) : "on"; ?>">
     94            </div>
     95            <div class="expresscurate_clear"></div>
     96        </div>
     97    </div>
     98    <div id="tab-2" class="tab-content">
     99        <div id="expresscurate_sitemap_widget">
     100            <ul class="expresscurate_sitemap_widget">
     101                <li>
     102                    <div class="info">
     103                        <span class="label">Configure Sitemap Manually</span>
     104                    </div>
     105                    <div class="value">
     106                        <input class="expresscurate_displayNone" type="checkbox"
     107                               id="expresscurate_sitemap_post_configure_manually"
     108                               name="expresscurate_sitemap_post_configure_manually" <?php if (get_post_meta($post->ID, '_expresscurate_sitemap_post_configure_manually', true) == 'on') echo 'checked'; ?>>
     109                        <label for="expresscurate_sitemap_post_configure_manually"></label>
     110                    </div>
     111                    <div class="expresscurate_clear"></div>
     112                </li>
     113                <li class="hiddenOptions <?php if (get_post_meta($post->ID, '_expresscurate_sitemap_post_configure_manually', true) != 'on') echo 'expresscurate_displayNone'; ?>">
     114                    <ul>
    93115                        <li>
    94116                            <div class="info">
    95                                 <span class="label">Sitemap frequency</span>
    96                                 <span class="gray-italic desc">Please select frequency for posts in sitemap</span>
     117                                <span class="label">Exclude from sitemap</span>
    97118                            </div>
    98119                            <div class="value">
    99                                 <?php $expresscurate_sitemap_post_frequency = get_post_meta($post->ID, '_expresscurate_sitemap_post_frequency', true) ?>
    100                                 <select name="expresscurate_sitemap_post_frequency"
    101                                         id="expresscurate_sitemap_post_frequency">
    102                                     <?php foreach($sitemapFrequencyArray as $key=>$val) {
    103                                         echo '<option value="' . $key . '"';
    104                                         if ($key == $expresscurate_sitemap_post_frequency) {
    105                                             echo ' selected="selected"';
    106                                         }
    107                                         echo '>' . $val . '</option>';
    108                                     }?>
    109                                 </select>
     120                                <input class="expresscurate_displayNone" type="checkbox"
     121                                       id="expresscurate_sitemap_post_exclude_from_sitemap"
     122                                       name="expresscurate_sitemap_post_exclude_from_sitemap"  <?php if (get_post_meta($post->ID, '_expresscurate_sitemap_post_exclude_from_sitemap', true) == 'on') echo 'checked'; ?>>
     123                                <label for="expresscurate_sitemap_post_exclude_from_sitemap"></label>
    110124                            </div>
    111125                            <div class="expresscurate_clear"></div>
    112126                        </li>
    113                         <li>
    114                             <div class="info">
    115                                 <span class="label">Sitemap priority</span>
    116                                 <span class="gray-italic desc">Please select priority for posts in sitemap</span>
    117                             </div>
    118                             <div class="value">
    119                                 <?php $expresscurate_sitemap_post_priority = get_post_meta($post->ID, '_expresscurate_sitemap_post_priority', true) ?>
    120                                 <select name="expresscurate_sitemap_post_priority"
    121                                         id="expresscurate_sitemap_post_priority">
    122                                     <?php for($i=0.1; $i<=1; $i=$i+0.1) {
    123                                         echo '<option value="'.$i.'"';
    124                                         if ($i == $expresscurate_sitemap_post_priority) {
    125                                             echo ' selected="selected"';
    126                                         }
    127                                         echo '>'.$i.'</option>';
    128                                     }?>
    129                                 </select>
    130                             </div>
    131                             <div class="expresscurate_clear"></div>
    132                         </li>
     127
     128                        <ul class="sitemapOption <?php if (get_post_meta($post->ID, '_expresscurate_sitemap_post_exclude_from_sitemap', true) == 'on') echo 'expresscurate_displayNone'; ?>">
     129                            <li>
     130                                <div class="info">
     131                                    <span class="label">Sitemap frequency</span>
     132                                    <span class="gray-italic desc">Please select frequency for posts in sitemap</span>
     133                                </div>
     134                                <div class="value">
     135                                    <?php $expresscurate_sitemap_post_frequency = get_post_meta($post->ID, '_expresscurate_sitemap_post_frequency', true) ?>
     136                                    <select name="expresscurate_sitemap_post_frequency"
     137                                            id="expresscurate_sitemap_post_frequency">
     138                                        <?php foreach ($sitemapFrequencyArray as $key => $val) {
     139                                            echo '<option value="' . $key . '"';
     140                                            if ($key == $expresscurate_sitemap_post_frequency) {
     141                                                echo ' selected="selected"';
     142                                            }
     143                                            echo '>' . $val . '</option>';
     144                                        } ?>
     145                                    </select>
     146                                </div>
     147                                <div class="expresscurate_clear"></div>
     148                            </li>
     149                            <li>
     150                                <div class="info">
     151                                    <span class="label">Sitemap priority</span>
     152                                    <span class="gray-italic desc">Please select priority for posts in sitemap</span>
     153                                </div>
     154                                <div class="value">
     155                                    <?php $expresscurate_sitemap_post_priority = get_post_meta($post->ID, '_expresscurate_sitemap_post_priority', true) ?>
     156                                    <select name="expresscurate_sitemap_post_priority"
     157                                            id="expresscurate_sitemap_post_priority">
     158                                        <?php for ($i = 0.1; $i <= 1; $i = $i + 0.1) {
     159                                            echo '<option value="' . $i . '"';
     160                                            if ($i == $expresscurate_sitemap_post_priority) {
     161                                                echo ' selected="selected"';
     162                                            }
     163                                            echo '>' . $i . '</option>';
     164                                        } ?>
     165                                    </select>
     166                                </div>
     167                                <div class="expresscurate_clear"></div>
     168                            </li>
     169                        </ul>
    133170                    </ul>
    134                 </ul>
    135             </li>
    136         </ul>
     171                </li>
     172            </ul>
     173        </div>
     174    </div>
     175    <div id="tab-3" class="tab-content">
     176        <div id="expresscurate_social_widget">
     177            <div class="info">
     178                <label for="expresscurate_advanced_seo_social_title" class="label">Title</label>
     179            </div>
     180            <div class="value">
     181                <input id="expresscurate_advanced_seo_social_title" class="expresscurate_disableInputStyle" type="text"
     182                       name='expresscurate_advanced_seo_social_title'
     183                       value="<?php echo get_post_meta($post->ID, '_expresscurate_advanced_seo_social_title', true); ?>">
     184            </div>
     185            <div class="expresscurate_clear"></div>
     186            <div class="info">
     187                <label for="expresscurate_advanced_seo_social_shortdesc" class="label">Short Description</label>
     188            </div>
     189            <div class="value">
     190                <input id="expresscurate_advanced_seo_social_shortdesc" class="expresscurate_disableInputStyle"
     191                       type="text"
     192                       name='expresscurate_advanced_seo_social_shortdesc'
     193                       value="<?php echo get_post_meta($post->ID, '_expresscurate_advanced_seo_social_shortdesc', true); ?>">
     194            </div>
     195            <div class="expresscurate_clear"></div>
     196            <div class="info">
     197                <label for="expresscurate_advanced_seo_social_desc" class="label">Description</label>
     198            </div>
     199            <div class="value">
     200                <input id="expresscurate_advanced_seo_social_desc" class="expresscurate_disableInputStyle" type="text"
     201                       name='expresscurate_advanced_seo_social_desc'
     202                       value="<?php echo get_post_meta($post->ID, '_expresscurate_advanced_seo_social_desc', true); ?>">
     203            </div>
     204            <div class="expresscurate_clear"></div>
     205        </div>
     206    </div>
     207    <div id="tab-4" class="tab-content postAnalysisTab">
     208
    137209    </div>
    138210</div>
    139 <div id="tab-3" class="tab-content">
    140     <div id="expresscurate_social_widget">
    141         <div class="info">
    142             <label for="expresscurate_advanced_seo_social_title" class="label">Title</label>
    143         </div>
    144         <div class="value">
    145             <input id="expresscurate_advanced_seo_social_title" class="expresscurate_disableInputStyle" type="text"
    146                    name='expresscurate_advanced_seo_social_title'
    147                    value="<?php echo get_post_meta($post->ID, '_expresscurate_advanced_seo_social_title', true); ?>">
    148         </div>
    149         <div class="expresscurate_clear"></div>
    150         <div class="info">
    151             <label for="expresscurate_advanced_seo_social_shortdesc" class="label">Short Description</label>
    152         </div>
    153         <div class="value">
    154             <input id="expresscurate_advanced_seo_social_shortdesc" class="expresscurate_disableInputStyle" type="text"
    155                    name='expresscurate_advanced_seo_social_shortdesc'
    156                    value="<?php echo get_post_meta($post->ID, '_expresscurate_advanced_seo_social_shortdesc', true); ?>">
    157         </div>
    158         <div class="expresscurate_clear"></div>
    159         <div class="info">
    160             <label for="expresscurate_advanced_seo_social_desc" class="label">Description</label>
    161         </div>
    162         <div class="value">
    163             <input id="expresscurate_advanced_seo_social_desc" class="expresscurate_disableInputStyle" type="text"
    164                    name='expresscurate_advanced_seo_social_desc'
    165                    value="<?php echo get_post_meta($post->ID, '_expresscurate_advanced_seo_social_desc', true); ?>">
    166         </div>
    167         <div class="expresscurate_clear"></div>
    168     </div>
    169 </div>
    170 <div id="tab-4" class="tab-content postAnalysisTab">
    171 
    172 </div>
    173 </div>
    174 
     211
  • expresscurate/trunk/templates/bookmarks.php

    r1129694 r1137344  
    1212    } ?>">
    1313    <div class="expresscurate_headBorderBottom expresscurate_OpenSansRegular">
    14         <a href="admin.php?page=expresscurate&type=keywords" class="expresscurate_writeUs">Suggestions? <span>Submit here!</span></a>
     14        <a href="admin.php?page=expresscurate_support" class="expresscurate_writeUs">Suggestions? <span>Submit here!</span></a>
    1515
    1616        <h2>Bookmarks</h2>
     
    2121        </div>
    2222        <div class="controlsWrap">
    23             <ul class="bookmarkListControls expresscurate_preventTextSelection expresscurate_controls expresscurate_displayNone">
     23            <ul class="bookmarkListControls expresscurate_preventTextSelection expresscurate_controls">
    2424                <li class="check">
    2525                    <span class="tooltip">select / deselect</span>
  • expresscurate/trunk/templates/dashboard.php

    r1129694 r1137344  
    2020<div class="expresscurate_blocks expresscurate_Styles wrap">
    2121    <div class="expresscurate_headBorderBottom expresscurate_OpenSansRegular">
    22         <a href="admin.php?page=expresscurate&type=keywords" class="expresscurate_writeUs">Suggestions? <span>Submit here!</span></a>
     22        <a href="admin.php?page=expresscurate_support" class="expresscurate_writeUs">Suggestions? <span>Submit here!</span></a>
    2323
    2424        <h2>ExpressCurate</h2>
  • expresscurate/trunk/templates/dialog.php

    r1129694 r1137344  
    11<?php
    22$settings = array('wpautop' => false, 'media_buttons' => false, 'teeny' => true, 'tinymce' => true, 'quicktags' => false);
     3$settingsClone = array('wpautop' => false, 'media_buttons' => false, 'teeny' => true, 'tinymce' => true, 'quicktags' => false );
    34?>
    45<div>
    5   <div class="content_editor expresscurate_Styles" id ="expresscurate_post_form">
    6     <div class="main">
    7       <div class="header">
    8         <div class="addressbar">
    9           <input type="text" placeholder="<?php echo __('Insert source URL to start', ExpressCurate_Actions::PLUGIN_FOLDER) ?>" id="expresscurate_source" name="expresscurate_source" value="<?php echo @get_post_meta($post->ID, 'expresscurate_source', true); ?>">
    10           <button class="load"  id="expresscurate_submit">Load</button>
    11         </div>
    12         <div class="title">
    13           <input type="text" value="" id="curated_title">
    14         </div>
    15       </div>
    16       <div class="content">
    17         <div class="hidden">
    18           <ul id="curated_images">
    19           </ul>
    20         </div>
    21         <div class="left imgContainer">
    22             <div class="imgIcons">
    23                 <div class="sizeX active">
    24                     <div class="tooltipWrap">
    25                         <span>Large size</span>
     6    <div class="content_editor expresscurate_Styles" id="expresscurate_post_form">
     7        <div class="main">
     8            <div class="header">
     9                <div class="addressbar">
     10                    <input type="text" class="expresscurate_load"
     11                           placeholder="<?php echo __('Insert source URL to start', ExpressCurate_Actions::PLUGIN_FOLDER) ?>"
     12                           id="expresscurate_source" name="expresscurate_source"
     13                           value="<?php echo @get_post_meta($post->ID, 'expresscurate_source', true); ?>">
     14                    <input type="text" class="expresscurate_load"
     15                           placeholder="<?php echo __('Insert source URL to start', ExpressCurate_Actions::PLUGIN_FOLDER) ?>"
     16                           id="expresscurate_clone_source" name="expresscurate_source"
     17                           value="<?php echo @get_post_meta($post->ID, 'expresscurate_source', true); ?>">
     18                    <button class="load" id="expresscurate_submit">Load</button>
     19                    <button class="load expresscurate_displayNone" id="expresscurate_clone">Clone</button>
     20                </div>
     21                <div class="title">
     22                    <input type="text" value="" id="curated_title">
     23                </div>
     24            </div>
     25            <div class="content">
     26                <div class="hidden">
     27                    <ul id="curated_images">
     28                    </ul>
     29                </div>
     30                <div class="left imgContainer">
     31                    <div class="imgIcons">
     32                        <div class="sizeX active">
     33                            <div class="tooltipWrap">
     34                                <span>Large size</span>
     35                            </div>
     36                        </div>
     37                        <div class="sizeM">
     38                            <div class="tooltipWrap">
     39                                <span>Middle size</span>
     40                            </div>
     41                        </div>
     42                        <div class="sizeS">
     43                            <div class="tooltipWrap">
     44                                <span>Small size</span>
     45                            </div>
     46                        </div>
     47
     48                        <div class="prevImg prev">
     49                            <div class="tooltipWrap">
     50                                <span>Previous</span>
     51                            </div>
     52                        </div>
     53                        <div class="nextImg next">
     54                            <div class="tooltipWrap">
     55                                <span>Next</span>
     56                            </div>
     57                        </div>
     58
     59                        <div class="alignleft imgAlign">
     60                            <div class="tooltipWrap">
     61                                <span>Align left</span>
     62                            </div>
     63                        </div>
     64                        <div class="alignnone active imgAlign">
     65                            <div class="tooltipWrap">
     66                                <span>Fit to center</span>
     67                            </div>
     68                        </div>
     69                        <div class="alignright imgAlign">
     70                            <div class="tooltipWrap">
     71                                <span>Align right</span>
     72                            </div>
     73                        </div>
     74                    </div>
     75                    <div class="img noimage">
     76                        <span class="imageCount expresscurate_displayNone"></span>
    2677                    </div>
    2778                </div>
    28                 <div class="sizeM">
    29                     <div class="tooltipWrap">
    30                         <span>Middle size</span>
     79                <div class="editor right">
     80                    <div id="expresscurate_dialog_content_editor_container">
     81                        <?php wp_editor('', 'expresscurate_dialog_content_editor', $settings); ?>
    3182                    </div>
    32                 </div>
    33                 <div class="sizeS">
    34                     <div class="tooltipWrap">
    35                         <span>Small size</span>
     83                    <div id="expresscurate_dialog_content_clone_editor_container" class="expresscurate_displayNone">
     84                        <?php wp_editor('', 'expresscurate_dialog_content_clone_editor', $settingsClone); ?>
    3685                    </div>
    37                 </div>
    38 
    39                 <div class="prevImg prev">
    40                     <div class="tooltipWrap">
    41                         <span>Previous</span>
    42                     </div>
    43                 </div>
    44                 <div class="nextImg next">
    45                     <div class="tooltipWrap">
    46                         <span>Next</span>
    47                     </div>
    48                 </div>
    49 
    50                 <div class="alignleft imgAlign">
    51                     <div class="tooltipWrap">
    52                         <span>Align left</span>
    53                     </div>
    54                 </div>
    55                 <div class="alignnone active imgAlign">
    56                     <div class="tooltipWrap">
    57                         <span>Fit to center</span>
    58                     </div>
    59                 </div>
    60                 <div class="alignright imgAlign">
    61                     <div class="tooltipWrap">
    62                         <span>Align right</span>
    63                     </div>
     86                    <div class="clear"></div>
    6487                </div>
    6588            </div>
    66             <div class="img noimage">
    67                 <span class="imageCount expresscurate_displayNone"></span>
     89            <div class="clear"></div>
     90            <div class="controls hidden">
     91                <ul class="expresscurate_preventTextSelection tags" id="expresscurate_special">
     92
     93                </ul>
     94                <div class="clear"></div>
     95                <div id="expresscurate_slider" class="slide_container">
     96                    <div class="slider">
     97                        <ul class="paragraphs_preview" id="curated_paragraphs">
     98                        </ul>
     99                    </div>
     100                    <div class="prevSlide inactiveButton"></div>
     101                    <div class="nextSlide inactiveButton"></div>
     102                </div>
     103                <div class="clear"></div>
    68104            </div>
    69105        </div>
    70         <div class="editor right">
    71           <?php wp_editor('', 'expresscurate_content_editor', $settings); ?>
    72 
    73           <div class="clear"></div>
     106        <div class="footer">
     107            <input type="hidden" value="<?php echo get_option('expresscurate_curated_text', 'Curated from'); ?>"
     108                   id="expresscurate_from" name="expresscurate_from"/>
     109            <input type="hidden" value="<?php echo get_option('expresscurate_curated_link_target', 'on'); ?>"
     110                   id="expresscurate_from_target" name="expresscurate_from_target"/>
     111            <input type="hidden" value="<?php echo get_option('expresscurate_autosummary', 5); ?>"
     112                   id="expresscurate_autosummary" name="expresscurate_autosummary"/>
     113            <ul class="labels" id="curated_tags">
     114                <li class="markButton expresscurate_displayNone expresscurate_preventTextSelection">
     115                    <span>mark keywords</span></li>
     116            </ul>
     117            <div class="clear"></div>
     118            <button class="curate right" id="expresscurate_insert"
     119                    onclick="return false;"><?php echo __('Curate into post', ExpressCurate_Actions::PLUGIN_FOLDER) ?></button>
     120            <button class="curate right expresscurate_displayNone" id="expresscurate_cloneInsert"
     121                    onclick="return false;"><?php echo __('Clone Post', ExpressCurate_Actions::PLUGIN_FOLDER) ?></button>
     122            <div class="clear"></div>
    74123        </div>
    75       </div>
    76       <div class="clear"></div>
    77       <div class="controls hidden">
    78         <ul class="expresscurate_preventTextSelection tags" id="expresscurate_special">
    79 
    80         </ul>
    81         <div class="clear"></div>
    82           <div id="expresscurate_slider" class="slide_container">
    83               <div class="slider">
    84                   <ul class="paragraphs_preview" id="curated_paragraphs">
    85                   </ul>
    86               </div>
    87               <div class="prevSlide inactiveButton"></div>
    88               <div class="nextSlide inactiveButton"></div>
    89           </div>
    90         <div class="clear"></div>
    91       </div>
    92124    </div>
    93     <div class="footer">
    94       <input type="hidden" value="<?php echo get_option('expresscurate_curated_text', 'Curated from'); ?>" id="expresscurate_from" name="expresscurate_from"/>
    95       <input type="hidden" value="<?php echo get_option('expresscurate_autosummary', 5); ?>" id="expresscurate_autosummary" name="expresscurate_autosummary"/>
    96       <ul class="labels" id="curated_tags">
    97           <li class="markButton expresscurate_displayNone expresscurate_preventTextSelection"><span>mark keywords</span></li>
    98       </ul>
    99       <div class="clear"></div>
    100       <button class="curate right" id="expresscurate_insert" onclick="return false;"><?php echo __('Curate into post', ExpressCurate_Actions::PLUGIN_FOLDER) ?></button>
    101       <div class="clear"></div>
    102     </div>
    103   </div>
    104125</div>
    105126<div id="expresscurate_loading">
    106   <img src="<?php echo plugin_dir_url(__FILE__); ?>../images/loading.gif" id="img-load" />
     127    <img src="<?php echo plugin_dir_url(__FILE__); ?>../images/loading.gif" id="img-load"/>
    107128</div>
    108129
    109130<script type="text/html" id="tmpl-dialogCuratedImage">
    110     <li id="tcurated_image_{{data.index}}" class="tcurated_image" data-id="{{data.index}}" style="background-image: url({{data.url}})"></li>
     131    <li id="tcurated_image_{{data.index}}" class="tcurated_image" data-id="{{data.index}}"
     132        style="background-image: url({{data.url}})"></li>
    111133</script>
    112134<script type="text/html" id="tmpl-dialogCuratedParagraphs">
    113     <li id="tcurated_text_{{data.index}}" title="{{data.title}}" class="tcurated_text expresscurate_tag_{{data.tag}}" data-id="{{data.index}}">{{data.title}}</li>
     135    <li id="tcurated_text_{{data.index}}" title="{{data.title}}" class="tcurated_text expresscurate_tag_{{data.tag}}"
     136        data-id="{{data.index}}">{{data.title}}
     137    </li>
    114138</script>
    115139<script type="text/html" id="tmpl-dialogCuratedtags">
    116     <li class="curated_post_tag"  id="curated_post_tag_{{data.index}}"><span class="tag">{{data.tag}}</span><a href="#" class="remove" data-id="{{data.index}}"></a></li>
     140    <li class="curated_post_tag" id="curated_post_tag_{{data.index}}"><span class="tag">{{data.tag}}</span><a href="#"
     141                                                                                                              class="remove"
     142                                                                                                              data-id="{{data.index}}"></a>
     143    </li>
    117144</script>
    118145<script type="text/html" id="tmpl-dialogMarkButton">
     
    120147</script>
    121148<script type="text/html" id="tmpl-dialogInsertTags">
    122     <li class="curated_post_tag" id="curated_post_tag_{{data.index}}"><a href="#" data-id="{{data.index}}">X</a><span>{{data.tag}}</span></li>
     149    <li class="curated_post_tag" id="curated_post_tag_{{data.index}}"><a href="#" data-id="{{data.index}}">X</a><span>{{data.tag}}</span>
     150    </li>
    123151</script>
    124152<script type="text/html" id="tmpl-dialogSearchParagraphs">
     
    134162</script>
    135163<script type="text/html" id="tmpl-dialogCuratedHeadings">
    136     <li class="curated_heading" id="curated_heading_{{data.index}}"  data-tag="{{data.index}}" title="{{data.content}}">{{data.index}}</li>
     164    <li class="curated_heading" id="curated_heading_{{data.index}}" data-tag="{{data.index}}" title="{{data.content}}">
     165        {{data.index}}
     166    </li>
    137167</script>
    138168<script type="text/html" id="tmpl-dialogCuratedDescription">
     
    148178        </ul>
    149179        <div id="" class="tab-content">
    150             <textarea id="expresscurate_socialEmbed" placeholder="Embed code" class="expresscurate_disableInputStyle"></textarea>
     180            <textarea id="expresscurate_socialEmbed" placeholder="Embed code"
     181                      class="expresscurate_disableInputStyle"></textarea>
    151182            <span class="expresscurate_errorMessage"></span>
    152183        </div>
  • expresscurate/trunk/templates/feed_dashboard.php

    r1129694 r1137344  
    66<div class="expresscurate_feed_dashboard expresscurate_Styles wrap">
    77    <div class="expresscurate_headBorderBottom expresscurate_headerPart expresscurate_OpenSansRegular">
    8         <a href="admin.php?page=expresscurate&type=keywords" class="expresscurate_writeUs">Suggestions? <span>Submit here!</span></a>
     8        <a href="admin.php?page=expresscurate_support" class="expresscurate_writeUs">Suggestions? <span>Submit here!</span></a>
    99
    1010        <h2>RSS Feeds</h2>
     
    2626                        <li>
    2727                            <a href="<?php echo $feed_url['feed_url'] ?>"
    28                                target="_newtab"><?php echo $feed_url['feed_url']; ?></a>
     28                               target="_newtab"><?php echo $feed_url['feed_title']; ?><br /><small><?php echo $url; ?></small></a>
    2929                            <span class="postsCount expresscurate_floatRight">
    3030                                <?php echo $feed_url['post_count']; ?>
     
    5050    <script type="text/html" id="tmpl-rssfeedItem">
    5151        <li>
    52             <a target="_newtab" href="{{data.feed_url}}">{{data.feed_url}}</a>
     52            <a target="_newtab" href="{{data.feed_url}}">{{data.feed_title}}<br/><small>{{data.link}}</small></a>
    5353                        <span class="postsCount expresscurate_floatRight">{{data.post_count}}
    5454                        <input type="hidden" name="expresscurate_feed_url" value="{{data.feed_url}}"/>
  • expresscurate/trunk/templates/feed_list.php

    r1129694 r1137344  
    1414
    1515if (!empty($contentList)) {
    16     foreach ($contentList as $key => $row) {
    17         if (is_array($row) && count($row) > 0) {
    18             foreach ($row as $content) {
    19                 $content['fullLink'] = $content['link'];
    20                 $extracted_url = extract_google_feed_url($content['link'], $row);
    21                 if ($extracted_url) {
    22                     $url = $extracted_url;
    23                 } else {
    24                     $url = $content['link'];
    25                 }
    26                 $content['link'] = $url;
    27                 $content['domain'] = parse_url($url, PHP_URL_SCHEME) . "://" . parse_url($url, PHP_URL_HOST);
    28                 array_push($sorted_feeds, $content);
     16    $feed_content = $contentList['content'];
     17    if (is_array($feed_content) && count($feed_content) > 0) {
     18        foreach ($feed_content as $content) {
     19            $content['fullLink'] = $content['link'];
     20            $extracted_url = extract_google_feed_url($content['link'], $feed_content);
     21            if ($extracted_url) {
     22                $url = $extracted_url;
     23            } else {
     24                $url = $content['link'];
    2925            }
     26            $content['link'] = $url;
     27            $content['domain'] = parse_url($url, PHP_URL_SCHEME) . "://" . parse_url($url, PHP_URL_HOST);
     28            array_push($sorted_feeds, $content);
    3029        }
    3130    }
     
    3332}
    3433
    35 wp_clear_scheduled_hook('expresscurate_pull_feeds');
    36 $pull_feed_interval = (get_option('expresscurate_pull_hours_interval')) ? get_option('expresscurate_pull_hours_interval') : 1;
    37 wp_schedule_event(strtotime("+" . $pull_feed_interval . " hour"), 'hourly', 'expresscurate_pull_feeds');
    3834$nextPullTime = human_time_diff(wp_next_scheduled('expresscurate_pull_feeds'), time());
    39 
    4035?>
    4136<input id="adminUrl" type="hidden" value="<?php echo get_admin_url(); ?>"/>
     
    4540    } ?>">
    4641    <div class="expresscurate_headBorderBottom expresscurate_OpenSansRegular">
    47         <a href="admin.php?page=expresscurate&type=keywords" class="expresscurate_writeUs">Suggestions? <span>Submit here!</span></a>
     42        <a href="admin.php?page=expresscurate_support" class="expresscurate_writeUs">Suggestions? <span>Submit here!</span></a>
    4843
    4944        <h2>Content Feed</h2>
     
    5651        </div>
    5752        <div class="controlsWrap">
    58             <ul class="feedListControls expresscurate_preventTextSelection expresscurate_controls expresscurate_displayNone">
     53            <ul class="feedListControls expresscurate_preventTextSelection expresscurate_controls ">
    5954                <li class="check">
    6055                    <span class="tooltip">select / deselect</span>
     
    6964                    <span class="tooltip">curate</span>
    7065                </li>
    71                 <!--<li class="pull active expresscurate_floatRight">
    72                     <span class="tooltip">pull</span>
    73                 </li>
    74                 <li class="pullTime active expresscurate_floatRight">
    75                     next update:
    76                     <p>in <?php /*echo $nextPullTime; */?></p>
    77                 </li>-->
     66                <?php if (strlen(get_option('expresscurate_links_rss', '')) > 2) { ?>
     67                    <li class="pull active expresscurate_floatRight">
     68                        <span class="tooltip">pull</span>
     69                        <span class="loading"></span>
     70                    </li>
     71                    <li class="pullTime active expresscurate_floatRight">
     72                        next update:
     73                        <p>in <?php echo $nextPullTime; ?></p>
     74                    </li>
     75                <?php } ?>
    7876                <li class="layout expresscurate_floatRight">
    7977                    <span class="tooltip"><?php if (get_option('expresscurate_bookmark_layout', '') == 'single') {
     
    9391        $i = 0;
    9492        ?>
    95         <ul class="expresscurate_feedBoxes expresscurate_masonryWrap"><?php
     93        <ul id="expresscurate_feedBoxes" class="expresscurate_feedBoxes expresscurate_masonryWrap"><?php
    9694        foreach ($sorted_feeds as $key => $item) {
    9795            ?>
     
    157155        ?></ul><?php
    158156    } ?>
    159     <label class="expresscurate_notDefined expresscurate_displayNone">Your content feed is empty. Configure <a
     157    <label class="expresscurate_notDefined expresscurate_displayNone">Your content feed is
     158        empty. <?php echo (strlen(get_option('expresscurate_links_rss', '')) > 2) ? '' : 'Configure <a
    160159            href="admin.php?page=expresscurate_feeds">RSS feeds</a> to
    161         start.</label>
     160        start.'; ?></label>
    162161
    163162    <form method="POST" action="<?php echo get_admin_url() ?>post-new.php#expresscurate_sources_collection"
  • expresscurate/trunk/templates/keywords.php

    r1129694 r1137344  
    88    <input type="hidden" id="expresscurate_plugin_dir" value="<?php echo plugin_dir_url(__FILE__); ?>"/>
    99    <label>Keywords Dashboard</label>
    10     <a href="admin.php?page=expresscurate&type=keywords" class="expresscurate_writeUs">Suggestions?
     10    <a href="admin.php?page=expresscurate_support" class="expresscurate_writeUs">Suggestions?
    1111        <span>Submit here!</span></a>
    1212    <br/>
  • expresscurate/trunk/templates/news.php

    r1075868 r1137344  
    11<div class="expresscurate_Styles wrap ">
    22    <div class="expresscurate_headBorderBottom expresscurate_OpenSansRegular">
    3         <a href="admin.php?page=expresscurate&type=keywords" class="expresscurate_writeUs">Suggestions? <span>Submit here!</span></a>
     3        <a href="admin.php?page=expresscurate_support" class="expresscurate_writeUs">Suggestions? <span>Submit here!</span></a>
    44        <h2>News</h2>
    55    </div>
  • expresscurate/trunk/templates/settings.php

    r1129694 r1137344  
    11<div class="expresscurate expresscurate_Styles expresscurate_settings wrap">
    22    <div class="expresscurate_headBorderBottom expresscurate_OpenSansRegular">
    3         <a href="admin.php?page=expresscurate&type=keywords" class="expresscurate_writeUs">Suggestions?
     3        <a href="admin.php?page=expresscurate_support" class="expresscurate_writeUs">Suggestions?
    44            <span>Submit here!</span></a>
    55
     
    7979                        ?>" name="expresscurate_curated_text" size="50"/>
    8080                    </li>
     81                    <li>                       
     82                        <p class="title">Open Original Article Link in a New Window/Tab<span scope="row" class="description  ">
     83            Select "Yes" if you want the original article link to be opened in a New Window/Tab. Select "No" if you want the link to be opened in the Same Window/Tab (default behavior).
     84          </span></p>
     85
     86                        <input class="expresscurate_displayNone" type="checkbox" id="expresscurate_curated_link_target"
     87                               name="expresscurate_curated_link_target" <?php
     88                        if (get_option('expresscurate_curated_link_target', 'on') == "on") {
     89                            echo 'checked';
     90                        }
     91                        ?> />
     92                        <label class="controls checkboxLabel" for="expresscurate_curated_link_target"></label>
     93                       
     94                    </li>
    8195                    <li>
    8296                        <label for="expresscurate_max_tags" class="title">Max Number of Auto-suggested Tags<span
     
    414428                    <li>
    415429                        <div class="title">
     430                            Content Pull Frequency
     431                            <div class="description">
     432                                How frequently should ExpressCurate pull content (from RSS feeds, Alerts, etc) into your
     433                                <a href="#">Content Feed</a>?
     434                            </div>
     435                        </div>
     436                        <select class="controls" id="expresscurate_pull_hours_interval"
     437                                name="expresscurate_pull_hours_interval">
     438                            <?php
     439                            for ($i = 1; $i < 14; $i++) {
     440                                ?>
     441                                <?php if ($i == 1) { ?>
     442                                    <option value="<?php echo $i; ?>" <?php
     443                                    if (get_option('expresscurate_pull_hours_interval') == $i) {
     444                                        echo 'selected="selected"';
     445                                    }
     446                                    ?>>Every hour
     447                                    </option>
     448
     449                                <?php } elseif ($i == 13) { ?>
     450                                    <option value="<?php echo $i; ?>" <?php
     451                                    if (get_option('expresscurate_pull_hours_interval') == $i) {
     452                                        echo 'selected="selected"';
     453                                    }
     454                                    ?>>Once a day
     455                                    </option>
     456
     457                                <?php } else { ?>
     458                                    <option value="<?php echo $i; ?>" <?php
     459                                    if (get_option('expresscurate_pull_hours_interval') == $i) {
     460                                        echo 'selected="selected"';
     461                                    }
     462                                    ?>>Every <?php echo $i; ?> hours
     463                                    </option>
     464
     465                                <?php
     466                                }
     467                            }
     468                            ?>
     469                        </select>
     470                    </li>
     471                    <li>
     472                        <div class="title">
    416473                            Keyword Match Email Alerts
    417474                            <div class="description">
     
    467524                        </select>
    468525                    </li>
    469                     <li>
    470                         <div class="title">
    471                             Content Pull Frequency
    472                             <div class="description">
    473                                 How frequently should ExpressCurate pull content (from RSS feeds, Alerts, etc) into your
    474                                 <a href="#">Content Feed</a>?
    475                             </div>
    476                         </div>
    477                         <select class="controls" id="expresscurate_pull_hours_interval"
    478                                 name="expresscurate_pull_hours_interval">
    479                             <?php
    480                             for ($i = 1; $i < 14; $i++) {
    481                                 ?>
    482                                 <?php if ($i == 1) { ?>
    483                                     <option value="<?php echo $i; ?>" <?php
    484                                     if (get_option('expresscurate_pull_hours_interval') == $i) {
    485                                         echo 'selected="selected"';
    486                                     }
    487                                     ?>>Every hour
    488                                     </option>
    489 
    490                                 <?php } elseif ($i == 13) { ?>
    491                                     <option value="<?php echo $i; ?>" <?php
    492                                     if (get_option('expresscurate_pull_hours_interval') == $i) {
    493                                         echo 'selected="selected"';
    494                                     }
    495                                     ?>>Once a day
    496                                     </option>
    497 
    498                                 <?php } else { ?>
    499                                     <option value="<?php echo $i; ?>" <?php
    500                                     if (get_option('expresscurate_pull_hours_interval') == $i) {
    501                                         echo 'selected="selected"';
    502                                     }
    503                                     ?>>Every <?php echo $i; ?> hours
    504                                     </option>
    505 
    506                                 <?php
    507                                 }
    508                             }
    509                             ?>
    510                         </select>
    511                     </li>
    512526                </ul>
    513527                <div class="centerSave">
  • expresscurate/trunk/templates/websites.php

    r1066998 r1137344  
    55<div class="expresscurate_topSources expresscurate_Styles wrap">
    66  <div class="expresscurate_headBorderBottom expresscurate_headerPart expresscurate_OpenSansRegular">
    7     <a href="admin.php?page=expresscurate&type=keywords" class="expresscurate_writeUs">Suggestions? <span>Submit here!</span></a>
     7    <a href="admin.php?page=expresscurate_support" class="expresscurate_writeUs">Suggestions? <span>Submit here!</span></a>
    88    <h2>Top Sources</h2>
    99      <label class="pageDesc">Top sources where you have curated from.</label>
Note: See TracChangeset for help on using the changeset viewer.