WordPress.org

Plugin Directory

Changeset 614019


Ignore:
Timestamp:
10/18/12 11:15:47 (18 months ago)
Author:
wpmuguru
Message:

tag & release 4.0.9

Location:
scribe
Files:
274 added
8 deleted
10 edited

Legend:

Unmodified
Added
Removed
  • scribe/trunk/readme.txt

    r504549 r614019  
    11=== Plugin Name === 
    22Contributors: ScribeSEO, nathanrice, wpmuguru 
    3 Donate link: http://scribeseo.com/ 
    4 Tags: Scribe, SEO, Copyblogger, search engine optimization, content analysis, copywriting, plugin, Google, Bing, Yahoo, copy compass, seo copywriting, seo copy writing, text analyzer 
     3Donate link: http://scribecontent.com/ 
     4Tags: content marketing, social media marketing, search marketing, keyword research, Scribe, SEO, Copyblogger, search engine optimization, content analysis, copywriting, Google, Bing, Yahoo, copy compass, seo copywriting, seo copy writing, text analyzer 
    55Requires at least: 3.3 
    6 Tested up to: 3.3 
    7 Stable tag: 3.0.11 
    8  
    9 Scribe makes SEO Copywriting Simple. 
     6Tested up to: 3.4.1 
     7Stable tag: 4.0.9 
     8 
     9Scribe makes content marketing simple. 
    1010 
    1111== Description == 
    1212 
    13 Scribe is an SEO software service for WordPress - think of it as a content optimization assistant - that analyzes web pages, blog posts, and online press releases at the click of a button. 
    14  
    15 Developed by <a href="http://www.copyblogger.com" title="Copyblogger">Copyblogger Media</a>, Scribe instructs web writers of any kind how to tweak their content to get more search engine traffic, all while maintaining quality reader-focused copy. 
     13Scribe is a professional content marketing application designed for online content creators.  
     14 
     15Developed by <a href=http://www.copyblogger.com title=”Copyblogger”>Copyblogger Media </a>, Scribe makes it easy to conduct in-depth research that helping writers and content producers to quickly identify content marketing opportunities for search and social media traffic and leads. 
     16 
     17Once you have performed your research, Scribe’s Content Analysis provides a fast yet intuitive way to check the alignment of your writing to the content on your site – helping you quickly insure that your content and site are focused on the terms that make up your content marketing strategy. You can then optimize the elements of your on-page content for maximum relevance for search rankings.  
     18 
     19Finally Scribe’s Site Connector tool provides a simple way for you to find bloggers and social media users that share a similar interest in the topics your site is focusing on.  
     20 
     21Scribe is the ultimate content marketing management resource – helping you at every critical stage to identify and execute on your content marketing strategy. 
     22 
    1623 
    1724== Installation == 
    1825 
    19 Use Scribe 3.0.8 for versions of WordPress prior to 3.3 
    20  
    21 **REQUIREMENTS** You must have a supported theme or plugin in order to use Scribe. Please see the list of supported themes/plugins at <a href="http://scribeseo.com/compatibility/" title="Scribe SEO Compatibility List">http://scribeseo.com/compatibility/</a>. 
     26**REQUIREMENTS** You must have a supported theme or plugin in order to use Scribe. Please see the list of supported themes/plugins at <a href="http://scribecontent.com/compatibility/" title="Scribe SEO Compatibility List">http://scribecontent.com/compatibility/</a>. 
    2227 
    2328Scribe analyzes **English** only. We do not have immediate plans to support other international languages. 
     
    2530Once you have confirmed that your site meets the requirements, follow these instructions to install: 
    2631 
    27 NOTE: Obtain an API Key from [http://scribeseo.com](http://scribeseo.com "ScribeSEO API Key").  
     32NOTE: Obtain an API Key from [http://scribecontent.com](http://scribecontent.com "Scribe API Key").  
    2833 
    2934Option #1 - Install Via Plugin Upload 
     
    3237   1. Open WordPress and go to Plugins>Add New>Upload and upload the scribe.zip file. 
    3338   1. Once done, Activate the plugin. 
    34    1. Go to Settings>Scribe Settings and enter your API Key. Click the Save button. 
     39   1. Go to Scribe> Settings and enter your API Key. Click the Save button. 
    3540   1. You should be good to Scribe! 
    3641 
     
    4045   1. Login to your WordPress admin and navigate to the Plugins > Installed page. 
    4146   1. Activate Scribe. 
    42    1. Navigate to the Setting > Scribe Settings page. 
     47   1. Navigate to the Scribe > Settings page. 
    4348   1. Enter your Scribe API key 
    4449   1. Scribe will now be available when you edit your posts! 
     
    4651== Frequently Asked Questions == 
    4752 
    48 = How is Scribe different from other SEO tools? = 
    49  
    50 Scribe is unique because it focuses on the content of your site and not just the structure of the site. As all SEO experts acknowledge, great SEO **starts** with great content. By using Scribe you will ensure that your content meets the best practices for content structure **and** that search engines can easily identify your keywords/concepts. 
    51  
    52 In essence, Scribe allows writers to perform effective search engine optimization with little effort and no mystery. 
     53= How does Scribe help me in my Content Marketing efforts? = 
     54 
     55Effective content marketing starts with great content – content that is both search engine and social media friendly. 
     56 
     57Scribe makes it easy for content creators to research and create content that is focused on the key topics that the audience they want to reach are interested in, using the language that audience uses when searching and discussing those topics.. This is the key to improving targeted traffic and leads from search and social media sources. 
     58 
     59Scribe’s powerful research tools help you find opportunities that are not being served, helping you quickly focus your content efforts on terms that have low competition online with strong demand from searchers. 
     60 
     61And once you find a content focus that works, Scribe’s Content Analysis provides a quick and easy way to inspect your content for both the strength of your writing style and the alignment of your content with your overall site – both crucial to search engine rankings in a post-Panda environment. 
     62 
     63Finally, as any good content marketer will attest, online connections matter and with Scribe Site Connections, it’s easier than ever to quickly identify complentary publishers, bloggers, and authoritative social media personalities so that you can engage them with your content. 
    5364 
    5465= Why do I need an API Key? = 
     
    5869= Why does Scribe require a theme or plugin in order to work? = 
    5970 
    60 Scribe relies on the SEO features of some of the more popular SEO frameworks. Our currently supported frameworks, found at <a href="http://scribeseo.com/compatibility" title="Scribe Compatibility">Scribe Compatibility</a>, have been tested and support the advanced SEO features required to maximize your exposure on search engines. 
     71Scribe relies on the SEO features of some of the more popular SEO frameworks. Our currently supported frameworks, found at <a href="http://scribecontent.com/compatibility" title="Scribe Compatibility">Scribe Compatibility</a>, have been tested and support the advanced SEO features required to maximize your exposure on search engines. 
    6172 
    6273= I don't see my theme listed! =  
    6374 
    64 We will continue to support other themes over time based on the cooperation of theme developers. Because our plugin is under the GPL, you may modify it to support other themes or plugins. For a complete list of compatible themes and plugins, go to <a href="http://scribeseo.com/compatibility/" title="Scribe SEO Compatibility List">http://scribeseo.com/compatibility/</a>. 
     75We will continue to support other themes over time based on the cooperation of theme developers. Because our plugin is under the GPL, you may modify it to support other themes or plugins. For a complete list of compatible themes and plugins, go to <a href="http://scribecontent.com/compatibility/" title="Scribe SEO Compatibility List">http://scribecontent.com/compatibility/</a>. 
    6576 
    6677== Screenshots == 
    6778 
    68 1. NEW FEATURE - Perform Keyword Research from within your WordPress edit screen 
    69  
    70 2. NEW FEATURE - Intelligent link building analysis for external links, internal links and social media connections 
    71  
    72 3. Quickly check your Scribe Content Analysis within the edit environment 
    73  
    74 4. Scribe analyzes the structure of your content and gives you suggestions on how to improve 
    75  
    76 5. Want to know your important keywords? Scribe automatically determines them for you 
    77  
    78 6. Easy suggestions on how to change the emphasis of your keywords within your document structure 
    79  
    80 7. Compare your keywords to other popular keywords by search frequency 
    81  
    82 8. Tags are automatically created for you - including synonyms 
    83  
    84 9. Quickly check how your post will appear in search engine results 
    85  
    86 10. For more detailed explanations, check out the SEO Best Practice Guide within the tool 
     791. IMPROVED FEATURE - Perform detailed Keyword Research from within your WordPress edit screen – helping you find content marketing opportunities quickly 
     80 
     812. NEW FEATURE – Keyword Details provides deep insight into how your site compares to other top sites helping you focus your content marketing efforts. 
     82 
     833. NEW FEATURE – Get headline ideas instantly from Twitter and Google + users. 
     84 
     854. NEW FEATURE – With the Scribe Keyword Graph and Site Score, you can quickly asses how well your content aligns with your site helping insure that your content marketing strategy remains focused on the keywords that matter. 
     86 
     875. NEW FEATURE – In the post Panda/Penguin Google world, online connections matter more than ever and with the new Scribe Site Connections tool, finding bloggers and social media users is fast and intelligent. 
     88 
     896. IMPROVED FEATURE – Our Document Analysis has been updated to account for the recent changes introduced by Google and Bing. 
     90 
     917. IMPROVED FEATURE – How your content links together on your site is very important, and with Scribe we have improved the way we find and report on the best pages in your site for the terms you are targeting. 
     92 
     938. IMPROVED FEATURE – With Scribe, adding semantically relevant tags to your post is as simple as clicking a button.  
    8794 
    8895 
    8996== Changelog == 
     97 
     98= 4.0.9 = 
     99* Upgraded version introducing a number of new features 
     100* NEW Keyword Details feature comparing your sites key search metric to the competition. 
     101* NEW Social Media search integration showing headlines and thought leaders based on your content. 
     102* NEW Keyword Graph comparing keyword usage within your content to the usage of those terms on your site. 
     103* New Site Connection tool helping you identify blogs and social media users that align with your sites content. 
    90104 
    91105= 3.0.11 = 
     
    153167 
    154168== Upgrade Notice == 
     169= 4.0.9 =  
     170Major update to Scribe with NEW features to improve your search and social media content marketing. 
     171 
    155172= 3.0.11 = 
    156173Bugfix for error in metaboxes in some installs. 
     
    195212Current public release. 
    196213 
    197 == Search Engine Optimization == 
    198  
    199 The Search Engine Optimization (SEO) process can generally be defined as four key parts; content, keywords, site structure and links. Most SEO activity focuses on one or all of these areas.  
    200  
    201 Scribe is designed to help authors/writers participate in the SEO process through the intelligent review and analysis of the content on the page.  
    202  
    203 First, conduct keyword research to find the best search terms using our Keyword Research tool. Next, we review the content and semantic structure of the content to find the most relevant keyword terms based on search behavior and identify how you can better use these terms within your content. Finally we help you identify related websites, social media users and pages within your current site that are appropriate for link building. 
    204  
    205 Scribe makes SEO copywriting easy. Try it for yourself. 
     214== Content Marketing == 
     215 
     216Content Marketing is the cornerstone strategy of search and social media marketing.  
     217 
     218Scribe is designed to help writers participate in the content marketing process through the intelligent review and analysis of the content on the page.  
     219 
     220First, by using the Keyword Research tool in Scribe, content marketers can find opportunities to create content that is both in high demand with little competition. 
     221 
     222Next, we review the semantic structure of the content to find the most relevant keyword terms identify how you can better use these terms within your content and on your site.  
     223 
     224Finally we help you build online relationships with others that are discussing your topics and ideas online. 
     225 
     226Scribe makes content marketing easy. Try it for yourself. 
    206227 
    207228A product from Copyblogger Media, LLC. 
     229 
  • scribe/trunk/scribe.php

    r504547 r614019  
    11<?php 
    22/* 
    3  Plugin Name: Scribe SEO 
    4  Plugin URI: http://scribeseo.com 
    5  Description: Quickly and easily check your content against SEO best practices utilizing the Scribe Content Optimizer.  You will need a <a href="https://my.scribeseo.com" title="My Scribe API key">Scribe API Key</a> in order to use the application. If you do not have an API Key, go to <a href="http://scribeseo.com" title="Get Scribe API Key">http://scribeseo.com</a>. <strong>Please</strong> make sure you are using a supported theme or plugin. For an updated list, go to <a href="http://scribeseo.com/compatibility/" title="Scribe Compatibility List">http://scribeseo.com/compatibility/</a>. 
    6  Version: 3.0.11 
     3 Plugin Name: Scribe 
     4 Plugin URI: http://scribecontent.com 
     5 Description: Increase your online traffic with Scribe – the intelligent content marketing tool for creative content producers . Scribe combines in-depth semantic keyword research, sophisticated content analysis and optimization tools, and targeted social media insights to help you focus your content marketing efforts. You will need a Scribe API Key in order to use the application. If you do not have an API Key, go to ​<a href="http://scribecontent.com" title="Get Scribe API Key">http://scribecontent.com</a>. Please make sure you are using a supported theme or plugin. For an updated list, go to <a href="http://scribecontent.com/compatibility/" title="Scribe Compatibility List">http://scribecontent.com/compatibility/</a>. 
     6 Version: 4.0.9 
    77 Author: Copyblogger Media 
    88 Author URI: http://www.copyblogger.com 
    99 */ 
    1010 
    11 define( 'ECORDIA_DEBUG', false ); 
    12  
    13 require_once ('lib/ecordia-access/ecordia-content-optimizer.class.php'); 
    14 require_once ('lib/ecordia-access/ecordia-user-account.class.php'); 
    15 require_once ('lib/ecordia-access/ecordia-keyword-alternates.class.php'); 
    16 require_once ('lib/ecordia-access/ecordia-keyword-research.class.php'); 
    17 require_once ('lib/ecordia-access/ecordia-link-building-research.class.php'); 
    18  
    19 if (!function_exists('json_encode') && file_exists(ABSPATH.'/wp-includes/js/tinymce/plugins/spellchecker/classes/utils/JSON.php')) { 
    20     require_once (ABSPATH.'/wp-includes/js/tinymce/plugins/spellchecker/classes/utils/JSON.php'); 
    21     function json_encode($data) { 
    22         $json == new Moxiecode_JSON(); 
    23         return $json->encode($data); 
     11if(!class_exists('Scribe_SEO')) { 
     12    class Scribe_SEO { 
     13        /// CONSTANTS 
     14         
     15        //// VERSION 
     16        const VERSION = '4.0.9'; 
     17         
     18        //// KEYS 
     19        const SHOW_PREMISE_NAG_KEY = '_scribe_show_premise_nag'; 
     20        const SETTINGS_KEY = '_scribe_settings'; 
     21        const VERSION_KEY = '_scribe_version'; 
     22        const PLUGIN_INFO_CACHE_KEY = 'scribe_plugin_info'; 
     23         
     24        //// SLUGS 
     25        const SETTINGS_TOP_PAGE_SLUG = 'scribe-settings'; 
     26        const SETTINGS_SUB_PAGE_SLUG_SETTINGS = 'scribe-settings'; 
     27        const SETTINGS_SUB_PAGE_SLUG_CONNECTIONS = 'scribe-connections'; 
     28        const SETTINGS_SUB_PAGE_SLUG_ACCOUNT = 'scribe-account'; 
     29        const SETTINGS_SUB_PAGE_SLUG_COMPATIBILITY = 'scribe-compatibility'; 
     30        const SETTINGS_SUB_PAGE_SLUG_SUPPORT = 'scribe-help'; 
     31        const SETTINGS_SUB_PAGE_SLUG_NEWS = 'scribe-news'; 
     32         
     33        //// USER META 
     34        const CONTENT_ANALYSIS_BASE_KEY = 'scribe_content_analysis'; 
     35        const KEYWORD_DETAILS_BASE_KEY = '_skwd_'; // We have to abbreviate this because of the option name limit of 64 - Scribe Keyword Details 
     36        const KEYWORD_SUGGESTIONS_TRANSIENT_BASE_KEY = 'skws_'; // We have to abbreviate this because of the option name limit - Scribe Keyword Suggestions 
     37        const LINK_BUILDING_INFO_BASE_KEY = 'scribe_link_building_info'; // We have to abbreviate this because of the option name limit 
     38        const PREVIOUS_KEYWORD_SUGGESTIONS_KEY = 'scribe_previous_keyword_suggestions_'; 
     39        const TARGET_TERM_BASE_KEY = 'scribe_target_term_'; 
     40         
     41        //// CACHE 
     42        const CACHE_PERIOD = 86400; // 24 HOURS 
     43        const KEYWORD_SUGGESTIONS_TRANSIENT_TIME = 86400; 
     44         
     45        //// URLS 
     46        const SEO_NEWS_FEED_URL = 'http://feeds.feedburner.com/SearchEngineJournal'; 
     47     
     48        /// DATA STORAGE 
     49        private static $admin_page_hooks = array('post.php', 'post-new.php', 'media-upload-popup', 'edit.php'); 
     50        private static $default_settings = array('post-types' => array('post','page')); 
     51         
     52        /* 
     53         * @var Scribe_API $scribe_api 
     54         */ 
     55        private static $scribe_api = null; 
     56        private static $scribe_api_account = null; 
     57        private static $upload_iframe_args = null; 
     58        // Upgraded from Scribe v3 
     59        private static $scribe_has_v3_data = false; 
     60 
     61        public static function init() { 
     62         
     63            if ( ! defined( 'SCRIBE_PLUGIN_DIR' ) ) 
     64                define( 'SCRIBE_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); 
     65 
     66            require_once( SCRIBE_PLUGIN_DIR . 'lib/scribe-connector.php' ); 
     67 
     68            if ( ! is_admin() ) 
     69                return; 
     70 
     71            if ( ! defined( 'SCRIBE_PLUGIN_URL' ) ) 
     72                define( 'SCRIBE_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); 
     73 
     74            require_once( SCRIBE_PLUGIN_DIR . 'lib/scribe-api.php' ); 
     75            require_once( SCRIBE_PLUGIN_DIR . 'lib/scribe-display-helpers.php' ); 
     76            require_once( SCRIBE_PLUGIN_DIR . 'lib/scribe-google.php' ); 
     77            require_once( SCRIBE_PLUGIN_DIR . 'lib/scribe-support.php' ); 
     78            require_once( SCRIBE_PLUGIN_DIR . 'lib/scribe-utility.php' ); 
     79            require_once( SCRIBE_PLUGIN_DIR . 'lib/class-admin.php' ); 
     80            require_once( SCRIBE_PLUGIN_DIR . 'views/backend/settings/class-main-settings.php' ); 
     81     
     82            self::add_actions(); 
     83            self::add_filters(); 
     84            self::initialize_defaults(); 
     85            self::initialize_memory_limit(); 
     86            self::initialize_scribe_api(); 
     87 
     88            // check for Scribe v3 data 
     89            self::$scribe_has_v3_data = (bool) get_option( '_ecordia_settings', false ); 
     90            if ( self::$scribe_has_v3_data ) 
     91                require_once( SCRIBE_PLUGIN_DIR . '/lib/history/scribe.php' ); 
     92 
     93            // check for update 
     94            self::update(); 
     95 
     96        } 
     97 
     98        private static function add_actions() { 
     99 
     100            add_action( 'admin_enqueue_scripts', array( __CLASS__, 'enqueue_administrative_resources' ) ); 
     101            add_action( 'admin_footer', array( __CLASS__, 'output_script_that_adds_target_blank_to_scribe_help_item' ) ); 
     102            add_action( 'admin_init', array( __CLASS__, 'handle_versions' ) ); 
     103            add_action( 'admin_menu', array( __CLASS__, 'add_administrative_interface_items' ) ); 
     104            add_action( 'admin_menu', array( __CLASS__, 'modify_administrative_interface_items' ) ); 
     105            // plugin updates 
     106            add_action( 'load-update-core.php', array( __CLASS__, 'delete_plugin_info' ) ); 
     107            add_filter( 'transient_update_plugins', array( __CLASS__, 'check_plugin_updates' ) ); 
     108            add_filter( 'site_transient_update_plugins', array( __CLASS__, 'check_plugin_updates' ) ); 
     109 
     110            /// ANALYSIS POPUPS 
     111            add_action( 'media_upload_scribe-analysis-keywords', array( __CLASS__, 'display_analysis_tabs' ) ); 
     112            add_action( 'media_upload_scribe-analysis-document', array( __CLASS__, 'display_analysis_tabs' ) ); 
     113            add_action( 'media_upload_scribe-analysis-tags', array( __CLASS__, 'display_analysis_tabs' ) ); 
     114            add_action( 'media_upload_scribe-analysis-help', array( __CLASS__, 'display_analysis_tabs' ) ); 
     115 
     116            /// KEYWORD POPUPS 
     117            add_action( 'media_upload_scribe-keyword-suggestions', array( __CLASS__, 'display_keyword_tabs' ) ); 
     118            add_action( 'media_upload_scribe-keyword-details', array( __CLASS__, 'display_keyword_tabs' ) ); 
     119 
     120            /// LINK BUILDING POPUPS 
     121            add_action( 'media_upload_scribe-link-building', array( __CLASS__, 'display_link_building_tabs' ) ); 
     122            add_action( 'media_upload_scribe-link-building-twitter-info', array( __CLASS__, 'display_link_building_tabs' ) ); 
     123 
     124            /// AJAX 
     125 
     126            //// CONTENT ANALYSIS 
     127            add_action( 'wp_ajax_scribe_analyze_content', array( __CLASS__, 'ajax_handle_analyze_content' ) ); 
     128 
     129            /// KEYWORD SUGGESTIONS 
     130            add_action( 'wp_ajax_scribe_keyword_suggestions', array( __CLASS__, 'ajax_handle_keyword_suggestions' ) ); 
     131 
     132            //// KEYWORD RESEARCH 
     133            add_action( 'wp_ajax_scribe_research_keyword', array( __CLASS__, 'ajax_handle_research_keyword' ) ); 
     134            add_action( 'wp_ajax_scribe_research_google_plus', array( __CLASS__, 'ajax_handle_research_google_plus' ) ); 
     135            add_action( 'wp_ajax_scribe_research_google_trends', array( __CLASS__, 'ajax_handle_research_google_trends' ) ); 
     136 
     137            //// LINK BUILDING 
     138            add_action( 'wp_ajax_scribe_build_links', array( __CLASS__, 'ajax_handle_build_links' ) ); 
     139 
     140            //// TARGET TERM 
     141            add_action( 'wp_ajax_scribe_clear_target_term', array( __CLASS__, 'ajax_handle_clear_target_term' ) ); 
     142            add_action( 'wp_ajax_scribe_set_target_term', array( __CLASS__, 'ajax_handle_set_target_term' ) ); 
     143 
     144        } 
     145 
     146        private static function add_filters() { 
     147            add_filter('pre_scribe_settings_save', array(__CLASS__, 'sanitize_scribe_settings')); 
     148        } 
     149         
     150        private static function initialize_defaults() { 
     151            self::$default_settings['your-url'] = home_url('/'); 
     152        } 
     153 
     154        private static function initialize_memory_limit() { 
     155            $memory_limit = scribe_convert_bytes(ini_get('memory_limit')); 
     156            $memory_limit_megabytes = ($memory_limit / (1024 * 1024)); 
     157            if($memory_limit < 64) { 
     158                ini_set('memory_limit', 64*1024*1024); 
     159            } 
     160        } 
     161 
     162        private static function initialize_scribe_api() { 
     163            if(null === self::$scribe_api) { 
     164                $settings = self::get_settings(); 
     165                self::$scribe_api = new Scribe_API($settings['api-key'], 1 == $settings['security-method']); 
     166            } 
     167        } 
     168 
     169        /// AJAX CALLBACKS 
     170         
     171        public static function ajax_handle_analyze_content() { 
     172            $data = stripslashes_deep($_REQUEST); 
     173             
     174            if(isset($data['scribe-analyze-content-nonce']) && wp_verify_nonce($data['scribe-analyze-content-nonce'], 'scribe-analyze-content')) { 
     175                $post_id = $data['scribe-post-id']; 
     176                 
     177                $title = $data['scribe-title']; 
     178                $description = $data['scribe-description']; 
     179                $content = $data['scribe-content']; 
     180                $headline = $data['scribe-headline']; 
     181                $keyword = self::get_target_term($post_id); 
     182                 
     183                $settings = self::get_settings(); 
     184                $url = $settings['your-url']; 
     185                 
     186                $content_analysis = self::analyze_content($title, $description, $content, $headline, $keyword, $url); 
     187 
     188                if(is_wp_error($content_analysis)) { 
     189                    $results = array('error' => true, 'error_message' => $content_analysis->get_error_message()); 
     190                } else { 
     191                    $request = new stdClass; 
     192                    $request->html_title = $title; 
     193                    $request->description = $description; 
     194                    $request->content = $content; 
     195                    $request->url = $url; 
     196                     
     197                    $content_analysis->request = $request; 
     198                    self::set_content_analysis($content_analysis, $post_id); 
     199                     
     200                    $account = self::$scribe_api->get_user_details(); 
     201                    $results = array('content_analysis' => self::process_content_analysis($content_analysis), 'evaluations_remaining' => number_format_i18n(self::get_content_analysis_evaluations_remaining($account))); 
     202                } 
     203            } else { 
     204                $results = array('error' => true, 'error_message' => __('Invalid request.')); 
     205            } 
     206             
     207            echo json_encode($results); 
     208            exit; 
     209        } 
     210         
     211        public static function ajax_handle_clear_target_term() { 
     212            $data = stripslashes_deep($_REQUEST); 
     213             
     214            if(isset($data['_wpnonce']) && wp_verify_nonce($data['_wpnonce'], 'scribe-clear-target-term')) { 
     215                $post_id = $data['scribe-post-id']; 
     216                $user_id = get_current_user_id(); 
     217                 
     218                self::clear_target_term($post_id, $user_id); 
     219                 
     220                $results = array('error' => false, 'post_id' => $post_id, 'user_id' => $user_id); 
     221            } else { 
     222                $results = array('error' => true, 'error_message' => __('Invalid request.')); 
     223            } 
     224             
     225            echo json_encode(compact('post_id', 'user_id')); 
     226            exit; 
     227        } 
     228         
     229        public static function ajax_handle_set_target_term() { 
     230            $data = stripslashes_deep($_REQUEST); 
     231             
     232            if(isset($data['scribe-set-target-term-nonce']) && wp_verify_nonce($data['scribe-set-target-term-nonce'], 'scribe-set-target-term')) { 
     233                $post_id = $data['scribe-post-id']; 
     234                $target_term = $data['scribe-target-term']; 
     235                $user_id = get_current_user_id(); 
     236                 
     237                self::set_target_term($target_term, $post_id, $user_id); 
     238                 
     239                $results = array('error' => false, 'post_id' => $post_id, 'user_id' => $user_id, 'target_term' => $target_term); 
     240            } else { 
     241                $results = array('error' => true, 'error_message' => __('Invalid request.')); 
     242            } 
     243             
     244            echo json_encode($results); 
     245            exit; 
     246        } 
     247         
     248        public static function ajax_handle_keyword_suggestions() { 
     249            $data = stripslashes_deep($_REQUEST); 
     250            $term = $data['term']; 
     251 
     252            $results = Scribe_Google::get_suggestions($term); 
     253            if(!is_array($results)) { 
     254                $results = array(); 
     255            } 
     256             
     257            $return = array(); 
     258            foreach($results as $result) 
     259                $return[] = array( 'value' => $result['term'], 'label' => sprintf('%s', esc_js( $result['term'] ) ) ); 
     260             
     261            echo json_encode($return); 
     262            exit; 
     263        } 
     264         
     265        public static function ajax_handle_research_keyword() { 
     266            $data = stripslashes_deep($_REQUEST); 
     267             
     268            if(isset($data['scribe-research-keyword-nonce']) && wp_verify_nonce($data['scribe-research-keyword-nonce'], 'scribe-research-keyword')) { 
     269                $post_id = $data['scribe-post-id']; 
     270                $target_keyword = preg_replace('/[^0-9a-zA-Z ]/', '', $data['scribe-keyword']); 
     271                $user_id = get_current_user_id(); 
     272                 
     273                $suggestions = self::get_keyword_suggestions( $target_keyword, $post_id, $user_id ); 
     274                $previous_suggestions = self::get_archived_keyword_suggestions( $post_id, $user_id ); 
     275                 
     276                $account = self::$scribe_api->get_user_details(); 
     277                $results = array('error' => false, 'keyword' => $target_keyword, 'suggestions' => $suggestions, 'previous_suggestions' => $previous_suggestions, 'evaluations_remaining' => number_format_i18n(self::get_keyword_evaluations_remaining($account))); 
     278            } else { 
     279                $results = array('error' => true, 'error_message' => __('Invalid request.')); 
     280            } 
     281 
     282            echo json_encode($results); 
     283            exit; 
     284        } 
     285         
     286        public static function ajax_handle_research_google_plus() { 
     287 
     288            $data = wp_parse_args( stripslashes_deep( $_REQUEST ), array( 
     289                'scribe-google-plus-nonce' => '', 
     290                'scribe-keyword' => '', 
     291            ) ); 
     292 
     293            $results = '<p>' . __( 'Invalid request.', 'scribeseo' ) . '</p>'; 
     294 
     295            if ( wp_verify_nonce( $data['scribe-google-plus-nonce'], 'scribe-research-google-plus' ) ) 
     296                $results = self::build_gplus_comments( $data['scribe-keyword'] ); 
     297 
     298            echo json_encode( $results ); 
     299            exit; 
     300        } 
     301 
     302        public static function ajax_handle_research_google_trends() { 
     303 
     304            $data = wp_parse_args( stripslashes_deep( $_REQUEST ), array( 
     305                'scribe-google-trends-nonce' => '', 
     306                'scribe-keyword' => '', 
     307            ) ); 
     308 
     309            $results = ''; 
     310            $content = '<script type="text/javascript" src="http://www.google.com/trends/embed.js?hl=en-US&q=___KEYWORD___&content=1&cid=TIMESERIES_GRAPH_0&export=5&w=500&h=330"></script> 
     311<script type="text/javascript" src="http://www.google.com/trends/embed.js?hl=en-US&q=___KEYWORD___&content=1&cid=TOP_QUERIES_0_0&export=5&w=300&h=420"></script> 
     312<script type="text/javascript" src="http://www.google.com/trends/embed.js?hl=en-US&q=___KEYWORD___&content=1&cid=RISING_QUERIES_0_0&export=5&w=300&h=420"></script>'; 
     313 
     314 
     315            if ( wp_verify_nonce( $data['scribe-google-trends-nonce'], 'scribe-research-google-trends' ) ) 
     316                $results = str_replace( '___KEYWORD___', $data['scribe-keyword'], $content ); 
     317 
     318            echo '<html><body>' . $results . '</body></html>'; 
     319            exit; 
     320        } 
     321 
     322        public static function ajax_handle_build_links() { 
     323            $data = stripslashes_deep($_REQUEST); 
     324                         
     325            if(isset($data['scribe-build-links-nonce']) && wp_verify_nonce($data['scribe-build-links-nonce'], 'scribe-build-links')) { 
     326                $post_id = isset( $data['scribe-post-id'] ) ?  $data['scribe-post-id'] : 0; 
     327                $type = strip_tags( stripslashes( $data['type'] ) ); 
     328                $keywords = array_filter( $data['scribe-keywords'] ); 
     329 
     330                $analysis = self::build_links( implode( ' + ', $keywords ), $type ); 
     331                if ( is_wp_error( $analysis ) ) { 
     332                    $results = array( 'error' => true, 'error_message' => $analysis->get_error_message() ); 
     333                } else { 
     334                    if ( $type != 'scr' ) 
     335                        $link_analysis = self::get_link_buiding_info( $post_id ); 
     336 
     337                    switch( $type ) { 
     338                        case 'scr': 
     339                            $link_analysis = new stdClass(); 
     340                            $link_analysis->score = $analysis; 
     341                            $link_analysis->linkScore = $analysis; 
     342                            $link_analysis->score_description = sprintf( scribe_get_link_building_score_description( $link_analysis->score ), implode( __( ' and ', 'scribeseo' ), $keywords ) ); 
     343                            break; 
     344                        case 'int': 
     345                            $link_analysis->internalLinks = $analysis; 
     346                            break; 
     347                        case 'ext': 
     348                            $link_analysis->externalLinks = $analysis; 
     349                            break; 
     350                        case 'soc': 
     351                            $link_analysis->googlePlusActivities = $analysis->googlePlusActivities; 
     352                            $link_analysis->twitterProfiles = $analysis->twitterProfiles; 
     353                            break; 
     354                    } 
     355 
     356                    $link_analysis->keywords = $keywords; 
     357 
     358                    self::set_link_building_info($link_analysis, $post_id); 
     359 
     360                    if ( $type == 'soc' ) 
     361                        $results = self::build_social_activity( $keywords, $link_analysis ); 
     362                    else 
     363                        $results = array('error' => false, 'link_analysis' => $link_analysis); 
     364                } 
     365            } else { 
     366                $results = array('error' => true, 'error_message' => __('Invalid request.')); 
     367            } 
     368 
     369            echo json_encode($results); 
     370            exit; 
     371        } 
     372 
     373        /// CALLBACKS 
     374         
     375        public static function add_administrative_interface_items() { 
     376            self::$admin_page_hooks[] = $connections = add_submenu_page(self::SETTINGS_TOP_PAGE_SLUG, __( 'Site Connections', 'scribeseo' ), __( 'Site Connections', 'scribeseo' ), 'manage_options', self::SETTINGS_SUB_PAGE_SLUG_CONNECTIONS, array(__CLASS__, 'display_connections_page')); 
     377            self::$admin_page_hooks[] = $account = add_submenu_page(self::SETTINGS_TOP_PAGE_SLUG, __('Account'), __('Account'), 'manage_options', self::SETTINGS_SUB_PAGE_SLUG_ACCOUNT, array(__CLASS__, 'display_account_page')); 
     378            self::$admin_page_hooks[] = $compatibility = add_submenu_page(self::SETTINGS_TOP_PAGE_SLUG, __('Compatibility'), __('Compatibility'), 'manage_options', self::SETTINGS_SUB_PAGE_SLUG_COMPATIBILITY, array(__CLASS__, 'display_compatibility_page')); 
     379            self::$admin_page_hooks[] = $news = add_submenu_page(self::SETTINGS_TOP_PAGE_SLUG, __('SEO News'), __('SEO News'), 'manage_options', self::SETTINGS_SUB_PAGE_SLUG_NEWS, array(__CLASS__, 'display_news_page')); 
     380            self::$admin_page_hooks[] = $support = add_submenu_page(self::SETTINGS_TOP_PAGE_SLUG, __( 'Scribe Help', 'scribeseo' ), __( 'Scribe Help', 'scribeseo' ), 'manage_options', self::SETTINGS_SUB_PAGE_SLUG_SUPPORT, array(__CLASS__, 'display_support_page')); 
     381             
     382            add_action("load-{$compatibility}", array(__CLASS__, 'process_compatibility_check')); 
     383            add_action("load-{$support}", array(__CLASS__, 'redirect_to_support')); 
     384             
     385             
     386            $settings = self::get_settings(); 
     387            $permission_level = isset( $settings['permissions-level'] ) ? $settings['permissions-level'] : 'manage_options'; 
     388            if ( current_user_can( $permission_level ) ) { 
     389                foreach((array)$settings['post-types'] as $post_type) { 
     390                    add_action("add_meta_boxes_{$post_type}", array(__CLASS__, 'add_meta_boxes')); 
     391                    add_filter("manage_{$post_type}_posts_columns", array(__CLASS__, 'add_scribe_columns')); 
     392                    add_action("manage_{$post_type}_posts_custom_column", array(__CLASS__, 'add_scribe_column_output'), 11, 2); 
     393                } 
     394            } 
     395        } 
     396 
     397        public static function add_meta_boxes($post) { 
     398            add_meta_box( 'scribe-keyword-research', __( 'Scribe Keyword Research', 'scribeseo' ), array( __CLASS__, 'display_keyword_research_meta_box'), $post->post_type, 'side', 'high' ); 
     399            add_meta_box( 'scribe-analysis', __( 'Scribe Content Optimizer', 'scribeseo' ), array( __CLASS__, 'display_analysis_meta_box'), $post->post_type, 'side', 'high' ); 
     400            add_meta_box( 'scribe-link-building', __( 'Scribe Link Building', 'scribeseo' ), array( __CLASS__, 'display_link_building_meta_box'), $post->post_type, 'side', 'high' ); 
     401        } 
     402         
     403        public static function add_scribe_columns($columns) { 
     404            $columns['scribe-doc-score'] = __('Scribe Page Score'); 
     405            $columns['scribe-site-score'] = __('Scribe Site Score'); 
     406            $columns['scribe-keywords'] = __('Scribe Keywords'); 
     407            if ( self::$scribe_has_v3_data ) 
     408                $columns['scribe-v3'] = __('Scribe v3 Score', 'scribeseo' ); 
     409 
     410            return $columns; 
     411        } 
     412 
     413        public static function add_scribe_column_output($column_name, $post_id) { 
     414 
     415            if ( $column_name == 'scribe-v3' ) { 
     416 
     417                $meta = get_post_meta( $post_id, '_ecordia_seo_info', true ); 
     418                if ( ! $meta ) 
     419                    return; 
     420 
     421                $ecordia_seo_info = maybe_unserialize( base64_decode( $meta ) ); 
     422                echo isset( $ecordia_seo_info['GetAnalysisResult']['Analysis']['SeoScore']['Score']['Value'] ) ? esc_html( $ecordia_seo_info['GetAnalysisResult']['Analysis']['SeoScore']['Score']['Value'] ) : ''; 
     423                return;              
     424 
     425            } 
     426 
     427            if ( ! in_array( $column_name, array( 'scribe-doc-score', 'scribe-site-score', 'scribe-keywords' ) ) ) 
     428                return; 
     429 
     430            $content_analysis = self::get_content_analysis($post_id); 
     431            if ( empty( $content_analysis ) ) { 
     432                switch( $column_name ) { 
     433                    case 'scribe-doc-score': 
     434                    case 'scribe-site-score': 
     435                        echo '-'; 
     436                        break; 
     437                    case 'scribe-keywords': 
     438                        echo __('Awaiting Analysis'); 
     439                        break; 
     440                } 
     441                return; 
     442            } 
     443 
     444            switch( $column_name ) { 
     445                case 'scribe-doc-score': 
     446                    if ( empty( $content_analysis->docScore ) ) 
     447                        _e( 'N/A', 'scribeseo' ); 
     448                    else 
     449                        printf( '<span class="%1$s">%2$s</span>', scribe_score_class( (int)$content_analysis->docScore ), (int)$content_analysis->docScore ); 
     450 
     451                    break; 
     452                case 'scribe-site-score': 
     453                    if ( empty( $content_analysis->scribeScore ) ) 
     454                        _e( 'N/A', 'scribeseo' ); 
     455                    else 
     456                        printf( '<span class="%1$s">%2$s</span>', scribe_score_class( (int)$content_analysis->scribeScore, 'site' ), (int)$content_analysis->scribeScore ); 
     457 
     458                    break; 
     459                case 'scribe-keywords': 
     460                    $keywords = self::get_content_analysis_keywords( $content_analysis, ' + ', false ); 
     461                    if ( empty( $keywords ) ) 
     462                        _e( 'None', 'scribeseo' ); 
     463                    else 
     464                        printf( '<span class="scribe-post-column-keywords">%s</span>', esc_html( $keywords ) ); 
     465 
     466                    break; 
     467            } 
     468        } 
     469         
     470        public static function add_tiny_mce_init_instance_callback($initialization_array) { 
     471            $initialization_array['init_instance_callback'] = 'scribe_tiny_mce_add_change_callback'; 
     472             
     473            return $initialization_array; 
     474        } 
     475         
     476        public static function add_upload_iframe_args($url) { 
     477            return add_query_arg(self::$upload_iframe_args, $url); 
     478        } 
     479         
     480        public static function enqueue_administrative_resources($hook) { 
     481            if(!in_array($hook, self::$admin_page_hooks)) { return; } 
     482             
     483            wp_enqueue_style('scribe-bootstrap-necessary', plugins_url('resources/backend/bootstrap/bootstrap-necessary.css', __FILE__), array(), '1.4.0'); 
     484            wp_enqueue_script('scribe-bootstrap-twipsy', plugins_url('resources/backend/bootstrap/bootstrap-twipsy.js', __FILE__), array('jquery'), '1.4.0'); 
     485            wp_enqueue_script('scribe-bootstrap-popover', plugins_url('resources/backend/bootstrap/bootstrap-popover.js', __FILE__), array('jquery', 'scribe-bootstrap-twipsy'), '1.4.0'); 
     486             
     487            // jQuery Autocomplete - Prevent collision with WordPress SEO 
     488            if(!wp_script_is('jquery-ui-autocomplete')) { 
     489                wp_enqueue_script('jquery-ui-autocomplete', plugins_url('resources/backend/jquery-ui-autocomplete.min.js', __FILE__), array('jquery', 'jquery-ui-core'), self::VERSION, true); 
     490            } 
     491            wp_enqueue_script('jquery-ui-autocomplete-html', plugins_url('resources/backend/jquery-ui-autocomplete-html.js', __FILE__), array('jquery-ui-autocomplete'), self::VERSION, true); 
     492             
     493            wp_enqueue_script('scribe-jqplot', plugins_url('resources/backend/jqplot/jquery.jqplot.min.js', __FILE__), array('jquery'), '1.0.0b2_r947'); 
     494            wp_enqueue_script('scribe-jqplot-point-labels', plugins_url('resources/backend/jqplot/plugins/jqplot.pointLabels.min.js', __FILE__), array('scribe-jqplot'), '1.0.0b2_r947'); 
     495            wp_enqueue_script('scribe-backend', plugins_url('resources/backend/scribe.js', __FILE__), array('jquery', 'thickbox', 'jquery-ui-tabs', 'scribe-jqplot', 'suggest'), self::VERSION); 
     496             
     497            wp_enqueue_style('scribe-jqplot', plugins_url('resources/backend/jqplot/jquery.jqplot.min.css', __FILE__), array(), '1.0.0b2_r947'); 
     498            wp_enqueue_style('scribe-backend', plugins_url('resources/backend/scribe.css', __FILE__), array('thickbox'), self::VERSION); 
     499             
     500            $settings = self::get_settings(); 
     501            $seo_tool_settings = ! empty( $settings['seo-tool-settings'] ) && is_object( $settings['seo-tool-settings'] ) ? $settings['seo-tool-settings'] : new stdClass; 
     502 
     503            $configuration = array( 
     504                'content_analysis_label' => __('Content Analysis'), 
     505                'keyword_research_label' => __('Keyword Research'), 
     506             
     507                'content_id' => apply_filters( 'scribeseo_post_content_id', 'content' ), 
     508                'seo_title_id' => ! empty( $seo_tool_settings->title ) ? trim( $seo_tool_settings->title ) : '', 
     509                'seo_description_id' => ! empty( $seo_tool_settings->description ) ? trim( $seo_tool_settings->description ) : '', 
     510                 
     511                'autocomplete_url' => add_query_arg(array('action' => 'scribe_keyword_suggestions'), admin_url('admin-ajax.php')), 
     512            ); 
     513            wp_localize_script('scribe-backend', 'Scribe_SEO_Configuration', $configuration); 
     514 
     515            add_filter('tiny_mce_before_init', array(__CLASS__, 'add_tiny_mce_init_instance_callback')); 
     516        } 
     517         
     518        public static function handle_versions() { 
     519            if ( isset( $_GET['scribe-dismiss-premise-nag'] ) && 1 == $_GET['scribe-dismiss-premise-nag'] ) { 
     520                update_option(self::SHOW_PREMISE_NAG_KEY, 'no'); 
     521                wp_redirect(add_query_arg(array('page' => self::SETTINGS_SUB_PAGE_SLUG_SETTINGS), admin_url('admin.php'))); 
     522                exit; 
     523            } 
     524        } 
     525         
     526        public static function modify_administrative_interface_items() { 
     527            global $menu; 
     528            $menu['58.11'] = array( '', 'read', 'separator-scribe', '', 'wp-menu-separator' ); 
     529        } 
     530         
     531        public static function output_script_that_adds_target_blank_to_scribe_help_item() { 
     532            include( SCRIBE_PLUGIN_DIR . 'views/backend/misc/help-script.php' ); 
     533        } 
     534         
     535        public static function process_compatibility_check() { 
     536            $data = stripslashes_deep($_POST); 
     537             
     538            if(!empty($data['send-scribe-compatibility-report-nonce']) && wp_verify_nonce($data['send-scribe-compatibility-report-nonce'], 'send-scribe-compatibility-report')) { 
     539                $compatibility = $data['scribe-compatibility']; 
     540                 
     541                $send_successful = self::send_test_results($compatibility['name'], $compatibility['email'], $compatibility['issue']); 
     542                 
     543                if($send_successful) { 
     544                    add_settings_error('general', 'settings_updated', __('Your results were successfully sent to the Copyblogger support team.'), 'updated'); 
     545                } else { 
     546                    add_settings_error('general', 'settings_updated', __('There was an issue sending your report. Please copy the below information and email it directly to <a href="mailto:support@copyblogger.com">support@copyblogger.com</a>.'), 'error'); 
     547                } 
     548                set_transient('settings_errors', get_settings_errors(), 30); 
     549                 
     550                $location = add_query_arg(array('page' => self::SETTINGS_SUB_PAGE_SLUG_COMPATIBILITY, 'settings-updated' => 'true'), admin_url('admin.php')); 
     551                wp_redirect($location); 
     552                 
     553                exit; 
     554            } 
     555        } 
     556         
     557        public static function redirect_to_support() { 
     558            wp_redirect( 'http://my.scribecontent.com/help/default.aspx' ); 
     559            exit; 
     560        } 
     561         
     562        public static function return_analysis_tabs($tabs) { 
     563            $tabs = array( 
     564                'scribe-analysis-keywords' => __('Keyword Analysis'), 
     565                'scribe-analysis-document' => __('Page Analysis'), 
     566                'scribe-analysis-tags' => __('Tags'), 
     567                'scribe-analysis-help' => __('Help'), 
     568            ); 
     569             
     570            return $tabs; 
     571        } 
     572         
     573        public static function return_keyword_tabs($tabs) { 
     574            $tabs = array( 
     575                'scribe-keyword-suggestions' => __('Suggestions') 
     576            ); 
     577             
     578            if($_GET['tab'] == 'scribe-keyword-details') { 
     579                $tabs['scribe-keyword-details'] = __('Details'); 
     580            } 
     581             
     582            return $tabs; 
     583        } 
     584         
     585        public static function return_link_tabs($tabs) { 
     586            return array(); 
     587        } 
     588         
     589        public static function sanitize_scribe_settings($settings) { 
     590            $settings['post-types'] = is_array($settings['post-types']) ? $settings['post-types'] : array(); 
     591             
     592            return $settings; 
     593        } 
     594         
     595        /// DISPLAY CALLBACKS 
     596         
     597        //// META BOXES 
     598         
     599        public static function display_analysis_meta_box($post) { 
     600            $content_analysis = self::get_content_analysis($post->ID); 
     601            $remaining_evaluations = self::get_content_analysis_evaluations_remaining(self::get_account()); 
     602            $content_analysis->keywordList = self::get_content_analysis_keywords( $content_analysis ); 
     603 
     604            include( SCRIBE_PLUGIN_DIR . 'views/backend/meta-boxes/content-analysis.php' ); 
     605        } 
     606         
     607        public static function display_keyword_research_meta_box( $post ) { 
     608 
     609            $previous_keywords = self::get_archived_keyword_suggestions( $post->ID ); 
     610            $target_term = self::get_target_term( $post->ID ); 
     611            $remaining_evaluations = self::get_keyword_evaluations_remaining( self::get_account() ); 
     612 
     613            include( SCRIBE_PLUGIN_DIR . 'views/backend/meta-boxes/keyword-research.php' ); 
     614        } 
     615         
     616        public static function display_link_building_meta_box($post) { 
     617            $content_analysis = self::get_content_analysis($post->ID); 
     618            if ( ! empty( $content_analysis ) ) 
     619                $content_score = $content_analysis->docScore; 
     620 
     621            $link_building_info = self::get_link_buiding_info($post->ID); 
     622            $link_terms = self::get_content_analysis_keywords( $content_analysis ); 
     623            $link_terms_array = self::get_content_analysis_keywords( $content_analysis, false ); 
     624             
     625            include( SCRIBE_PLUGIN_DIR . 'views/backend/meta-boxes/link-building.php' ); 
     626        } 
     627         
     628        //// SETTINGS 
     629        public static function display_connections_page() { 
     630            $social_activity = self::build_social_activity ( '' );           
     631            add_meta_box('scribe-main-connections', __( 'Site Connections', 'scribeseo' ), array(__CLASS__, 'display_connections_meta_box'), 'scribe-connections', 'normal'); 
     632             
     633            include( SCRIBE_PLUGIN_DIR . 'views/backend/link-building/site-connections.php' ); 
     634        } 
     635        public static function display_connections_meta_box($account) { 
     636            include( SCRIBE_PLUGIN_DIR . 'views/backend/meta-boxes/connections.php' ); 
     637        } 
     638         
     639        public static function display_account_page() { 
     640            $settings = self::get_settings(); 
     641            $account = self::get_account($settings['api-key']); 
     642             
     643            add_meta_box('scribe-main-account', __('Account Information'), array(__CLASS__, 'display_account_meta_box'), 'scribe-account', 'normal'); 
     644             
     645            include( SCRIBE_PLUGIN_DIR . 'views/backend/settings/account.php' ); 
     646        } 
     647         
     648        public static function display_account_meta_box($account) { 
     649            include( SCRIBE_PLUGIN_DIR . 'views/backend/meta-boxes/account.php' ); 
     650        } 
     651         
     652        public static function display_compatibility_page() { 
     653            add_meta_box('scribe-information-compatibility', __('Your Information'), array(__CLASS__, 'display_compatibility_info_meta_box'), 'scribe-compatibility', 'normal'); 
     654            add_meta_box('scribe-results-compatibility', __('Your Install Details'), array(__CLASS__, 'display_compatibility_results_meta_box'), 'scribe-compatibility', 'normal'); 
     655             
     656            include( SCRIBE_PLUGIN_DIR . 'views/backend/settings/compatibility.php' ); 
     657        } 
     658 
     659        public static function display_compatibility_info_meta_box() { 
     660            $user = wp_get_current_user(); 
     661             
     662            include( SCRIBE_PLUGIN_DIR . 'views/backend/meta-boxes/compatibility-info.php' ); 
     663        } 
     664         
     665        public static function display_compatibility_results_meta_box() { 
     666            $test_results = self::get_test_results(); 
     667             
     668            include( SCRIBE_PLUGIN_DIR . 'views/backend/meta-boxes/compatibility-results.php' ); 
     669        } 
     670         
     671        public static function display_news_page() { 
     672            $feed = fetch_feed(self::SEO_NEWS_FEED_URL); 
     673             
     674            include( SCRIBE_PLUGIN_DIR . 'views/backend/settings/news.php' ); 
     675        } 
     676         
     677        public static function display_settings_page() { 
     678            add_meta_box('scribe-main-settings', __('Scribe Settings'), array(__CLASS__, 'display_settings_meta_box'), 'scribe-settings', 'normal'); 
     679             
     680            $dismiss_nag_url = add_query_arg(array('page' => self::SETTINGS_SUB_PAGE_SLUG_SETTINGS, 'scribe-dismiss-premise-nag' => 1), admin_url('admin.php')); 
     681            $show_nag = 'no' != get_option(self::SHOW_PREMISE_NAG_KEY); 
     682             
     683            include( SCRIBE_PLUGIN_DIR . 'views/backend/settings/settings.php' ); 
     684        } 
     685         
     686        public static function display_settings_meta_box() { 
     687            $settings = self::get_settings(); 
     688            $dependencies = self::get_available_dependencies(); 
     689 
     690            include( SCRIBE_PLUGIN_DIR . 'views/backend/meta-boxes/settings.php' ); 
     691        } 
     692 
     693        public static function get_query_domain() { 
     694 
     695            $settings = self::get_settings(); 
     696            $domain = parse_url( $settings['your-url'], PHP_URL_HOST ); 
     697 
     698            return $domain ? $domain : $settings['your-url']; 
     699 
     700        } 
     701        //// IFRAMES 
     702         
     703        ///// ANALYSIS 
     704         
     705        public static function display_analysis_tabs() { 
     706            wp_enqueue_style('media'); 
     707            return wp_iframe('scribe_analysis_iframe_callback'); 
     708        } 
     709         
     710        public static function display_analysis_iframe() { 
     711            add_filter('media_upload_tabs', array(__CLASS__, 'return_analysis_tabs')); 
     712            media_upload_header(); 
     713             
     714            $data = stripslashes_deep($_REQUEST); 
     715            $post_id = $data['post_id']; 
     716             
     717            if ( empty( $post_id ) ) { 
     718                include( SCRIBE_PLUGIN_DIR . 'views/backend/misc/popup-error.php' ); 
     719                return; 
     720            } 
     721 
     722            $tab = $data['tab']; 
     723            $content_analysis = self::get_content_analysis($post_id); 
     724 
     725            switch($tab) { 
     726                case 'scribe-analysis-document': 
     727 
     728                    $serp_url = self::get_permalink( $_REQUEST['post_id'] ); 
     729 
     730                    include( SCRIBE_PLUGIN_DIR . 'views/backend/content-analysis/document-analysis.php' ); 
     731                    break; 
     732                case 'scribe-analysis-tags': 
     733                    $tags = array(); 
     734                    foreach( $content_analysis->tags as $tag ) 
     735                        $tags[$tag] = false; 
     736 
     737                    foreach( $content_analysis->keywords as $keyword ) { 
     738 
     739                        if ( isset( $tags[$keyword->text] ) && $keyword->kwl != 4 ) 
     740                            $tags[$keyword->text] = true; 
     741 
     742                    } 
     743                    include( SCRIBE_PLUGIN_DIR . 'views/backend/content-analysis/tags.php' ); 
     744                    break; 
     745                case 'scribe-analysis-help': 
     746                    include( SCRIBE_PLUGIN_DIR . 'views/backend/content-analysis/help.php' ); 
     747                    break; 
     748                case 'scribe-analysis-keywords': 
     749                default: 
     750                    $keywords = array(); 
     751                    foreach( $content_analysis->keywords as $keyword ) { 
     752 
     753                        $keyword->padding = 0; 
     754                        $keywords[$keyword->kwr] = $keyword; 
     755 
     756                    } 
     757 
     758                    ksort( $keywords, SORT_NUMERIC ); 
     759                    // check for overlap 
     760                    $maxkwr = max( array_keys( $keywords ) ); 
     761                    for( $i = 0; $i < $maxkwr; $i++ ) { 
     762                        if ( ! isset( $keywords[$i] ) ) 
     763                            continue; 
     764 
     765                        for( $j = $i + 1; $j <= $maxkwr; $j++ ) { 
     766                            if ( ! isset( $keywords[$j] ) ) 
     767                                continue; 
     768 
     769                            if ( abs( $keywords[$i]->kwc - $keywords[$j]->kwc ) < 0.4 && abs( $keywords[$i]->kws - $keywords[$j]->kws ) < 1.0 ) 
     770                                $keywords[$j]->padding++; 
     771 
     772                        } 
     773                    } 
     774                    $content_analysis->keywords = $keywords; 
     775                    $document_tab_url = add_query_arg( array( 'post_id' => $post_id, 'type' => 'scribe-analysis-keywords', 'tab' => 'scribe-analysis-document', 'scribe-content-analysis-review' => 'true' ), admin_url( 'media-upload.php' ) ); 
     776                    include( SCRIBE_PLUGIN_DIR . 'views/backend/content-analysis/keyword-analysis.php' ); 
     777                    break; 
     778            } 
     779?> 
     780<script type="text/javascript"> 
     781// style the media tab 
     782 
     783jQuery(document).ready(function($) { 
     784    jQuery('ul#sidemenu').addClass('scribe-content-analysis-tabs'); 
     785    jQuery('ul#sidemenu li a').addClass('nav-tab').filter('.current').addClass('nav-tab-active'); 
     786}); 
     787</script> 
     788<?php 
     789        } 
     790         
     791        ///// KEYWORDS 
     792         
     793        public static function display_keyword_tabs() { 
     794            wp_enqueue_style('media'); 
     795            return wp_iframe('scribe_keyword_iframe_callback'); 
     796        } 
     797         
     798        public static function display_keyword_iframe() { 
     799            add_filter('media_upload_tabs', array(__CLASS__, 'return_keyword_tabs')); 
     800            media_upload_header(); 
     801             
     802            $data = wp_parse_args( stripslashes_deep( $_REQUEST ), array( 
     803                'post_id' => '', 
     804                'tab' => '', 
     805                'scribe-details-keyword' => '', 
     806                'scribe-force-details-keyword-refresh' => '', 
     807                'scribe-previous-keywords' => '', 
     808                'scribe-details-previous' => '', 
     809                'scribe-keyword' => '', 
     810            ) ); 
     811            $post_id = $data['post_id']; 
     812            $user_id = get_current_user_id(); 
     813             
     814            if ( empty( $post_id ) ) { 
     815                include( SCRIBE_PLUGIN_DIR . 'views/backend/misc/popup-error.php' ); 
     816                return; 
     817            } 
     818 
     819            $tab = $data['tab']; 
     820            switch($tab) { 
     821                case 'scribe-keyword-details': 
     822                    $queried_keyword = $data['scribe-details-keyword']; 
     823 
     824                    $details = self::get_keyword_details($queried_keyword, 'true' == $data['scribe-force-details-keyword-refresh']); 
     825 
     826                    include( SCRIBE_PLUGIN_DIR . 'views/backend/keyword-research/details.php' ); 
     827                    break; 
     828                case 'scribe-keyword-suggestions': 
     829                default: 
     830                    $previous = $data['scribe-previous-keywords'] == 'true' || $data['scribe-details-previous'] == '1'; 
     831 
     832                    $target_term = self::get_target_term( $post_id, $user_id ); 
     833                    if($previous) { 
     834                        $keywords = self::get_archived_keyword_suggestions( $post_id, $user_id ); 
     835                        $title = __('Previous Keyword Suggestions'); 
     836                    } else { 
     837                        $queried_keyword = urldecode($data['scribe-keyword']); 
     838                        $keywords = self::get_keyword_suggestions( $queried_keyword, $post_id, $user_id ); 
     839 
     840                        $title = sprintf( __( 'Keyword Suggestions for <em>%1$s</em>', 'scribeseo' ), esc_html( $queried_keyword ) ); 
     841                    } 
     842 
     843                    include( SCRIBE_PLUGIN_DIR . 'views/backend/keyword-research/suggestions.php' ); 
     844                    break; 
     845            } 
     846        } 
     847         
     848        //// LINK BUILDING 
     849         
     850        public static function display_link_building_tabs() { 
     851            wp_enqueue_style('media'); 
     852            return wp_iframe('scribe_link_building_iframe_callback'); 
     853        } 
     854         
     855        public static function display_link_building_iframe() { 
     856            add_filter('media_upload_tabs', array(__CLASS__, 'return_link_tabs')); 
     857            media_upload_header(); 
     858                         
     859            $data = stripslashes_deep($_REQUEST); 
     860            $post_id = $data['post_id']; 
     861            $user_id = get_current_user_id(); 
     862             
     863            $content_analysis = self::get_content_analysis( $post_id ); 
     864            $content_analysis_keywords = self::get_content_analysis_keywords( $content_analysis, false ); 
     865            $target_term = self::get_target_term( $post_id ); 
     866 
     867            $link_building_info = null; 
     868            if ( isset( $data['scribe-link-building-review'] ) && 1 == $data['scribe-link-building-review'] ) 
     869                $link_building_info = self::get_link_buiding_info($post_id); 
     870 
     871            $link_building_complete = isset( $link_building_info->keywords ) ? 'true' : 'false'; 
     872 
     873            if ( ! is_object( $link_building_info ) ) 
     874                $link_building_info = new stdClass; 
     875 
     876//          $social_activity = self::build_social_activity ( '', $link_building_info ); 
     877            $link_building_keywords = isset( $link_building_info->keywords ) ? $link_building_info->keywords : array(); 
     878            if ( isset( $_GET['scribe-link-building-term'] ) ) { 
     879 
     880                $initial_term = urldecode( $_GET['scribe-link-building-term'] ); 
     881                if ( ! in_array( $initial_term, $link_building_keywords ) ) 
     882                    $link_building_keywords[] = ucwords( $initial_term ); 
     883 
     884            } 
     885 
     886            include( SCRIBE_PLUGIN_DIR . 'views/backend/link-building/analysis.php' ); 
     887        } 
     888         
     889        /// POST META 
     890         
     891        //// WEB CONNECTOR 
     892         
     893        private static function get_post_meta_item($post_id, $item) { 
     894            if(empty($post_id)) { 
     895                return false; 
     896            } 
     897             
     898            $value = apply_filters('scribe_pre_get_post_meta_item', false, $post_id, $item); 
     899             
     900            if(empty($value)) { 
     901                $settings = self::get_settings(); 
     902                if(!is_object($settings['seo-tool-settings'])) { 
     903                    return false; 
     904                } 
     905                 
     906                $property = "meta_storage_{$item}"; 
     907                switch($settings['seo-tool-settings']->meta_storage) { 
     908                    case 'flat': 
     909                        $value = get_post_meta($post_id, $settings['seo-tool-settings']->{$property}, true); 
     910                        break; 
     911                    case 'array': 
     912                        $components = explode('.', $settings['seo-tool-settings']->{$property}); 
     913                        $value = get_post_meta($post_id, $settings['seo-tool-settings']->meta_storage_key, true); 
     914                         
     915                        while(!empty($components)) { 
     916                            $piece = array_shift($components); 
     917                            $value = $value[$piece]; 
     918                        } 
     919                        break; 
     920                } 
     921            } 
     922             
     923            return $value; 
     924        } 
     925         
     926        private static function set_post_meta_item($post_id, $item, $value) { 
     927            if(empty($post_id)) { 
     928                return false; 
     929            } 
     930             
     931            $handled = apply_filters('scribe_set_post_meta_item', false, $post_id, $item, $value); 
     932            if($handled) { 
     933                return true; 
     934            } 
     935             
     936            $settings = self::get_settings(); 
     937            if(!is_object($settings['seo-tool-settings'])) { 
     938                return false; 
     939            } 
     940             
     941            $property = "meta_storage_{$item}"; 
     942            switch($settings['seo-tool-settings']->meta_storage) { 
     943                case 'flat': 
     944                    update_post_meta($post_id, $settings['seo-tool-settings']->{$property}, $value); 
     945                    break; 
     946                case 'array': 
     947                    $components = explode('.', $settings['seo-tool-settings']->{$property}); 
     948                    $existing = get_post_meta($post_id, $settings['seo-tool-settings']->meta_storage_key, true); 
     949                     
     950                    $array_access_string = ''; 
     951                    while(!empty($components)) { 
     952                        $piece = array_shift($components); 
     953                        $array_access_string .= "['{$piece}']"; 
     954                    } 
     955                    eval("\$existing$array_access_string = \$value;"); 
     956                     
     957                    update_post_meta($post_id, $settings['seo-tool-settings']->meta_storage_key, $existing); 
     958                    break; 
     959            } 
     960             
     961            return true; 
     962        } 
     963         
     964        public static function get_post_meta_description($post_id) { 
     965            return self::get_post_meta_item($post_id, 'description'); 
     966        } 
     967         
     968        public static function get_post_meta_title($post_id) { 
     969            return self::get_post_meta_item($post_id, 'title'); 
     970        } 
     971         
     972        public static function set_post_meta_description($post_id, $post_meta_description) { 
     973            return self::set_post_meta_item($post_id, 'description', $post_meta_description); 
     974        } 
     975         
     976        public static function set_post_meta_title($post_id, $post_meta_title) { 
     977            return self::set_post_meta_item($post_id, 'title', $post_meta_title); 
     978        } 
     979         
     980        /// USER META 
     981         
     982        //// CONTENT ANALYSIS 
     983         
     984        private static function get_content_analysis_key() { 
     985            return '_' . self::CONTENT_ANALYSIS_BASE_KEY; 
     986        } 
     987         
     988        private static function get_content_analysis_user_key( $post_id, $prefix = true ) { 
     989            global $wpdb; 
     990            return ( $prefix ? $wpdb->prefix : '' ) . self::CONTENT_ANALYSIS_BASE_KEY . '_' . $post_id; 
     991        } 
     992         
     993        private static function get_content_analysis($post_id = null, $user_id = null) { 
     994 
     995            global $post; 
     996 
     997            if ( empty( $post_id ) ) 
     998                $post_id = $post->ID; 
     999             
     1000            $content_analysis = get_post_meta( $post_id, self::get_content_analysis_key(), true ); 
     1001 
     1002            if ( empty( $content_analysis ) ) { 
     1003 
     1004                if ( empty( $user_id ) ) 
     1005                    $user_id = get_current_user_id(); 
     1006 
     1007                $content_analysis = get_user_option( self::get_content_analysis_user_key( $post_id, false ), $user_id ); 
     1008 
     1009                if ( is_object( $content_analysis ) ) 
     1010                    self::set_content_analysis( $content_analysis, $post_id ); 
     1011                else 
     1012                    $content_analysis = false; 
     1013                 
     1014            } 
     1015             
     1016            return self::process_content_analysis( $content_analysis ); 
     1017        } 
     1018 
     1019        private static function get_content_analysis_keywords( $content_analysis, $sep = ' + ', $all = true ) { 
     1020 
     1021            if ( empty( $content_analysis->keywords ) || ! is_array( $content_analysis->keywords ) ) 
     1022                return $sep ? '' : array(); 
     1023 
     1024            $keywords = array(); 
     1025            foreach( $content_analysis->keywords as $keyword ) { 
     1026 
     1027                if ( $all || $keyword->kwl == 1 ) 
     1028                    $keywords[] = $keyword->text; 
     1029 
     1030            } 
     1031 
     1032            $keywords = array_unique( $keywords ); 
     1033            if ( $sep ) 
     1034                return ucwords( implode( $sep, $keywords ) ); 
     1035 
     1036            return $keywords; 
     1037 
     1038        } 
     1039        private static function process_content_analysis( $content_analysis ) { 
     1040            if ( ! empty( $content_analysis->KWS ) && is_array( $content_analysis->KWS ) ) 
     1041                usort( $content_analysis->KWS, array( __CLASS__, 'sort_by_keyword_score' ) ); 
     1042             
     1043            if ( ! empty( $content_analysis->request ) && is_object( $content_analysis->request ) ) { 
     1044                $bing = new stdClass; 
     1045                $bing->engine = 'bing'; 
     1046                 
     1047                $google = new stdClass; 
     1048                $google->engine = 'google'; 
     1049                 
     1050                $content_analysis->serps = array($bing, $google); 
     1051                 
     1052                $content_analysis->serp_title = $content_analysis->request->html_title; 
     1053                if(strlen($content_analysis->serp_title) > 69) { 
     1054                    $content_analysis->serp_title = substr($content_analysis->serp_title, 0, 69) . '...'; 
     1055                } 
     1056                 
     1057                $content_analysis->serp_description = $content_analysis->request->description; 
     1058                if(strlen($content_analysis->serp_description) > 140) { 
     1059                    $content_analysis->serp_description = substr($content_analysis->serp_description, 0, 140) . '...'; 
     1060                } 
     1061                 
     1062                $content_analysis->serp_url = $content_analysis->request->url; 
     1063            } 
     1064             
     1065            return $content_analysis; 
     1066        } 
     1067         
     1068        public static function sort_by_keyword_score($a, $b) { 
     1069            return $b->KwC - $a->KwC; 
     1070        } 
     1071         
     1072        private static function set_content_analysis($content_analysis, $post_id = null ) { 
     1073 
     1074            global $post; 
     1075 
     1076            if ( ! is_object( $content_analysis ) ) 
     1077                return; 
     1078 
     1079            if ( empty( $post_id ) ) 
     1080                $post_id = $post->ID; 
     1081             
     1082            $key = self::get_content_analysis_key(); 
     1083             
     1084            update_post_meta( $post_id, $key, $content_analysis ); 
     1085 
     1086        } 
     1087         
     1088        //// LINK BUILDING 
     1089         
     1090        private static function get_link_building_info_key() { 
     1091            return '_' . self::LINK_BUILDING_INFO_BASE_KEY; 
     1092        } 
     1093         
     1094        private static function get_link_building_info_user_key( $post_id, $prefix = true ) { 
     1095            global $wpdb; 
     1096            return ( $prefix ? $wpdb->prefix : '' ) . self::LINK_BUILDING_INFO_BASE_KEY . '_' . $post_id; 
     1097        } 
     1098         
     1099        private static function get_link_buiding_info( $post_id = null, $user_id = null ) { 
     1100 
     1101            global $post; 
     1102 
     1103            if ( empty( $post_id ) ) 
     1104                $post_id = $post->ID; 
     1105             
     1106            $link_building_info = get_post_meta( $post_id, self::get_link_building_info_key(), true ); 
     1107             
     1108            if ( empty( $link_building_info ) ) { 
     1109 
     1110                if ( empty( $user_id ) ) 
     1111                    $user_id = get_current_user_id(); 
     1112 
     1113                $link_building_info = get_user_option( self::get_link_building_info_user_key( $post_id, false ), $user_id ); 
     1114 
     1115                if ( is_object( $link_building_info ) ) 
     1116                    self::set_link_building_info( $link_building_info, $post_id ); 
     1117                else 
     1118                    $link_building_info = false; 
     1119                 
     1120            } 
     1121             
     1122            return $link_building_info; 
     1123        } 
     1124         
     1125        private static function set_link_building_info( $link_building_info, $post_id = null ) { 
     1126 
     1127            global $post; 
     1128 
     1129            if ( ! is_object( $link_building_info ) ) 
     1130                return; 
     1131 
     1132            if ( empty( $post_id ) ) 
     1133                $post_id = $post->ID; 
     1134             
     1135            update_post_meta( $post_id, self::get_link_building_info_key(), $link_building_info ); 
     1136             
     1137        } 
     1138         
     1139        //// TARGET TERM 
     1140         
     1141        private static function clear_target_term($post_id = null, $user_id = null) { 
     1142            if(empty($post_id)) { 
     1143                global $post; 
     1144                $post_id = $post->ID; 
     1145            } 
     1146             
     1147            if(empty($user_id)) { 
     1148                $user_id = get_current_user_id(); 
     1149            } 
     1150             
     1151            $key = self::get_target_term_key( $post_id, false ); 
     1152            delete_user_option( $user_id, $key ); 
     1153        } 
     1154         
     1155        private static function get_target_term_key( $post_id, $prefix = true ) { 
     1156            global $wpdb; 
     1157 
     1158            return ( $prefix ? $wpdb->prefix : '' ) . self::TARGET_TERM_BASE_KEY . $post_id; 
     1159        } 
     1160         
     1161        private static function get_target_term($post_id = null, $user_id = null) { 
     1162            if(empty($post_id)) { 
     1163                global $post; 
     1164                $post_id = $post->ID; 
     1165            } 
     1166             
     1167            if(empty($user_id)) { 
     1168                $user_id = get_current_user_id(); 
     1169            } 
     1170             
     1171            $key = self::get_target_term_key($post_id); 
     1172             
     1173            $target_term = wp_cache_get($key, $user_id); 
     1174            if(false === $target_term) { 
     1175                $target_term = trim( get_user_option( self::get_target_term_key( $post_id, false ), $user_id ) ); 
     1176                wp_cache_set($key, $target_term, $user_id, time() + self::CACHE_PERIOD); 
     1177            } 
     1178             
     1179            return $target_term; 
     1180        } 
     1181         
     1182        private static function set_target_term($target_term, $post_id = null, $user_id = null) { 
     1183            global $post; 
     1184            if ( empty( $post_id ) ) 
     1185                $post_id = $post->ID; 
     1186             
     1187            if ( empty( $user_id ) ) 
     1188                $user_id = get_current_user_id(); 
     1189             
     1190            $key = self::get_target_term_key($post_id); 
     1191              
     1192            update_user_option( $user_id, self::get_target_term_key( $post_id, false ), $target_term ); 
     1193            wp_cache_set($key, $target_term, $user_id, time() + self::CACHE_PERIOD); 
     1194        } 
     1195         
     1196        /// SETTINGS 
     1197         
     1198        public static function get_settings() { 
     1199            $settings = wp_cache_get(self::SETTINGS_KEY); 
     1200             
     1201            if(!is_array($settings)) { 
     1202                $settings = wp_parse_args(get_option(self::SETTINGS_KEY, self::$default_settings), self::$default_settings); 
     1203                wp_cache_set(self::SETTINGS_KEY, $settings, null, time() + self::CACHE_PERIOD); 
     1204            } 
     1205             
     1206            return $settings; 
     1207        } 
     1208         
     1209        private static function set_settings($settings) { 
     1210            if(is_array($settings)) { 
     1211                $settings = wp_parse_args($settings, self::$default_settings); 
     1212                update_option(self::SETTINGS_KEY, $settings); 
     1213                wp_cache_set(self::SETTINGS_KEY, $settings, null, time() + self::CACHE_PERIOD); 
     1214            } 
     1215        } 
     1216        public static function get_option( $key, $setting = null ) { 
     1217         
     1218            /** 
     1219             * Get setting. The default is set here, once, so it doesn't have to be 
     1220             * repeated in the function arguments for accesspress_option() too. 
     1221             */ 
     1222            $setting = $setting ? $setting : self::SETTINGS_KEY; 
     1223         
     1224            /** setup caches */ 
     1225            static $settings_cache = array(); 
     1226            static $options_cache = array(); 
     1227         
     1228            /** Short circuit */ 
     1229            $pre = apply_filters( 'scribe_pre_get_option_'.$key, false, $setting ); 
     1230            if ( false !== $pre ) 
     1231                return $pre; 
     1232         
     1233            /** Check options cache */ 
     1234            if ( isset( $options_cache[$setting][$key] ) ) { 
     1235         
     1236                // option has been cached 
     1237                return $options_cache[$setting][$key]; 
     1238         
     1239            } 
     1240         
     1241            /** check settings cache */ 
     1242            if ( isset( $settings_cache[$setting] ) ) { 
     1243         
     1244                // setting has been cached 
     1245                $options = apply_filters( 'scribe_options', $settings_cache[$setting], $setting ); 
     1246         
     1247            } else { 
     1248         
     1249                // set value and cache setting 
     1250                $options = $settings_cache[$setting] = apply_filters( 'scribe_options', get_option( $setting ), $setting ); 
     1251         
     1252            } 
     1253         
     1254            // check for non-existent option 
     1255            if ( ! is_array( $options ) || ! array_key_exists( $key, (array) $options ) ) { 
     1256         
     1257                // cache non-existent option 
     1258                $options_cache[$setting][$key] = ''; 
     1259         
     1260                return ''; 
     1261            } 
     1262         
     1263            // option has been cached, cache option 
     1264            $options_cache[$setting][$key] = is_array( $options[$key] ) ? stripslashes_deep( $options[$key] ) : stripslashes( wp_kses_decode_entities( $options[$key] ) ); 
     1265         
     1266            return $options_cache[$setting][$key]; 
     1267         
     1268        } 
     1269        public static function admin_redirect( $page = '', $query_args = array() ) { 
     1270         
     1271            if ( ! $page ) 
     1272                return; 
     1273         
     1274            $url = html_entity_decode( menu_page_url( $page, 0 ) ); 
     1275         
     1276            foreach ( (array) $query_args as $key => $value ) { 
     1277                if ( empty( $key ) && empty( $value ) ) { 
     1278                    unset( $query_args[$key] ); 
     1279                } 
     1280            } 
     1281         
     1282            $url = add_query_arg( $query_args, $url ); 
     1283         
     1284            wp_redirect( esc_url_raw( $url ) ); 
     1285         
     1286        } 
     1287         
     1288        /// API DELEGATION 
     1289         
     1290        //// ACCOUNT 
     1291         
     1292        private static function get_account($api_key = null) { 
     1293            $settings = self::get_settings(); 
     1294             
     1295            if(empty($api_key)) { 
     1296                if(empty(self::$scribe_api_account)) { 
     1297                    self::$scribe_api_account = self::$scribe_api->get_user_details(); 
     1298                } 
     1299                 
     1300                $result = self::$scribe_api_account; 
     1301            } else { 
     1302                $scribe_api = new Scribe_API($api_key, 1 == $settings['security-method']); 
     1303                $result = $scribe_api->get_user_details(); 
     1304            } 
     1305 
     1306            return $result; 
     1307        } 
     1308         
     1309        private static function get_content_analysis_evaluations_remaining( $account ) { 
     1310 
     1311            return self::get_evaluations_remaining( $account, 'ContentAnalysis' ); 
     1312 
     1313        } 
     1314         
     1315        private static function get_keyword_evaluations_remaining($account) { 
     1316 
     1317            return self::get_evaluations_remaining( $account, 'KeywordIdeaResearch' ); 
     1318 
     1319        } 
     1320 
     1321        private static function get_evaluations_remaining( $account, $type ) { 
     1322 
     1323            if ( is_wp_error( $account ) || empty( $type ) ) 
     1324                return 0; 
     1325 
     1326            foreach( $account->evaluations as $evaluation_information ) { 
     1327 
     1328                if ( $type == $evaluation_information->type ) 
     1329                    return $evaluation_information->remaining; 
     1330 
     1331            } 
     1332 
     1333            return 0; 
     1334 
     1335        } 
     1336        //// CONTENT ANALYSIS 
     1337         
     1338        private static function analyze_content($title, $description, $content, $headline, $keyword, $url) { 
     1339            return self::$scribe_api->analyze_content($title, $description, $content, $headline, $keyword, $url); 
     1340        } 
     1341         
     1342        private static function get_keyword_recommendations($possessed_keys) { 
     1343 
     1344            $desired_keys = array(); 
     1345            $desired_keys[0] = array( 
     1346                'KwET' => __( 'Add the keyword to the HTML title tag of your content.', 'scribeseo' ), 
     1347                'KwETP' => __( 'Add the keyword to the beginning of your HTML title tag.', 'scribeseo' ), 
     1348                'KwEM' => __( 'Add the keyword to the META DESCRIPTION tag of your content.', 'scribeseo' ), 
     1349                'KwEMP' => __( 'Add the keyword to the beginning of the META DESCRIPTION tag of your content.', 'scribeseo' ), 
     1350                'KwED' => __( 'Reduce the number of times you use the keyword in your content.', 'scribeseo' ), 
     1351                'KwEH' => __( 'Include the keyword in the title attribute of your hyperlink/anchor text.', 'scribeseo' ), 
     1352                'KwELF' => __( 'Add this keyword more frequently to the page.', 'scribeseo' ), 
     1353            ); 
     1354            $desired_keys[1] = array( 
     1355                'KwET' => __( 'Add the keywords to the HTML title tag of your content.', 'scribeseo' ), 
     1356                'KwETP' => __( 'Add the keywords to the beginning of your HTML title tag.', 'scribeseo' ), 
     1357                'KwEM' => __( 'Add the keywords to the META DESCRIPTION tag of your content.', 'scribeseo' ), 
     1358                'KwEMP' => __( 'Add the keywords to the beginning of the META DESCRIPTION tag of your content.', 'scribeseo' ), 
     1359                'KwED' => __( 'Reduce the number of times you use the keywords in your content.', 'scribeseo' ), 
     1360                'KwEH' => __( 'Include the keywords in the title attribute of your hyperlink/anchor text.', 'scribeseo' ), 
     1361                'KwELF' => __( 'Add these keywords more frequently to the page.', 'scribeseo' ), 
     1362            ); 
     1363             
     1364             
     1365            $index = ( count( explode(' ', $keyword ) ) > 1 ? 1 : 0 ); 
     1366            $recommendations = array(); 
     1367            foreach( $desired_keys[0] as $desired_key => $recommendation ) { 
     1368 
     1369                if ( in_array( $desired_key, $possessed_keys ) ) 
     1370                    $recommendations[$desired_key] = $desired_keys[$index][$desired_key]; 
     1371 
     1372            } 
     1373             
     1374            return $recommendations; 
     1375        } 
     1376         
     1377        private static function get_content_recommendations($possessed_keys) { 
     1378            $desired_keys = array( 
     1379                'TitleLen' => __('The HTML title of the page contains less than three words, consider adding more words to the HTML title.'), 
     1380                'TitleCharLen' => __('The HTML title of the page is too long, consider shortening the title to less than 72 characters.'), 
     1381                'MetaCharLen' => __('The META DESCRIPTION is too long, consider shortening the description to less than 165 characters.'), 
     1382                'BodyLen' => __('The page is too short, consider adding more words to the page.'), 
     1383                'Hyper' => __('No hyperlinks were found in the page, consider adding hyperlinks to relevant terms.'), 
     1384                'HyperLen' => __('No hyperlinks were found in the first part of the page, consider adding a hyperlink to the first paragraph.'), 
     1385                'NoPKW' => __( 'No Primary Keywords were found in your content. See the information under Improve Keyword Rank to improve the identification of a keyword.', 'scribeseo' ), 
     1386            ); 
     1387             
     1388            $recommendations = array(); 
     1389            foreach($desired_keys as $desired_key => $recommendation) { 
     1390                if(in_array($desired_key, $possessed_keys)) { 
     1391                    $recommendations[$desired_key] = $recommendation; 
     1392                } 
     1393            } 
     1394             
     1395            return $recommendations; 
     1396        } 
     1397         
     1398        //// DEPENDENCIES 
     1399         
     1400        public static function get_available_dependencies() { 
     1401            $available_dependencies = self::$scribe_api->get_supported_dependencies(); 
     1402 
     1403            $all_plugins = get_plugins(); 
     1404            $active_plugins = array(); 
     1405            foreach( (array) $all_plugins as $plugin_file => $plugin_data ) { 
     1406 
     1407                if ( is_plugin_active( $plugin_file ) ) 
     1408                    $active_plugins[] = $plugin_data['Name']; 
     1409 
     1410            } 
     1411 
     1412            foreach( (array) $available_dependencies->plugins as $key => $value ) { 
     1413 
     1414                $display_name = empty( $value->display_name ) ? $value->name : $value->display_name; 
     1415                if ( ! in_array( $display_name, $active_plugins ) ) 
     1416                    unset( $available_dependencies->plugins[$key] ); 
     1417 
     1418            } 
     1419 
     1420            return $available_dependencies; 
     1421 
     1422        } 
     1423         
     1424        //// KEYWORD RESEARCH 
     1425 
     1426        private static function get_keyword_details_key($keyword) { 
     1427            return self::KEYWORD_DETAILS_BASE_KEY . md5($keyword); 
     1428        } 
     1429         
     1430        private static function get_keyword_details($keyword, $force_refresh) { 
     1431            $option_key = self::get_keyword_details_key($keyword); 
     1432             
     1433            $details = wp_cache_get($option_key); 
     1434            if(empty($details) || $force_refresh) { 
     1435                $details = get_option($option_key); 
     1436             
     1437                if(empty($details) || $force_refresh) { 
     1438                    $settings = self::get_settings(); 
     1439                     
     1440                    $facebook_key = 'testapikey'; 
     1441                    $details = self::$scribe_api->get_keyword_details( $facebook_key, $keyword, self::get_query_domain() ); 
     1442                     
     1443                    if(!is_wp_error($details)) { 
     1444                        $cached_details = clone $details; 
     1445                        $cached_details->cached = true; 
     1446                        update_option($option_key, $cached_details); 
     1447                    } 
     1448                } else { 
     1449                    $cached_details = $details; 
     1450                } 
     1451                wp_cache_set($option_key, $cached_details, null, time() + self::CACHE_PERIOD); 
     1452            } 
     1453             
     1454            return $details; 
     1455        } 
     1456         
     1457        private static function get_keyword_suggestions_key($keyword) { 
     1458            if(empty($user_id)) { 
     1459                $user_id = get_current_user_id(); 
     1460            } 
     1461             
     1462            return self::KEYWORD_SUGGESTIONS_TRANSIENT_BASE_KEY . md5($keyword); 
     1463        } 
     1464         
     1465        private static function get_keyword_suggestions($keyword, $post_id, $user_id = null) { 
     1466            if ( empty( $user_id ) ) 
     1467                $user_id = get_current_user_id(); 
     1468 
     1469            $transient_key = self::get_keyword_suggestions_key($keyword); 
     1470            $suggestions = get_transient($transient_key); 
     1471 
     1472            if(empty($suggestions)) { 
     1473                $suggestions = self::$scribe_api->get_keyword_suggestions( $keyword ); 
     1474                if(!is_wp_error($suggestions)) { 
     1475                    foreach($suggestions as $suggestion) { 
     1476                        $suggestion->time_retrieved = current_time('timestamp'); 
     1477                    } 
     1478                    self::update_archived_keyword_suggestions($suggestions, $post_id, $user_id); 
     1479                     
     1480                    set_transient($transient_key, $suggestions, self::KEYWORD_SUGGESTIONS_TRANSIENT_TIME); 
     1481                } 
     1482            } 
     1483             
     1484            return $suggestions; 
     1485        } 
     1486         
     1487        private static function get_archived_keyword_suggestions( $post_id, $user_id = null ) { 
     1488            global $wpdb; 
     1489 
     1490            if ( empty( $user_id ) ) 
     1491                $user_id = get_current_user_id(); 
     1492 
     1493            $base_key = self::PREVIOUS_KEYWORD_SUGGESTIONS_KEY . $post_id; 
     1494            $keywords = wp_cache_get( $wpdb->prefix . $base_key, $user_id ); 
     1495             
     1496            if(false === $keywords) { 
     1497                $keywords = get_user_option( $base_key, $user_id ); 
     1498                wp_cache_set( $wpdb->prefix . $base_key, $keywords, $user_id, time() + self::CACHE_PERIOD ); 
     1499            } 
     1500             
     1501            $keywords = array_filter((array)$keywords); 
     1502            return $keywords; 
     1503        } 
     1504         
     1505        private static function update_archived_keyword_suggestions( $keywords, $post_id, $user_id = null ) { 
     1506            global $wpdb; 
     1507 
     1508            if ( empty( $user_id ) ) 
     1509                $user_id = get_current_user_id(); 
     1510 
     1511            if ( ! is_array( $keywords ) ) 
     1512                return; 
     1513 
     1514            $archived = self::get_archived_keyword_suggestions( $post_id, $user_id ); 
     1515            $archived = $keywords + $archived; 
     1516            $archived = array_filter(array_slice($archived, 0, 20)); 
     1517 
     1518            $base_key = self::PREVIOUS_KEYWORD_SUGGESTIONS_KEY . $post_id; 
     1519 
     1520            update_user_option( $user_id, $base_key, $archived ); 
     1521            wp_cache_set( $wpdb->prefix . $base_key, $keywords, $user_id, time() + self::CACHE_PERIOD ); 
     1522 
     1523        } 
     1524 
     1525        /// G+ Activity 
     1526 
     1527        private static function build_social_activity( $keyword, $links = null ) { 
     1528 
     1529            if ( empty( $keyword ) && empty( $links ) ) 
     1530                return ''; 
     1531 
     1532            if ( empty( $links ) ) 
     1533                $links = self::build_links( $keyword, 'soc' ); 
     1534 
     1535            if ( is_wp_error( $links ) ) 
     1536                return '<p>' . $links->get_error_message() . '</p>'; 
     1537 
     1538            if ( ( empty( $links->googlePlusActivities ) && empty( $links->twitterProfiles ) ) || ( ! is_array( $links->googlePlusActivities ) && ! is_array( $links->twitterProfiles ) ) ) 
     1539                return __( '<p>No Activity</p>', 'scribeseo' ); 
     1540 
     1541            $plus_format = '<li class="scribe-google-plus-item"><a href="http://plus.google.com/u/0/%1$s" title="%2$s" class="img" target="_blank"><img src="%3$s" /></a><h4><a href="http://plus.google.com/u/0/%1$s" title="%2$s" target="_blank">%2$s</a></h4> %4$s</li>'; 
     1542            $twitter_format = '<li class="scribe-google-plus-item"><a href="http://twitter.com/%1$s" class="img" target="_blank"><img src="%2$s" /></a><h4><a href="http://twitter.com/%1$s" target="_blank">%1$s</a> <span class="scribe-google-plus-klout-score">%4$d</span></h4> %3$s</li>'; 
     1543            $output = '<ul class="scribe-google-plus-items">'; 
     1544 
     1545            foreach( (array)$links->googlePlusActivities as $activity ) 
     1546                $output .= sprintf( $plus_format, esc_url( $activity->profileId ), esc_attr( $activity->profileDisplayName ), esc_url( $activity->profileImageUrl ), esc_html( $activity->content ) ); 
     1547 
     1548            foreach( (array)$links->twitterProfiles as $activity ) 
     1549                $output .= sprintf( $twitter_format, esc_url( $activity->profileDisplayName ), esc_url( $activity->profileImageUrl ), esc_html( $activity->content ), $activity->klout ); 
     1550 
     1551            $output .= '</ul>'; 
     1552 
     1553            return $output; 
     1554 
     1555        } 
     1556 
     1557        private static function build_gplus_comments( $keyword, $comments = null ) { 
     1558 
     1559            if ( empty( $keyword ) && empty( $comments ) ) 
     1560                return ''; 
     1561 
     1562            if ( empty( $comments ) ) 
     1563                $comments = self::get_gplus_comments( $keyword ); 
     1564 
     1565            if ( is_wp_error( $comments ) ) 
     1566                return '<p>' . $comments->get_error_message() . '</p>'; 
     1567 
     1568            if ( empty( $comments->comments ) || ! is_array( $comments->comments ) ) 
     1569                return '<p>' . __( 'No Activity', 'scribeseo' ) . '</p>'; 
     1570 
     1571            $plus_format = '<li class="scribe-google-plus-item"><a href="http://plus.google.com/u/0/%1$s" title="%2$s" class="img" target="_blank"><img src="%3$s" /></a><div class="scribe-google-plus-comment"><span class="scribe-google-plus-content">%4$s</span> <p>%5$s <span class="scribe-google-plus-author"><a href="http://plus.google.com/u/0/%1$s" title="%2$s" target="_blank">%2$s</a></span></p></div></li>'; 
     1572            $output = '<ul class="scribe-google-plus-items">'; 
     1573            foreach( (array)$comments->comments as $comment ) 
     1574                $output .= sprintf( $plus_format, esc_url( $comment->profileId ), esc_attr( $comment->profileDisplayName ), esc_url( $comment->profileImageUrl ), esc_html( $comment->content ), __( 'Posted by', 'scribeseo' ) ); 
     1575 
     1576            $output .= '</ul>'; 
     1577 
     1578            return $output; 
     1579 
     1580        } 
     1581 
     1582        private static function get_gplus_comments( $keyword ) { 
     1583 
     1584            return self::$scribe_api->get_comment_analysis( $keyword, self::get_query_domain() ); 
     1585 
     1586        } 
     1587 
     1588        /// Twitter activity 
     1589 
     1590        private static function build_twitter_activity( $links ) { 
     1591 
     1592            if ( empty( $links ) ) 
     1593                return ''; 
     1594 
     1595            if ( is_wp_error( $links ) ) 
     1596                return '<p>' . $links->get_error_message() . '</p>'; 
     1597 
     1598            if ( empty( $links->twitterProfiles ) || ! is_array( $links->twitterProfiles ) ) 
     1599                return '<p>' . __( 'No Activity', 'scribeseo' ) . '</p>'; 
     1600 
     1601            $twitter_format = '<li class="scribe-google-plus-item"><a href="http://twitter.com/%1$s" class="img" target="_blank"><img src="%2$s" /></a><h4><a href="http://twitter.com/%1$s" target="_blank">%2$s</a></h4> %3$s</li>'; 
     1602            $output = '<ul class="scribe-google-plus-items">'; 
     1603            foreach( (array)$links->twitterProfiles as $activity ) 
     1604                $output .= sprintf( $twitter_format, esc_url( $activity->profileDisplayName ), esc_url( $activity->profileImageUrl ), esc_html( $activity->content ) ); 
     1605 
     1606            $output .= '</ul>'; 
     1607 
     1608            return $output; 
     1609 
     1610        } 
     1611 
     1612        /// LINK BUILDING 
     1613         
     1614        private static function build_links( $keyword, $type ) { 
     1615 
     1616            return self::$scribe_api->get_link_analysis( $keyword, self::get_query_domain(), $type ); 
     1617 
     1618        } 
     1619         
     1620        /// SUPPORT SCRIPT 
     1621         
     1622        private static function get_test_results() { 
     1623            $scribe_support = new Scribe_Support; 
     1624            return $scribe_support->get_test_results(); 
     1625        } 
     1626         
     1627        private static function send_test_results($name, $email, $issue) { 
     1628            $name = trim($name); 
     1629            $email = trim($email); 
     1630            $issue = trim($issue); 
     1631             
     1632            if(empty($name)) { 
     1633                $name = __('Unknown User'); 
     1634            } 
     1635             
     1636            if(!is_email($email)) { 
     1637                return false; 
     1638            } 
     1639             
     1640            if(!empty($issue)) { 
     1641                $issue = sprintf(__("They also added the following comments:\n\n===\n\n%s\n\n==="), $issue); 
     1642            } 
     1643             
     1644            $site_name = get_bloginfo('name'); 
     1645            $site_domain = home_url('/'); 
     1646            $email_subject = sprintf(__('Scribe Compatibility Check from %1$s at %2$s'), $name, $site_name); 
     1647 
     1648            $test_results = self::get_test_results(); 
     1649            $test_results_text = ''; 
     1650            foreach($test_results as $test_result) { 
     1651                $test_results_text .= "**{$test_result['name']}**\n{$test_result['value']}\n\n\n"; 
     1652            } 
     1653            $test_results_text = trim($test_results_text); 
     1654             
     1655            $email_body = sprintf(__('Support Team, 
     1656 
     1657This message is the result of running the Scribe SEO Compatibility Check on %1$s (located at %2$s). The user provided the name %3$s and the email address %4$s. %5$s 
     1658 
     1659The test results from the compatibility checker were as follows: 
     1660 
     1661%6$s 
     1662 
     1663Regards, 
     1664Scribe SEO Plugin'), $site_name, $site_domain, $name, $email, $issue, $test_results_text); 
     1665 
     1666            $email_to = 'support@copyblogger.com'; 
     1667            $email_headers = array(sprintf('From: %s', $email)); 
     1668            return wp_mail($email_to, $email_subject, $email_body, $email_headers); 
     1669        } 
     1670         
     1671        /// UTILITY 
     1672 
     1673        public static function get_upload_iframe_src($type, $tab, $args) { 
     1674            if(empty($tab)) { 
     1675                $tab = $type; 
     1676            } 
     1677             
     1678            if(!is_array($args)) { 
     1679                $args = array(); 
     1680            } 
     1681             
     1682            if(empty($args['post_id']) && !empty($_REQUEST['post_id'])) { 
     1683                $args['post_id'] = $_REQUEST['post_id']; 
     1684            } 
     1685 
     1686            add_filter("{$type}_upload_iframe_src", array(__CLASS__, 'add_upload_iframe_args')); 
     1687            self::$upload_iframe_args = array_merge(array('type' => $type, 'tab' => $tab), $args); 
     1688            $url = get_upload_iframe_src($type); 
     1689            self::$upload_iframe_args = null; 
     1690            remove_filter("{$type}_upload_iframe_src", array(__CLASS__, 'add_upload_iframe_args')); 
     1691            return $url; 
     1692        } 
     1693 
     1694        public static function sort_by_annual_volume($a, $b) { 
     1695            return $b->av - $a->av; 
     1696        } 
     1697         
     1698        public static function verify_scribe_api_key( $key ) { 
     1699 
     1700            $account = self::get_account( $key ); 
     1701            return ! is_wp_error( $account ); 
     1702 
     1703        } 
     1704 
     1705        public static function clear_keyword_research_cache() { 
     1706 
     1707            global $wpdb; 
     1708 
     1709            $key = $wpdb->get_blog_prefix() . substr( self::PREVIOUS_KEYWORD_SUGGESTIONS_KEY, 0, -1 ) . '\_%'; 
     1710            $cached_ids = $wpdb->get_col( $wpdb->prepare( "SELECT umeta_id FROM {$wpdb->usermeta} WHERE meta_key LIKE %s", $key ) ); 
     1711 
     1712            if ( empty( $cached_ids ) ) 
     1713                return; 
     1714 
     1715            foreach( $cached_ids as $id ) 
     1716                $wpdb->delete( $wpdb->usermeta, array( 'umeta_id' => $id ), array( '%d' ) ); 
     1717 
     1718        } 
     1719 
     1720        public static function formatting_allowedtags() { 
     1721         
     1722            return array( 
     1723                    'a'          => array( 'href' => array(), 'title' => array(), ), 
     1724                    'b'          => array(), 
     1725                    'blockquote' => array(), 
     1726                    'br'         => array(), 
     1727                    'div'        => array( 'align' => array(), 'class' => array(), 'style' => array(), ), 
     1728                    'em'         => array(), 
     1729                    'i'          => array(), 
     1730                    'p'          => array( 'align' => array(), 'class' => array(), 'style' => array(), ), 
     1731                    'span'       => array( 'align' => array(), 'class' => array(), 'style' => array(), ), 
     1732                    'strong'     => array(), 
     1733         
     1734            ); 
     1735         
     1736        } 
     1737 
     1738        private static function get_permalink( $post_id ) { 
     1739 
     1740            $post = get_post( $post_id ); 
     1741            if ( empty( $post ) ) 
     1742                return home_url( '/' ); 
     1743 
     1744            if ( $post->post_status == 'publish' ) 
     1745                return get_permalink( $post_id ); 
     1746 
     1747            $rewritecode = array( 
     1748                '%year%', 
     1749                '%monthnum%', 
     1750                '%day%', 
     1751                '%hour%', 
     1752                '%minute%', 
     1753                '%second%', 
     1754                $leavename? '' : '%postname%', 
     1755                '%post_id%', 
     1756                '%category%', 
     1757                '%author%', 
     1758                $leavename? '' : '%pagename%', 
     1759            ); 
     1760 
     1761            $unixtime = strtotime( $post->post_date ? $post->post_date : time() ); 
     1762            $permalink = get_option('permalink_structure'); 
     1763 
     1764            $category = ''; 
     1765            if ( strpos($permalink, '%category%') !== false ) { 
     1766                $cats = get_the_category($post->ID); 
     1767                if ( $cats ) { 
     1768                    usort($cats, '_usort_terms_by_ID'); // order by ID 
     1769                    $category = $cats[0]->slug; 
     1770                    if ( $parent = $cats[0]->parent ) 
     1771                        $category = get_category_parents($parent, false, '/', true) . $category; 
     1772                } 
     1773                // show default category in permalinks, without 
     1774                // having to assign it explicitly 
     1775                if ( empty($category) ) { 
     1776                    $default_category = get_category( get_option( 'default_category' ) ); 
     1777                    $category = is_wp_error( $default_category ) ? '' : $default_category->slug; 
     1778                } 
     1779            } 
     1780 
     1781            $author = ''; 
     1782            if ( strpos($permalink, '%author%') !== false ) { 
     1783                $authordata = get_userdata($post->post_author); 
     1784                $author = $authordata->user_nicename; 
     1785            } 
     1786 
     1787            $date = explode(" ",date('Y m d H i s', $unixtime)); 
     1788            $rewritereplace = 
     1789            array( 
     1790                $date[0], 
     1791                $date[1], 
     1792                $date[2], 
     1793                $date[3], 
     1794                $date[4], 
     1795                $date[5], 
     1796                $post->post_name ? $post->post_name : sanitize_title_with_dashes( $post->post_title ), 
     1797                $post->ID, 
     1798                $category, 
     1799                $author, 
     1800                $post->post_name, 
     1801            ); 
     1802            $permalink = home_url( str_replace($rewritecode, $rewritereplace, $permalink) ); 
     1803            $permalink = user_trailingslashit($permalink, 'single'); 
     1804 
     1805            return $permalink; 
     1806        } 
     1807        // update database function 
     1808        private static function update() { 
     1809 
     1810            global $wpdb; 
     1811 
     1812            $settings = self::get_settings(); 
     1813            $version = isset( $settings['version'] ) ? $settings['version'] : '4.0'; 
     1814            // stop if the version is already the current one  
     1815            if ( $version == self::VERSION ) 
     1816                return; 
     1817 
     1818            // 4.0.7 
     1819            if ( version_compare( $version, '4.0.8'. '<=' ) ) { 
     1820 
     1821                $scribe_user_meta = $wpdb->get_results( "SELECT umeta_id, user_id, meta_key FROM {$wpdb->usermeta} WHERE meta_key like '_scribe%'" ); 
     1822                if ( empty( $scribe_user_meta ) ) 
     1823                    return self::update_settings_version(); 
     1824 
     1825                foreach( $scribe_user_meta as $key => $meta_row ) { 
     1826 
     1827                    $scribe_user_meta[$key]->post_id = preg_replace( '|(\D+)|', '', $meta_row->meta_key ); 
     1828                    if ( ! is_multisite() ) 
     1829                        continue; 
     1830 
     1831                    // try to eliminate any that we know do not belong to this site 
     1832                    if ( ! $scribe_user_meta[$key]->post_id || ! user_can( $meta_row->user_id, 'edit_posts' ) ) { 
     1833 
     1834                        unset( $scribe_user_meta[$key] ); 
     1835                        continue; 
     1836 
     1837                    } 
     1838                    $post = get_post( $scribe_user_meta[$key]->post_id ); 
     1839                    if ( empty( $post ) || in_array( $post->post_type, array( 'attachment', 'nav_menu_item', 'revision' ) ) ) 
     1840                        unset( $scribe_user_meta[$key] ); 
     1841 
     1842                } 
     1843 
     1844                $new_meta_keys = array( 
     1845                    'content' => $wpdb->prefix . self::CONTENT_ANALYSIS_BASE_KEY, 
     1846                    'link' => $wpdb->prefix . self::LINK_BUILDING_INFO_BASE_KEY, 
     1847                    'target' => $wpdb->prefix . self::TARGET_TERM_BASE_KEY, 
     1848                    'previous' => $wpdb->prefix . self::PREVIOUS_KEYWORD_SUGGESTIONS_KEY, 
     1849                ); 
     1850                     
     1851                foreach( $scribe_user_meta as $meta_row ) { 
     1852 
     1853                    $key_parts = explode( '_', trim( $meta_row->meta_key, '_' ) ); 
     1854                    if ( ! isset( $new_meta_keys[$key_parts[1]] ) ) 
     1855                        continue; 
     1856 
     1857                    $wpdb->update( $wpdb->usermeta, array( 'meta_key' => $new_meta_keys[$key_parts[1]] . $meta_row->post_id ), array( 'umeta_id' => $meta_row->umeta_id ) ); 
     1858                } 
     1859 
     1860            } // 4.0.8 
     1861 
     1862            self::update_settings_version(); 
     1863 
     1864        } 
     1865        private static function update_settings_version() { 
     1866 
     1867            $settings = self::get_settings(); 
     1868            $settings['version'] = self::VERSION; 
     1869            self::set_settings( $settings ); 
     1870 
     1871            return true; 
     1872             
     1873        } 
     1874        // plugin update handling 
     1875        public static function delete_plugin_info() { 
     1876 
     1877            delete_transient( self::PLUGIN_INFO_CACHE_KEY ); 
     1878 
     1879        } 
     1880        public static function check_plugin_updates( $option ) { 
     1881            $info = get_transient( self::PLUGIN_INFO_CACHE_KEY ); 
     1882 
     1883            if ( ! $info ) { 
     1884 
     1885                $info = self::$scribe_api->get_latest_plugin_info(); 
     1886                if( !$info ) 
     1887                    return $option; 
     1888 
     1889                set_transient(  self::PLUGIN_INFO_CACHE_KEY, $info, self::CACHE_PERIOD ); 
     1890            } 
     1891 
     1892            $basename = plugin_basename( __FILE__ ); 
     1893            if( ! isset( $option->response[$basename] ) || ! is_object( $option->response[$basename] ) ) 
     1894                $option->response[$basename] = new stdClass(); 
     1895     
     1896            //Empty response means that the key is invalid. Do not queue for upgrade 
     1897            if( ! is_object( $info ) || ! isset( $info->version ) || version_compare( self::VERSION, $info->version, '>=' ) ) { 
     1898                unset( $option->response[$basename] ); 
     1899            } else { 
     1900                $option->response[$basename]->url = $info->homepage; 
     1901                $option->response[$basename]->slug = $info->slug; 
     1902                $option->response[$basename]->package = $info->download_link; 
     1903                $option->response[$basename]->new_version = $info->version; 
     1904                $option->response[$basename]->id = "0"; 
     1905            } 
     1906     
     1907            return $option; 
     1908        } 
     1909        public static function is_menu_page( $pagehook = '' ) { 
     1910 
     1911            global $page_hook; 
     1912 
     1913            if ( isset( $page_hook ) && $page_hook == $pagehook ) 
     1914                return true; 
     1915 
     1916            /* May be too early for $page_hook */ 
     1917            if ( isset( $_REQUEST['page'] ) && $_REQUEST['page'] == $pagehook ) 
     1918                return true; 
     1919 
     1920            return false; 
     1921 
     1922        } 
     1923 
    241924    } 
     1925     
     1926    // IFrame Callbacks 
     1927     
     1928    function scribe_analysis_iframe_callback() { 
     1929        Scribe_SEO::display_analysis_iframe(); 
     1930    } 
     1931     
     1932    function scribe_keyword_iframe_callback() { 
     1933        Scribe_SEO::display_keyword_iframe(); 
     1934    } 
     1935     
     1936    function scribe_link_building_iframe_callback() { 
     1937        Scribe_SEO::display_link_building_iframe(); 
     1938    } 
     1939     
     1940     
     1941    add_action( 'init', array( 'Scribe_SEO', 'init' ) ); 
    251942} 
    26  
    27 if (!class_exists('Ecordia')) { 
    28     class Ecordia { 
    29  
    30         var $version = '3.0.11'; 
    31         var $_meta_seoInfo = '_ecordia_seo_info'; 
    32         var $_meta_linkResearchInfo = '_ecordia_link_research'; 
    33         var $_option_ecordiaSettings = '_ecordia_settings'; 
    34         var $_option_cachedUserResults = '_ecordia_cachedUserResults'; 
    35         var $_option_keywordResearchList = '_ecordia_keyword_research_history'; 
    36  
    37         var $settings = null; 
    38         var $_utility_DependencyUrl = 'http://vesta.ecordia.com/optimizer/docs/scribe-dependencies.xml'; 
    39         var $_possible_Item = array(); 
    40         var $_possible_Items = array(); 
    41         var $_possible_CurrentType = array(); 
    42         var $_possible_CurrentData = array(); 
    43  
    44         function Ecordia() { 
    45             $this->addActions(); 
    46             $this->addFilters(); 
    47  
    48             wp_register_style('ecordia', plugins_url('resources/ecordia.css', __FILE__), array(), $this->version); 
    49             wp_register_script('ecordia', plugins_url('resources/ecordia.js', __FILE__), array('jquery'), $this->version); 
    50         } 
    51  
    52         function addActions() { 
    53             add_action('admin_head', array(&$this, 'addAdminHeaderCode')); 
    54             add_action('admin_init', array(&$this, 'settingsSave')); 
    55             add_action('admin_menu', array(&$this, 'addAdminInterfaceItems')); 
    56             add_action('manage_posts_custom_column', array(&$this, 'displayEcordiaPostsColumns'), 10, 2); 
    57             add_action('manage_pages_custom_column', array(&$this, 'displayEcordiaPostsColumns'), 10, 2); 
    58             add_action('save_post', array(&$this, 'saveSerializedValueToPreventOverriding'), 10, 2); 
    59             add_action('update_scribe_user_info', array(&$this, 'getScheduledUserInfo')); 
    60  
    61             $settings = $this->getSettings(); 
    62             if ( empty($settings['api-key'])) { 
    63                 add_action('admin_notices', array(&$this, 'displayAdminNoticeRegardingAPIKey')); 
    64             } 
    65  
    66             // Thickbox interfaces 
    67             add_action('media_upload_ecordia-score', array(&$this, 'displayThickboxInterface')); 
    68             add_action('media_upload_ecordia-keyword-analysis', array(&$this, 'displayThickboxInterface')); 
    69             add_action('media_upload_ecordia-change-keywords', array(&$this, 'displayThickboxInterface')); 
    70             add_action('media_upload_ecordia-keyword-alternates', array(&$this, 'displayThickboxInterface')); 
    71             add_action('media_upload_ecordia-tags', array(&$this, 'displayThickboxInterface')); 
    72             add_action('media_upload_ecordia-serp', array(&$this, 'displayThickboxInterface')); 
    73             add_action('media_upload_ecordia-seo-best-practices', array(&$this, 'displayThickboxInterface')); 
    74             add_action('media_upload_ecordia-error', array(&$this, 'displayThickboxInterface')); 
    75             add_action('media_upload_ecordia-debug', array(&$this, 'displayThickboxInterface')); 
    76  
    77             // Keyword Research Thickbox 
    78             add_action('media_upload_ecordia-keyword-research', array(&$this, 'displayKeywordResearchThickboxInterface')); 
    79             add_action('media_upload_ecordia-keyword-research-review', array(&$this, 'displayKeywordResearchThickboxInterface')); 
    80  
    81             // Link Building Thickbox 
    82             add_action('media_upload_ecordia-link-building-external', array(&$this, 'displayLinkBuildingResearchThickboxInterface')); 
    83             add_action('media_upload_ecordia-link-building-internal', array(&$this, 'displayLinkBuildingResearchThickboxInterface')); 
    84             add_action('media_upload_ecordia-link-building-social', array(&$this, 'displayLinkBuildingResearchThickboxInterface')); 
    85  
    86             // AJAX stuff 
    87             add_action('wp_ajax_ecordia_analyze', array(&$this, 'analyzeSeoContent')); 
    88             add_action('wp_ajax_ecordia_user_info', array(&$this, 'fetchUserInfo')); 
    89             add_action('wp_ajax_ecordia_keyword_alternates', array(&$this, 'getKeywordAlternates')); 
    90             add_action('wp_ajax_scribe_keyword_research', array(&$this, 'getKeywordResearch')); 
    91             add_action('wp_ajax_scribe_link_building_research', array(&$this, 'getLinkBuildingResearch')); 
    92         } 
    93  
    94         function addFilters() { 
    95             add_filter('manage_posts_columns', array(&$this, 'addEcordiaPostsColumns')); 
    96             add_filter('manage_pages_columns', array(&$this, 'addEcordiaPostsColumns')); 
    97         } 
    98  
    99         function addAdminHeaderCode() { 
    100             global $pagenow; 
    101             if (false !== strpos($pagenow, 'post') || false !== strpos($pagenow, 'page') || false !== strpos($pagenow, 'media-upload')) { 
    102                 include ('views/admin-header.php'); 
    103             } 
    104         } 
    105  
    106         function addAdminInterfaceItems() { 
    107             add_options_page(__('Scribe Settings'), __('Scribe Settings'), 'manage_options', 'scribe', array(&$this, 'displaySettingsPage')); 
    108  
    109             $permission = $this->getPermissionLevel(); 
    110  
    111             if(current_user_can($permission)) { 
    112                 $dependency = $this->getEcordiaDependency(); 
    113                 $title = __('Scribe Content Optimizer'); 
    114                 if ( empty($dependency)) { 
    115                     $displayFunction = array(&$this, 'displayMetaBoxError'); 
    116                     $title .= __(' &mdash; <span class="ecordia-error">Error</span>'); 
    117                 } else { 
    118                     $displayFunction = array(&$this, 'displayMetaBox'); 
    119                 } 
    120  
    121                 foreach($this->getSupportedPostTypes() as $type) { 
    122                     add_meta_box('ecordia-keyword-research', __('Scribe Keyword Research'), array(&$this, 'displayKeywordResearchMetaBox'), $type, 'side', 'core'); 
    123                     add_meta_box('ecordia', $title, $displayFunction, $type, 'side', 'core'); 
    124                     add_meta_box('ecordia-link-building', __('Scribe Link Building'), array(&$this, 'displayLinkBuildingMetaBox'), $type, 'side', 'core'); 
    125                 } 
    126             } 
    127  
    128             global $pagenow; 
    129             if (false !== strpos($pagenow, 'post') || false !== strpos($pagenow, 'page') || false !== strpos($pagenow, 'scribe') || $_GET['page'] == 'scribe' || false !== strpos($pagenow, 'edit')) { 
    130                 wp_enqueue_style('ecordia'); 
    131                 wp_enqueue_script('ecordia'); 
    132                 add_filter('tiny_mce_before_init', array(&$this, 'addInitInstanceCallback')); 
    133             } 
    134         } 
    135  
    136         function addEcordiaPostsColumns($columns) { 
    137             $authorKey = array_search('author', array_keys($columns)); 
    138             //removed preserve_keys parameter for lt PHP5.0.2 
    139             $before = array_slice($columns, 0, $authorKey + 1); 
    140             $before['seo-score'] = __('Scribe Optimizer'); 
    141             $before['primary-seo-keywords'] = __('Primary Keywords'); 
    142  
    143             //removed preserve_keys parameter for lt PHP5.0.2 
    144             $after = array_slice($columns, $authorKey + 1, count($columns) + 1); 
    145             $columns = array_merge($before, $after); 
    146             return $columns; 
    147         } 
    148  
    149         function addInitInstanceCallback($initArray) { 
    150             $initArray['init_instance_callback'] = 'ecordia_addTinyMCEEvent'; 
    151             return $initArray; 
    152         } 
    153  
    154         function analyzeSeoContent() { 
    155             $title = $this->sanitizeForCall(stripslashes($_POST['title'])); 
    156             $description = $this->sanitizeForCall(stripslashes($_POST['description'])); 
    157             $content = $this->sanitizeForCall(stripslashes($_POST['content'])); 
    158             $url = get_permalink($_POST['pid']); 
    159             if(empty($url)) { 
    160                 $url = site_url('/'); 
    161             } 
    162             $pid = intval($_POST['pid']); 
    163             $settings = $this->getSettings(); 
    164             $results = array('success'=>false, 'message'=>__(''), 'extended'=>__('')); 
    165  
    166             if ( empty($settings['api-key'])) { 
    167                 $results['message'] = __('You need to set your API key.'); 
    168                 $results['extended'] = 'show-settings-prompt'; 
    169             } else { 
    170                 $optimizer = new EcordiaContentOptimizer($settings['api-key'], $settings['use-ssl']); 
    171                 $optimizer->GetAnalysis($title, $description, $content, $url); 
    172                 if ($optimizer->hasError()) { 
    173                     $results['message'] = __('Analysis Failure'); 
    174                     $results['extended'] = $optimizer->getErrorMessage(); 
    175                 } else { 
    176                     $this->getUserInfo(true); 
    177                     $results = $optimizer->getRawResults(); 
    178                     $serialized = base64_encode(serialize($results)); 
    179                     update_post_meta($pid, $this->_meta_seoInfo, $serialized); 
    180                     $results['success'] = true; 
    181                     ob_start(); 
    182                     global $post; 
    183                     $post = get_post($pid); 
    184                     include ('views/meta-box/after.php'); 
    185                     $results['meta'] = ob_get_clean(); 
    186  
    187                     ob_start(); 
    188                     include('views/link-building/meta-box-after.php'); 
    189                     $results['linkMeta'] = ob_get_clean(); 
    190                 } 
    191             } 
    192  
    193  
    194             print json_encode($results); 
    195             exit(); 
    196         } 
    197         function sanitizeForCall($value) { 
    198             return str_replace(array('<![CDATA[',']]>'),array('',''),trim($value)); 
    199         } 
    200  
    201         function getKeywordAlternatesInfo($seed) { 
    202             $settings = $this->getSettings(); 
    203             $keywords = new EcordiaKeywordAlternates($settings['api-key'], $settings['use-ssl']); 
    204             $keywords->GetAlternateKeywords($seed); 
    205             return $keywords; 
    206         } 
    207  
    208         function getKeywordAlternates() { 
    209             $seed = stripslashes($_POST['seed']); 
    210             $keywords = $this->getKeywordAlternatesInfo($seed); 
    211             if($keywords->hasError()) { 
    212                 ?> 
    213 <p><?php _e('Error retrieving results.'); ?></p> 
    214                 <?php 
    215             } else { 
    216                 $info = $keywords->getRawResults(); 
    217                 $keywordAlternates = $info['GetKeywordAlternatesResult']['AlternateKeywords']['Keyword']; 
    218                 include('views/popup/alternate-keyword-table.php'); 
    219             } 
    220             exit(); 
    221         } 
    222  
    223         function getKeywordResearch() { 
    224             $results = array('error'=>true); 
    225             $data = stripslashes_deep($_POST); 
    226  
    227             $phrase = $data['phrase']; 
    228             $matchType = $data['match']; 
    229  
    230             if(!empty($phrase) && in_array($matchType, array('broad','phrase','exact'))) { 
    231                 $keywords = $this->getKeywordIdeas($phrase, $matchType); 
    232                 $raw = $keywords->getRawResults(); 
    233                 if(!$keywords->hasError()) { 
    234                     $this->getScheduledUserInfo(); 
    235                     $results = $data; 
    236                     $results['number'] = $data['number'] - 1; 
    237                 } 
    238             } 
    239  
    240             echo json_encode($results); 
    241             exit(); 
    242         } 
    243  
    244         function getScheduledUserInfo() { 
    245             $userInfo = $this->getUserInfo(true); 
    246         } 
    247  
    248         function getLinkBuildingResearch() { 
    249             $data = stripslashes_deep($_POST); 
    250             $id = absint($data['id']); 
    251             $type = $data['type']; 
    252             $terms = array_map('trim',explode(',', $data['terms'])); 
    253             $settings = $this->getSettings(); 
    254             $linkBuilding = new EcordiaLinkBuildingResearch($settings['api-key'], $settings['use-ssl']); 
    255  
    256             if('social' == $type) { 
    257                 $linkBuilding->GetSocialMediaSearchResults($terms); 
    258             } else { 
    259 //              $link = site_url(''); 
    260                 $link = get_permalink($id); 
    261                 $linkBuilding->GetSearchEngineLinks($terms,$type,$link); 
    262             } 
    263  
    264             $research = $linkBuilding->getRawResults(); 
    265             $research['CurrentSelections'] = $terms; 
    266  
    267             $this->setLinkBuildingResearchForPostAndType($id, $type, $research); 
    268  
    269             include('views/link-building/research-results-list.php'); 
    270  
    271             exit(); 
    272         } 
    273  
    274         function getKeywordIdeas($phrase, $matchType) { 
    275             $settings = $this->getSettings(); 
    276             $keywords = new EcordiaKeywordResearch($settings['api-key'], $settings['use-ssl']); 
    277             $keywords->GetKeywordIdeas($phrase, $matchType); 
    278             if(!$keywords->hasError()) { 
    279                 $this->setKeywordResearchIdeas($phrase, $matchType, $keywords->getRawResults()); 
    280             } 
    281             return $keywords; 
    282         } 
    283  
    284         function displayAdminNoticeRegardingAPIKey() { 
    285             print '<div id="ecordia-empty-api-key" class="error"><p>'.sprintf(__('Your Scribe API Key is Empty.  Please <a href="%s">configure the Scribe Content Optimizer plugin</a>. If you need an API Key, please go to <a href="http://scribeseo.com/how-to-obtain-a-scribe-api-key/" title="Get a Scribe API Key" target="_blank">http://scribeseo.com/</a> to obtain a key.'), admin_url('options-general.php?page=scribe')).'</p></div>'; 
    286         } 
    287  
    288         function displayEcordiaPostsColumns($columnName, $postId) { 
    289             switch ($columnName) { 
    290                 case 'seo-score': 
    291                     $score = $this->getSeoScoreForPost($postId); 
    292                     if ($score) { 
    293                         printf(__('<span class="%1$s">%2$s%%</span>'), $this->getSeoScoreClassForPost($score), $score); 
    294                     } else { 
    295                         _e('NA'); 
    296                     } 
    297                     break; 
    298                 case 'primary-seo-keywords': 
    299                     $keywords = $this->getSeoPrimaryKeywordsForPost($postId); 
    300                     if (is_array($keywords)) { 
    301                         if ( empty($keywords)) { 
    302                             echo '<span class="ecordia-error">'.__('None').'</span>'; 
    303                         } else { 
    304                             $output = '<ul>'; 
    305                             foreach ($keywords as $keyword) { 
    306                                 $output .= "<li>{$keyword}</li>"; 
    307                             } 
    308                             $output .= '</ul>'; 
    309                         } 
    310                         print $output; 
    311                     } else { 
    312                         _e('NA'); 
    313                     } 
    314                     break; 
    315             } 
    316         } 
    317  
    318         function fetchUserInfo() { 
    319             $userInfo = $this->getUserInfo(true); 
    320             include('views/account-info.php'); 
    321             exit(); 
    322         } 
    323  
    324  
    325         function saveSerializedValueToPreventOverriding($postId) { 
    326             if(isset( $_POST['serialized-ecordia-results']) && !empty($_POST['serialized-ecordia-results'])) { 
    327                 if(false !== (wp_is_post_autosave($postId) || wp_is_post_revision($postId))) { 
    328                     return; 
    329                 } 
    330                 update_post_meta($postId, $this->_meta_seoInfo, stripslashes($_POST['serialized-ecordia-results'])); 
    331             } 
    332         } 
    333  
    334         // DISPLAY CALLBACKS 
    335  
    336         function displayMetaBoxError() { 
    337             include ('views/meta-box/error.php'); 
    338         } 
    339  
    340         function displayMetaBox($post) { 
    341             if ($this->postHasBeenAnalyzed($post->ID)) { 
    342                 include ('views/meta-box/after.php'); 
    343             } else { 
    344                 include ('views/meta-box/before.php'); 
    345             } 
    346         } 
    347  
    348         function displayKeywordResearchMetaBox($post) { 
    349             include('views/keyword-research/meta-box.php'); 
    350         } 
    351  
    352         function displayLinkBuildingMetaBox($post) { 
    353             if($this->postHasBeenAnalyzed($post->ID)) { 
    354                 include('views/link-building/meta-box-after.php'); 
    355             } else { 
    356                 include('views/link-building/meta-box-before.php'); 
    357             } 
    358         } 
    359  
    360         function displaySettingsPage() { 
    361             include ('views/settings.php'); 
    362         } 
    363  
    364         function displayThickboxInterface() { 
    365             wp_enqueue_style('ecordia'); 
    366             wp_enqueue_script('ecordia'); 
    367             wp_enqueue_style('global'); 
    368             wp_enqueue_style('media'); 
    369             wp_iframe('ecordia_thickbox_include'); 
    370         } 
    371  
    372         function displayKeywordResearchThickboxInterface() { 
    373             wp_enqueue_style('ecordia'); 
    374             wp_enqueue_script('ecordia'); 
    375             wp_enqueue_style('global'); 
    376             wp_enqueue_style('media'); 
    377             wp_iframe('ecordia_keyword_research_thickbox_include'); 
    378         } 
    379  
    380         function displayLinkBuildingResearchThickboxInterface() { 
    381             wp_enqueue_style('ecordia'); 
    382             wp_enqueue_script('ecordia'); 
    383             wp_enqueue_style('global'); 
    384             wp_enqueue_style('media'); 
    385             wp_iframe('ecordia_link_building_research_thickbox_include'); 
    386         } 
    387  
    388  
    389  
    390         function thickboxInclude() { 
    391             $pages = array('ecordia-score', 'ecordia-keyword-analysis', 'ecordia-change-keywords', 'ecordia-keyword-alternates', 'ecordia-tags', 'ecordia-serp', 'ecordia-seo-best-practices', 'ecordia-error'); 
    392             if( defined( 'ECORDIA_DEBUG' ) && ECORDIA_DEBUG ) { 
    393                 $pages[] = 'ecordia-debug'; 
    394             } 
    395             $tab = in_array($_GET['tab'], $pages) ? $_GET['tab'] : 'ecordia-score'; 
    396             $page = str_replace('ecordia-', '', $tab); 
    397  
    398  
    399             if (false === strpos($tab, 'error')) { 
    400                 add_filter('media_upload_tabs', array(&$this, 'thickboxTabs')); 
    401                 media_upload_header(); 
    402             } 
    403  
    404             $info = $this->getSeoInfoForPost($_GET['post']); 
    405             if (false === $info && false === strpos($tab, 'error')) { 
    406                 print '<form><p>No analysis present.</p></form>'; 
    407                 return; 
    408             } 
    409  
    410             include ('views/popup/'.$page.'.php'); 
    411         } 
    412  
    413         function keywordResearchThickboxInclude() { 
    414             $phrase = urldecode($_GET['phrase']); 
    415             $type = urldecode($_GET['match-type']); 
    416  
    417  
    418             if($_GET['tab'] == 'ecordia-keyword-research-review') { 
    419                 include('views/keyword-research/keyword-research-review.php'); 
    420             } else { 
    421                 $info = $this->getKeywordResearchIdeas($phrase, $type); 
    422                 include('views/keyword-research/keyword-research.php'); 
    423             } 
    424         } 
    425  
    426         function linkBuildingResearchThickboxInclude() { 
    427             $pages = array('ecordia-link-building-external', 'ecordia-link-building-internal', 'ecordia-link-building-social'); 
    428  
    429             $tab = in_array($_GET['tab'], $pages) ? $_GET['tab'] : 'ecordia-link-building-external'; 
    430             $page = str_replace('ecordia-', '', $tab); 
    431  
    432  
    433             if (false === strpos($tab, 'error')) { 
    434                 add_filter('media_upload_tabs', array(&$this, 'linkBuildingThickboxTabs')); 
    435                 media_upload_header(); 
    436             } 
    437  
    438             $info = $this->getSeoInfoForPost($_GET['post']); 
    439             $keywordInfo = $info['GetAnalysisResult']['Analysis']['PrimaryKeywords']; 
    440             $keywords = $keywordInfo['Keywords']['Keyword']; 
    441             $properKeywords = array(); 
    442             foreach($keywords as $keyword) { 
    443                 if(in_array($keyword['Rank'],array('Primary', 'Important', 'Significant'))) { 
    444                     $properKeywords[] = $keyword; 
    445                 } 
    446             } 
    447  
    448             $type = str_replace('link-building-','',$page); 
    449             $research = $this->getLinkBuildingResearchForPostAndType($_GET['post'], $type); 
    450             if (false === $info && false === strpos($tab, 'error')) { 
    451                 print '<form><p>No analysis present.</p></form>'; 
    452                 return; 
    453             } 
    454  
    455             echo '<span id="link-building-type" data-type="'.$type.'"></span>'; 
    456             echo '<span id="link-building-post-id" data-id="'.absint($_GET['post']).'"></span>'; 
    457             $klout_logo_url = plugins_url('/resources/images/klout-powered-gray.png', __FILE__); 
    458             include ('views/link-building/'.$page.'.php'); 
    459         } 
    460  
    461         function settingsSave() { 
    462             if (isset($_POST['save-ecordia-api-key-information']) && current_user_can('manage_options') && check_admin_referer('save-ecordia-api-key-information')) { 
    463                 $settings = $this->getSettings(); 
    464                 $settings['api-key'] = trim(stripslashes($_POST['ecordia-api-key'])); 
    465                 $settings['use-ssl'] = stripslashes($_POST['ecordia-connection-method']) == 'https'; 
    466  
    467                 $permissions = array('manage_options','delete_others_posts','delete_published_posts','delete_posts'); 
    468                 $settings['permissions-level'] = in_array($_POST['ecordia-permissions-level'],array_keys($permissions)) ? $_POST['ecordia-permissions-level'] : 'manage_options'; 
    469  
    470                 $settings['seo-tool-method'] = empty($_POST['ecordia-seo-tool-method']) ? '' : '1'; 
    471                 $settings['seo-tool'] = empty($_POST['ecordia-seo-tool-chooser']) ? array() : unserialize(stripslashes($_POST['ecordia-seo-tool-chooser'])); 
    472  
    473                 $settings['ecordia-post-types'] = !is_array($_POST['ecordia-post-types']) ? array() : $_POST['ecordia-post-types']; 
    474  
    475  
    476                 $this->setSettings($settings); 
    477                 wp_redirect(admin_url('options-general.php?page=scribe&updated=true')); 
    478                 exit(); 
    479             } 
    480         } 
    481  
    482         function thickboxTabs($tabs) { 
    483             $pages = array('ecordia-score'=>__('SEO Score'), 'ecordia-keyword-analysis'=>__('Keyword Analysis'), 'ecordia-change-keywords'=>__('Change Keywords'), 'ecordia-keyword-alternates'=>__('Alternate Keywords'), 'ecordia-tags'=>__('Tags'), 'ecordia-serp'=>__('SERP'), 'ecordia-seo-best-practices'=>__('SEO Best Practices')); 
    484             if( defined( 'ECORDIA_DEBUG' ) && ECORDIA_DEBUG ) { 
    485                 $pages['ecordia-debug'] = __( 'Debug Info' ); 
    486             } 
    487             return $pages; 
    488         } 
    489         function linkBuildingThickboxTabs($tabs) { 
    490             return array('ecordia-link-building-external'=>__('External Links'), 'ecordia-link-building-internal'=>__('Internal Links'), 'ecordia-link-building-social'=>__('Social Media')); 
    491         } 
    492  
    493         // UTILITY - changed the order to support AIOSEO first before themes 
    494  
    495         function getSupportedPostTypes() { 
    496             $settings = $this->getSettings(); 
    497             if(!is_array($settings['ecordia-post-types'])) { 
    498                 return array('post','page'); 
    499             } else { 
    500                 return $settings['ecordia-post-types']; 
    501             } 
    502         } 
    503  
    504         function getNumberEvaluationsRemaining() { 
    505             $userInfo = $this->getUserInfo(false); 
    506             if(is_wp_error($userInfo)) { 
    507                 return '...'; 
    508             } else { 
    509                 return $userInfo->getCreditsRemaining(); 
    510             } 
    511         } 
    512  
    513         function getNumberKeywordEvaluationsRemaining() { 
    514             $userInfo = $this->getUserInfo(false); 
    515             if(is_wp_error($userInfo)) { 
    516                 return '...'; 
    517             } else { 
    518                 return $userInfo->getKeywordCreditsRemaining(); 
    519             } 
    520         } 
    521  
    522         function getAutomaticDependency() { 
    523             $themeName = substr(trim(get_current_theme()),0,6); 
    524             $templateName = strtolower(trim(get_template())); 
    525             $frameworkName = THEME_FRAMEWORK; 
    526             if (is_plugin_active('fv-all-in-one-seo-pack/fv-all-in-one-seo-pack.php')) { 
    527                 return 'fvaioseo'; 
    528             } else if (is_plugin_active('all-in-one-seo-pack/all_in_one_seo_pack.php')) { 
    529                 return 'aioseo'; 
    530             } else if (is_plugin_active('all-in-one-seo-pack-pro/all_in_one_seo_pack.php')) { 
    531                 return 'aioseo'; 
    532             } else if ($frameworkName == 'woothemes'){ 
    533                 return 'woothemes'; 
    534             } else if (in_array($themeName, array('Thesis', 'Hybrid', 'Headwa'))) { 
    535                 return strtolower($themeName); 
    536             } else if (in_array($templateName, array('hybrid','genesis'))) { 
    537                 return $templateName; 
    538             } 
    539         } 
    540  
    541         function getAutomaticDependencyNiceName($automatic) { 
    542             switch( $automatic ) { 
    543                 case 'aioseo': 
    544                     $currently = __( 'All in One SEO Pack Plugin' ); 
    545                     break; 
    546                 case 'headwa': 
    547                     $currently = __( 'Headway Theme' ); 
    548                     break; 
    549                 case 'hybrid': 
    550                     $currently = __( 'Hybrid Theme' ); 
    551                     break; 
    552                 case 'genesis': 
    553                     $currently = __( 'Genesis Theme' ); 
    554                     break; 
    555                 case 'thesis': 
    556                     $currently = __( 'Thesis Theme' ); 
    557                     break; 
    558                 case 'fvaioseo': 
    559                     $currently = __( 'FV All in One SEO Pack' ); 
    560                     break; 
    561                 case 'woothemes': 
    562                     $currently = __( 'WooThemes' ); 
    563                     break; 
    564                 default: 
    565                     $currently = sprintf( __( '<span class="ecordia-error">unable to detected theme/plugin</span>.  Please select the "Choose the SEO tool" option below. To see a list of compatible plugins and themes go to <a href="%1$s" target="_blank">http://scribeseo.com/compatibility</a>.' ), 'http://scribeseo.com/compatibility'  ); 
    566                     break; 
    567             } 
    568             return $currently; 
    569         } 
    570  
    571         function getEcordiaDependency() { 
    572             $settings = $this->getSettings(); 
    573             if($settings['seo-tool-method'] == '') { 
    574                 return $this->getAutomaticDependency(); 
    575             } else { 
    576                 return 'user-defined'; 
    577             } 
    578         } 
    579  
    580         function getPossibleDependencies() { 
    581             $response = wp_remote_get($this->_utility_DependencyUrl); 
    582             if(is_wp_error($response)) { 
    583                 return array('plugins'=>array(),'themes'=>array()); 
    584             } else { 
    585                 $xml = $response['body']; 
    586                 $parser = xml_parser_create(); 
    587                 xml_set_element_handler($parser,array($this,'getPossibleDependenciesStartTag'),array($this,'getPossibleDependenciesEndTag')); 
    588                 xml_set_character_data_handler($parser, array($this,'getPossibleDependenciesContents')); 
    589                 if(!xml_parse($parser,$xml)) { 
    590                     return array(); 
    591                 } else { 
    592                     return $this->_possible_Items; 
    593                 } 
    594             } 
    595         } 
    596  
    597         function getPossibleDependenciesStartTag($parser,$data) { 
    598             $name = strtolower($data); 
    599             switch($name) { 
    600                 case 'plugins': 
    601                 case 'themes': 
    602                     $this->_possible_CurrentType = $name; 
    603                     break; 
    604                 case 'name': 
    605                 case 'titleelementid': 
    606                 case 'descriptionelementid': 
    607                     $this->_possible_CurrentData = str_replace('elementid','',$name); 
    608                     break; 
    609                 case 'item': 
    610                     $this->_possible_Item = array(); 
    611                     break; 
    612             } 
    613         } 
    614  
    615         function getPossibleDependenciesEndTag($parser,$data) { 
    616             $name = strtolower($data); 
    617             switch($name) { 
    618                 case 'item': 
    619                     $this->_possible_Items[$this->_possible_CurrentType][] = $this->_possible_Item; 
    620                     break; 
    621                 case 'name': 
    622                 case 'titleelementid': 
    623                 case 'descriptionelementid': 
    624                     $this->_possible_CurrentData = ''; 
    625                     break; 
    626             } 
    627         } 
    628  
    629         function getPossibleDependenciesContents($parser,$data) { 
    630             if(!empty($this->_possible_CurrentData)) { 
    631                 $this->_possible_Item[$this->_possible_CurrentData] = $data; 
    632             } 
    633         } 
    634  
    635         function getSeoInfoForPost($postId) { 
    636             $info = get_post_meta($postId, $this->_meta_seoInfo, true); 
    637             if ( empty($info)) { 
    638                 $info = false; 
    639             } else { 
    640                 if (is_array($info)) { 
    641                     $info = base64_encode(serialize($info)); 
    642                 } 
    643                 $info = unserialize(base64_decode($info)); 
    644             } 
    645             return $info; 
    646         } 
    647         function getLinkBuildingResearchForPostAndType($postId, $type) { 
    648             $info = get_post_meta($postId, $this->_meta_linkResearchInfo.'_'.$type, true); 
    649             if(empty($info)) { 
    650                 $info = false; 
    651             } else { 
    652                 $info = unserialize(base64_decode($info)); 
    653             } 
    654             return $info; 
    655         } 
    656         function setLinkBuildingResearchForPostAndType($postId, $type, $info) { 
    657             if(is_array($info)) { 
    658                 $info = base64_encode(serialize($info)); 
    659                 update_post_meta($postId, $this->_meta_linkResearchInfo.'_'.$type, $info); 
    660             } 
    661         } 
    662         function getNumberExternalLinkResearch($postId) { 
    663             $info = $this->getLinkBuildingResearchForPostAndType($postId, 'external'); 
    664             if(!$info) { 
    665                 return 0; 
    666             } else { 
    667                 $links = $info['GetSearchEngineResultsResult']['Links']['SearchEngineLink']; 
    668                 return is_array($links) ? count($links) : 0; 
    669             } 
    670         } 
    671         function getNumberInternalLinkResearch($postId) { 
    672             $info = $this->getLinkBuildingResearchForPostAndType($postId, 'internal'); 
    673             if(!$info) { 
    674                 return 0; 
    675             } else { 
    676                 $links = $info['GetSearchEngineResultsResult']['Links']['SearchEngineLink']; 
    677                 return is_array($links) ? count($links) : 0; 
    678             } 
    679         } 
    680         function getNumberSocialLinkResearch($postId) { 
    681             $info = $this->getLinkBuildingResearchForPostAndType($postId, 'social'); 
    682             if(!$info) { 
    683                 return 0; 
    684             } else { 
    685                 $links = $info['GetSocialMediaSearchResultsResult']['Entries']['SocialMediaUser']; 
    686                 return count($links); 
    687             } 
    688         } 
    689  
    690         function setKeywordResearchIdeas($phrase, $matchType, $ideas) { 
    691             $key = 'keyword_research_info_'.md5($phrase.$matchType); 
    692             $this->addKeywordResearchHistory($key, $phrase, $matchType); 
    693             if(!is_array($ideas)) { 
    694                 $ideas = array(); 
    695             } 
    696             update_option($key, $ideas); 
    697         } 
    698  
    699         function getKeywordResearchIdeas($phrase, $matchType) { 
    700             $key = 'keyword_research_info_'.md5($phrase.$matchType); 
    701             $info = get_option($key, array()); 
    702             if(!is_array($info)) { 
    703                 $info = array(); 
    704             } 
    705             return $info; 
    706         } 
    707  
    708         function addKeywordResearchHistory($key, $phrase, $matchType) { 
    709             $meta = $this->getKeywordResearchHistory(); 
    710             $meta[$key] = array('phrase'=>$phrase, 'type'=>$matchType); 
    711             update_option($this->_option_keywordResearchList, $meta); 
    712         } 
    713  
    714         function getKeywordResearchHistory() { 
    715             $meta = get_option($this->_option_keywordResearchList, array()); 
    716             if(!is_array($meta)) { 
    717                 $meta = array(); 
    718             } 
    719  
    720             usort($meta, create_function('$a, $b', 'return strcmp($a["phrase"], $b["phrase"]);')); 
    721  
    722             return $meta; 
    723         } 
    724  
    725         function getSeoScoreForPost($postId) { 
    726             $info = $this->getSeoInfoForPost($postId); 
    727             if (@is_numeric($info['GetAnalysisResult']['Analysis']['SeoScore']['Score']['Value'])) { 
    728                 return intval($info['GetAnalysisResult']['Analysis']['SeoScore']['Score']['Value']); 
    729             } 
    730             return false; 
    731         } 
    732  
    733         function getSeoScoreClassForPost($score) { 
    734             $score = intval($score); 
    735             if ($score <= 50) { 
    736                 return 'ecordia-score-low'; 
    737             } elseif ($score <= 75) { 
    738                 return 'ecordia-score-medium'; 
    739             } else { 
    740                 return 'ecordia-score-high'; 
    741             } 
    742         } 
    743  
    744         function getSeoPrimaryKeywordsForPost($postId) { 
    745             $info = $this->getSeoInfoForPost($postId); 
    746             if (false === $info) { 
    747                 return array(); 
    748             } else { 
    749                 $allKeywords = (array) $info['GetAnalysisResult']['Analysis']['KeywordAnalysis']['Keywords']['Keyword']; 
    750                 $primaryKeywords = array(); 
    751                 foreach ($allKeywords as $keyword) { 
    752                     if ($keyword['Rank'] == 'Primary') { 
    753                         $primaryKeywords[] = $keyword['Term']; 
    754                     } 
    755                 } 
    756                 return $primaryKeywords; 
    757             } 
    758         } 
    759  
    760         function postHasBeenAnalyzed($postId) { 
    761             return false !== $this->getSeoInfoForPost($postId); 
    762         } 
    763  
    764         function getPostSeoData($postId) { 
    765             $seoData = get_post_meta($postId, $this->_meta_seoInfo, true); 
    766             if (!$seoData) { 
    767                 return false; 
    768             } else { 
    769                 return $seoData; 
    770             } 
    771         } 
    772  
    773         function getUserInfo($live = false) { 
    774  
    775             $settings = $this->getSettings(); 
    776             if ( $live && empty( $settings['api-key'] ) ) { 
    777  
    778                 delete_option( $this->_option_cachedUserResults ); 
    779                 return new WP_Error(-1, __('You must set an API key.')); 
    780  
    781             } 
    782  
    783             $userAccountAccess = new EcordiaUserAccount( $settings['api-key'], $settings['use-ssl'], $live ); 
    784  
    785             if ( $live ) { 
    786  
    787                 $userAccountAccess->UserAccountStatus(); 
    788                 if ( $userAccountAccess->hasError() ) 
    789                     return new WP_Error($userAccountAccess->getErrorType(), $userAccountAccess->getErrorMessage() . $userAccountAccess->client->response . '<br /> ' .$userAccountAccess->client->request, $userAccountAccess); 
    790  
    791             } elseif ( ! $userAccountAccess->has_results() ) { 
    792  
    793                 return new WP_Error(-100, __('Fetching Information...')); 
    794  
    795             } 
    796  
    797             return $userAccountAccess; 
    798  
    799         } 
    800  
    801         function getSettings() { 
    802             if (null === $this->settings) { 
    803                 $this->settings = get_option($this->_option_ecordiaSettings, array()); 
    804                 $this->settings = is_array($this->settings) ? $this->settings : array(); 
    805             } 
    806             return $this->settings; 
    807         } 
    808         function getPermissionLevel() { 
    809             $settings = $this->getSettings(); 
    810             if(empty($settings['permissions-level'])) { 
    811                 $settings['permissions-level'] = 'administrator'; 
    812                 $this->setSettings($settings); 
    813             } 
    814             return $settings['permissions-level']; 
    815         } 
    816  
    817         function setSettings($settings) { 
    818             if (!is_array($settings)) { 
    819                 return; 
    820             } 
    821             $this->settings = $settings; 
    822             update_option($this->_option_ecordiaSettings, $this->settings); 
    823         } 
    824  
    825         function displaySection($section) { 
    826             include ('views/misc/section-display.php'); 
    827         } 
    828  
    829         function getPostTypes() { 
    830             global $wp_version; 
    831             if(version_compare($wp_version,'3','>=')) { 
    832                 return get_post_types(array('show_ui'=>true), 'objects'); 
    833             } else { 
    834                 $post = new stdClass; 
    835                 $post->labels = new stdClass; 
    836                 $post->labels->name = __('Posts'); 
    837  
    838                 $page = new stdClass; 
    839                 $page->labels = new stdClass; 
    840                 $page->labels->name = __('Pages'); 
    841  
    842                 return array('post'=>$post, 'page'=>$page); 
    843             } 
    844         } 
    845     } 
    846  
    847  
    848     $ecordia = new Ecordia; 
    849     function ecordia_thickbox_include() { 
    850         global $ecordia; 
    851         $ecordia->thickboxInclude(); 
    852     } 
    853  
    854     function ecordia_keyword_research_thickbox_include() { 
    855         global $ecordia; 
    856         $ecordia->keywordResearchThickboxInclude(); 
    857     } 
    858     function ecordia_link_building_research_thickbox_include() { 
    859         global $ecordia; 
    860         $ecordia->linkBuildingResearchThickboxInclude(); 
    861     } 
    862 } 
Note: See TracChangeset for help on using the changeset viewer.