All_in_One_SEO_Pack_Module

The All In One SEO Pack All in One SEO Pack Module class.

Defined (1)

The class is defined in the following location(s).

/admin/aioseop_module_class.php  
  1. abstract class All_in_One_SEO_Pack_Module { 
  2. public static $instance = null; 
  3. protected $plugin_name; 
  4. protected $name; 
  5. protected $menu_name; 
  6. protected $prefix; 
  7. protected $file; 
  8. protected $options; 
  9. protected $option_name; 
  10. protected $default_options; 
  11. protected $help_text = array(); 
  12. protected $help_anchors = array(); 
  13. protected $locations = null; // organize settings into settings pages with a menu items and/or metaboxes on post types edit screen; optional 
  14. protected $layout = null; // organize settings on a settings page into multiple, separate metaboxes; optional 
  15. protected $tabs = null; // organize layouts on a settings page into multiple, separate tabs; optional 
  16. protected $current_tab = null; // the current tab 
  17. protected $pagehook = null; // the current page hook 
  18. protected $store_option = false; 
  19. protected $parent_option = 'aioseop_options'; 
  20. protected $post_metaboxes = array(); 
  21. protected $tabbed_metaboxes = true; 
  22. protected $credentials = false; // used for WP Filesystem 
  23. protected $script_data = null; // used for passing data to JavaScript 
  24. protected $plugin_path = null; 
  25. protected $pointers = array(); 
  26. protected $form = 'dofollow'; 
  27.  
  28. /** 
  29. * Handles calls to display_settings_page_{$location}, does error checking. 
  30. */ 
  31. function __call( $name, $arguments ) { 
  32. if ( $this->strpos( $name, 'display_settings_page_' ) === 0 ) { 
  33. return $this->display_settings_page( $this->substr( $name, 22 ) ); 
  34. $error = __( sprintf( "Method %s doesn't exist", $name ), 'all-in-one-seo-pack' ); 
  35. if ( class_exists( 'BadMethodCallException' ) ) { 
  36. throw new BadMethodCallException( $error ); 
  37. throw new Exception( $error ); 
  38.  
  39. function __construct() { 
  40. if ( empty( $this->file ) ) { 
  41. $this->file = __FILE__; 
  42. $this->plugin_name = AIOSEOP_PLUGIN_NAME; 
  43. $this->plugin_path = array(); 
  44. // $this->plugin_path['dir'] = plugin_dir_path( $this->file ); 
  45. $this->plugin_path['basename'] = plugin_basename( $this->file ); 
  46. $this->plugin_path['dirname'] = dirname( $this->plugin_path['basename'] ); 
  47. $this->plugin_path['url'] = plugin_dir_url( $this->file ); 
  48. $this->plugin_path['images_url'] = $this->plugin_path['url'] . 'images'; 
  49. $this->script_data['plugin_path'] = $this->plugin_path; 
  50.  
  51. /** 
  52. * Get options for module, stored individually or together. 
  53. */ 
  54. function get_class_option() { 
  55. $option_name = $this->get_option_name(); 
  56. if ( $this->store_option || $option_name == $this->parent_option ) { 
  57. return get_option( $option_name ); 
  58. } else { 
  59. $option = get_option( $this->parent_option ); 
  60. if ( isset( $option['modules'] ) && isset( $option['modules'][ $option_name ] ) ) { 
  61. return $option['modules'][ $option_name ]; 
  62.  
  63. return false; 
  64.  
  65. /** 
  66. * Update options for module, stored individually or together. 
  67. */ 
  68. function update_class_option( $option_data, $option_name = false ) { 
  69. if ( $option_name == false ) { 
  70. $option_name = $this->get_option_name(); 
  71. if ( $this->store_option || $option_name == $this->parent_option ) { 
  72. return update_option( $option_name, $option_data ); 
  73. } else { 
  74. $option = get_option( $this->parent_option ); 
  75. if ( ! isset( $option['modules'] ) ) { 
  76. $option['modules'] = array(); 
  77. $option['modules'][ $option_name ] = $option_data; 
  78.  
  79. return update_option( $this->parent_option, $option ); 
  80.  
  81. /** 
  82. * Delete options for module, stored individually or together. 
  83. */ 
  84. function delete_class_option( $delete = false ) { 
  85. $option_name = $this->get_option_name(); 
  86. if ( $this->store_option || $delete ) { 
  87. delete_option( $option_name ); 
  88. } else { 
  89. $option = get_option( $this->parent_option ); 
  90. if ( isset( $option['modules'] ) && isset( $option['modules'][ $option_name ] ) ) { 
  91. unset( $option['modules'][ $option_name ] ); 
  92.  
  93. return update_option( $this->parent_option, $option ); 
  94.  
  95. return false; 
  96.  
  97. /** 
  98. * Get the option name with prefix. 
  99. */ 
  100. function get_option_name() { 
  101. if ( ! isset( $this->option_name ) || empty( $this->option_name ) ) { 
  102. $this->option_name = $this->prefix . 'options'; 
  103.  
  104. return $this->option_name; 
  105.  
  106. /** 
  107. * Convenience function to see if an option is set. 
  108. */ 
  109. function option_isset( $option, $location = null ) { 
  110. $prefix = $this->get_prefix( $location ); 
  111. $opt = $prefix . $option; 
  112.  
  113. return ( isset( $this->options[ $opt ] ) && $this->options[ $opt ] ); 
  114.  
  115. /*** Case conversion; handle non UTF-8 encodings and fallback ***/ 
  116.  
  117. function convert_case( $str, $mode = 'upper' ) { 
  118. static $charset = null; 
  119. if ( $charset == null ) { 
  120. $charset = get_bloginfo( 'charset' ); 
  121. $str = (string) $str; 
  122. if ( $mode == 'title' ) { 
  123. if ( function_exists( 'mb_convert_case' ) ) { 
  124. return mb_convert_case( $str, MB_CASE_TITLE, $charset ); 
  125. } else { 
  126. return ucwords( $str ); 
  127.  
  128. if ( $charset == 'UTF-8' ) { 
  129. global $UTF8_TABLES; 
  130. include_once( AIOSEOP_PLUGIN_DIR . 'inc/aioseop_UTF8.php' ); 
  131. if ( is_array( $UTF8_TABLES ) ) { 
  132. if ( $mode == 'upper' ) { 
  133. return strtr( $str, $UTF8_TABLES['strtoupper'] ); 
  134. if ( $mode == 'lower' ) { 
  135. return strtr( $str, $UTF8_TABLES['strtolower'] ); 
  136.  
  137. if ( $mode == 'upper' ) { 
  138. if ( function_exists( 'mb_strtoupper' ) ) { 
  139. return mb_strtoupper( $str, $charset ); 
  140. } else { 
  141. return strtoupper( $str ); 
  142.  
  143. if ( $mode == 'lower' ) { 
  144. if ( function_exists( 'mb_strtolower' ) ) { 
  145. return mb_strtolower( $str, $charset ); 
  146. } else { 
  147. return strtolower( $str ); 
  148.  
  149. return $str; 
  150.  
  151. /** 
  152. * Convert a string to lower case 
  153. * Compatible with mb_strtolower(), an UTF-8 friendly replacement for strtolower() 
  154. */ 
  155. function strtolower( $str ) { 
  156. return $this->convert_case( $str, 'lower' ); 
  157.  
  158. /** 
  159. * Convert a string to upper case 
  160. * Compatible with mb_strtoupper(), an UTF-8 friendly replacement for strtoupper() 
  161. */ 
  162. function strtoupper( $str ) { 
  163. return $this->convert_case( $str, 'upper' ); 
  164.  
  165. /** 
  166. * Convert a string to title case 
  167. * Compatible with mb_convert_case(), an UTF-8 friendly replacement for ucwords() 
  168. */ 
  169. function ucwords( $str ) { 
  170. return $this->convert_case( $str, 'title' ); 
  171.  
  172. /** 
  173. * Wrapper for strlen() - uses mb_strlen() if possible. 
  174. */ 
  175. function strlen( $string ) { 
  176. if ( function_exists( 'mb_strlen' ) ) { 
  177. return mb_strlen( $string ); 
  178.  
  179. return strlen( $string ); 
  180.  
  181. /** 
  182. * Wrapper for substr() - uses mb_substr() if possible. 
  183. */ 
  184. function substr( $string, $start = 0, $length = 2147483647 ) { 
  185. $args = func_get_args(); 
  186. if ( function_exists( 'mb_substr' ) ) { 
  187. return call_user_func_array( 'mb_substr', $args ); 
  188.  
  189. return call_user_func_array( 'substr', $args ); 
  190.  
  191. /** 
  192. * Wrapper for strpos() - uses mb_strpos() if possible. 
  193. */ 
  194. function strpos( $haystack, $needle, $offset = 0 ) { 
  195. if ( function_exists( 'mb_strpos' ) ) { 
  196. return mb_strpos( $haystack, $needle, $offset ); 
  197.  
  198. return strpos( $haystack, $needle, $offset ); 
  199.  
  200. /** 
  201. * Wrapper for strrpos() - uses mb_strrpos() if possible. 
  202. */ 
  203. function strrpos( $haystack, $needle, $offset = 0 ) { 
  204. if ( function_exists( 'mb_strrpos' ) ) { 
  205. return mb_strrpos( $haystack, $needle, $offset ); 
  206.  
  207. return strrpos( $haystack, $needle, $offset ); 
  208.  
  209. /** 
  210. * convert xml string to php array - useful to get a serializable value 
  211. * @param string $xmlstr 
  212. * @return array 
  213. * @author Adrien aka Gaarf & contributors 
  214. * @see http://gaarf.info/2009/08/13/xml-string-to-php-array/ 
  215. */ 
  216. function html_string_to_array( $xmlstr ) { 
  217. if ( ! class_exists( 'DOMDocument' ) ) { 
  218. return array(); 
  219. } else { 
  220. $doc = new DOMDocument(); 
  221. $doc->loadHTML( $xmlstr ); 
  222.  
  223. return $this->domnode_to_array( $doc->documentElement ); 
  224.  
  225. function xml_string_to_array( $xmlstr ) { 
  226. if ( ! class_exists( 'DOMDocument' ) ) { 
  227. return array(); 
  228. } else { 
  229. $doc = new DOMDocument(); 
  230. $doc->loadXML( $xmlstr ); 
  231.  
  232. return $this->domnode_to_array( $doc->documentElement ); 
  233.  
  234. function domnode_to_array( $node ) { 
  235. switch ( $node->nodeType ) { 
  236. case XML_CDATA_SECTION_NODE: 
  237. case XML_TEXT_NODE: 
  238. return trim( $node->textContent ); 
  239. break; 
  240. case XML_ELEMENT_NODE: 
  241. $output = array(); 
  242. for ( $i = 0, $m = $node->childNodes->length; $i < $m; $i ++ ) { 
  243. $child = $node->childNodes->item( $i ); 
  244. $v = $this->domnode_to_array( $child ); 
  245. if ( isset( $child->tagName ) ) { 
  246. $t = $child->tagName; 
  247. if ( ! isset( $output[ $t ] ) ) { 
  248. $output[ $t ] = array(); 
  249. if ( is_array( $output ) ) { 
  250. $output[ $t ][] = $v; 
  251. } elseif ( $v || $v === '0' ) { 
  252. $output = (string) $v; 
  253. if ( $node->attributes->length && ! is_array( $output ) ) //Has attributes but isn't an array 
  254. $output = array( '@content' => $output ); 
  255. } //Change output into an array. 
  256. if ( is_array( $output ) ) { 
  257. if ( $node->attributes->length ) { 
  258. $a = array(); 
  259. foreach ( $node->attributes as $attrName => $attrNode ) { 
  260. $a[ $attrName ] = (string) $attrNode->value; 
  261. $output['@attributes'] = $a; 
  262. foreach ( $output as $t => $v ) { 
  263. if ( is_array( $v ) && count( $v ) == 1 && $t != '@attributes' ) { 
  264. $output[ $t ] = $v[0]; 
  265. if ( empty( $output ) ) { 
  266. return ''; 
  267.  
  268. return $output; 
  269.  
  270. /*** adds support for using %cf_(name of field)% for using custom fields / Advanced Custom Fields in titles / descriptions etc. ***/ 
  271. function apply_cf_fields( $format ) { 
  272. return preg_replace_callback( '/%cf_([^%]*?)%/', array( $this, 'cf_field_replace' ), $format ); 
  273.  
  274. function cf_field_replace( $matches ) { 
  275. $result = ''; 
  276. if ( ! empty( $matches ) ) { 
  277. if ( ! empty( $matches[1] ) ) { 
  278. if ( function_exists( 'get_field' ) ) { 
  279. $result = get_field( $matches[1] ); 
  280. if ( empty( $result ) ) { 
  281. global $post; 
  282. if ( ! empty( $post ) ) { 
  283. $result = get_post_meta( $post->ID, $matches[1], true ); 
  284. if ( empty( $result ) ) { 
  285. $result = $matches[0]; 
  286. } else { 
  287. $result = $matches[0]; 
  288. $result = strip_tags( $result ); 
  289.  
  290. return $result; 
  291.  
  292. /** 
  293. * Returns child blogs of parent in a multisite. 
  294. */ 
  295. function get_child_blogs() { 
  296. global $wpdb, $blog_id; 
  297. $site_id = $wpdb->siteid; 
  298. if ( is_multisite() ) { 
  299. if ( $site_id != $blog_id ) { 
  300. return false; 
  301.  
  302. return $wpdb->get_col( "SELECT blog_id FROM {$wpdb->blogs} WHERE site_id = {$blog_id} AND site_id != blog_id" ); 
  303.  
  304. return false; 
  305.  
  306. /** 
  307. * Checks if the plugin is active on a given blog by blogid on a multisite. 
  308. */ 
  309. function is_aioseop_active_on_blog( $bid = false ) { 
  310. global $blog_id; 
  311. if ( empty( $bid ) || ( $bid == $blog_id ) || ! is_multisite() ) { 
  312. return true; 
  313. if ( ! function_exists( 'is_plugin_active_for_network' ) ) { 
  314. require_once( ABSPATH . '/wp-admin/includes/plugin.php' ); 
  315. if ( is_plugin_active_for_network( AIOSEOP_PLUGIN_BASENAME ) ) { 
  316. return true; 
  317.  
  318. return in_array( AIOSEOP_PLUGIN_BASENAME, (array) get_blog_option( $bid, 'active_plugins', array() ) ); 
  319.  
  320. function quote_list_for_regex( $list, $quote = '/' ) { 
  321. $regex = ''; 
  322. $cont = 0; 
  323. foreach ( $list as $l ) { 
  324. if ( $cont ) { 
  325. $regex .= '|'; 
  326. $cont = 1; 
  327. $regex .= preg_quote( trim( $l ), $quote ); 
  328.  
  329. return $regex; 
  330.  
  331. // original code thanks to Sean M. Brown -- http://smbrown.wordpress.com/2009/04/29/verify-googlebot-forward-reverse-dns/ 
  332. function is_good_bot() { 
  333. $botlist = array( 
  334. 'Yahoo! Slurp' => 'crawl.yahoo.net',  
  335. 'googlebot' => '.googlebot.com',  
  336. 'msnbot' => 'search.msn.com',  
  337. ); 
  338. $botlist = apply_filters( $this->prefix . 'botlist', $botlist ); 
  339. if ( ! empty( $botlist ) ) { 
  340. if ( ! isset( $_SERVER['HTTP_USER_AGENT'] ) ) { 
  341. return false; 
  342. $ua = $_SERVER['HTTP_USER_AGENT']; 
  343. $uas = $this->quote_list_for_regex( $botlist ); 
  344. if ( preg_match( '/' . $uas . '/i', $ua ) ) { 
  345. $ip = $_SERVER['REMOTE_ADDR']; 
  346. $hostname = gethostbyaddr( $ip ); 
  347. $ip_by_hostname = gethostbyname( $hostname ); 
  348. if ( $ip_by_hostname == $ip ) { 
  349. $hosts = array_values( $botlist ); 
  350. foreach ( $hosts as $k => $h ) { 
  351. $hosts[ $k ] = preg_quote( $h ) . '$'; 
  352. $hosts = join( '|', $hosts ); 
  353. if ( preg_match( '/' . $hosts . '/i', $hostname ) ) { 
  354. return true; 
  355.  
  356. return false; 
  357.  
  358. function default_bad_bots() { 
  359. $botlist = array( 
  360. 'Abonti',  
  361. 'aggregator',  
  362. 'AhrefsBot',  
  363. 'asterias',  
  364. 'BDCbot',  
  365. 'BLEXBot',  
  366. 'BuiltBotTough',  
  367. 'Bullseye',  
  368. 'BunnySlippers',  
  369. 'ca-crawler',  
  370. 'CCBot',  
  371. 'Cegbfeieh',  
  372. 'CheeseBot',  
  373. 'CherryPicker',  
  374. 'CopyRightCheck',  
  375. 'cosmos',  
  376. 'Crescent',  
  377. 'discobot',  
  378. 'DittoSpyder',  
  379. 'DotBot',  
  380. 'Download Ninja',  
  381. 'EasouSpider',  
  382. 'EmailCollector',  
  383. 'EmailSiphon',  
  384. 'EmailWolf',  
  385. 'EroCrawler',  
  386. 'Exabot',  
  387. 'ExtractorPro',  
  388. 'Fasterfox',  
  389. 'FeedBooster',  
  390. 'Foobot',  
  391. 'Genieo',  
  392. 'grub-client',  
  393. 'Harvest',  
  394. 'hloader',  
  395. 'httplib',  
  396. 'HTTrack',  
  397. 'humanlinks',  
  398. 'ieautodiscovery',  
  399. 'InfoNaviRobot',  
  400. 'IstellaBot',  
  401. 'Java/1.',  
  402. 'JennyBot',  
  403. 'k2spider',  
  404. 'Kenjin Spider',  
  405. 'Keyword Density/0.9',  
  406. 'larbin',  
  407. 'LexiBot',  
  408. 'libWeb',  
  409. 'libwww',  
  410. 'LinkextractorPro',  
  411. 'linko',  
  412. 'LinkScan/8.1a Unix',  
  413. 'LinkWalker',  
  414. 'LNSpiderguy',  
  415. 'lwp-trivial',  
  416. 'magpie',  
  417. 'Mata Hari',  
  418. 'MaxPointCrawler',  
  419. 'MegaIndex',  
  420. 'Microsoft URL Control',  
  421. 'MIIxpc',  
  422. 'Mippin',  
  423. 'Missigua Locator',  
  424. 'Mister PiX',  
  425. 'MJ12bot',  
  426. 'moget',  
  427. 'MSIECrawler',  
  428. 'NetAnts',  
  429. 'NICErsPRO',  
  430. 'Niki-Bot',  
  431. 'NPBot',  
  432. 'Nutch',  
  433. 'Offline Explorer',  
  434. 'Openfind',  
  435. 'panscient.com',  
  436. 'PHP/5.{',  
  437. 'ProPowerBot/2.14',  
  438. 'ProWebWalker',  
  439. 'Python-urllib',  
  440. 'QueryN Metasearch',  
  441. 'RepoMonkey',  
  442. 'SemrushBot',  
  443. 'SISTRIX',  
  444. 'sitecheck.Internetseer.com',  
  445. 'SiteSnagger',  
  446. 'SnapPreviewBot',  
  447. 'Sogou',  
  448. 'SpankBot',  
  449. 'spanner',  
  450. 'spbot',  
  451. 'Spinn3r',  
  452. 'suzuran',  
  453. 'Szukacz/1.4',  
  454. 'Teleport',  
  455. 'Telesoft',  
  456. 'The Intraformant',  
  457. 'TheNomad',  
  458. 'TightTwatBot',  
  459. 'Titan',  
  460. 'toCrawl/UrlDispatcher',  
  461. 'True_Robot',  
  462. 'turingos',  
  463. 'TurnitinBot',  
  464. 'UbiCrawler',  
  465. 'UnisterBot',  
  466. 'URLy Warning',  
  467. 'VCI',  
  468. 'WBSearchBot',  
  469. 'Web Downloader/6.9',  
  470. 'Web Image Collector',  
  471. 'WebAuto',  
  472. 'WebBandit',  
  473. 'WebCopier',  
  474. 'WebEnhancer',  
  475. 'WebmasterWorldForumBot',  
  476. 'WebReaper',  
  477. 'WebSauger',  
  478. 'Website Quester',  
  479. 'Webster Pro',  
  480. 'WebStripper',  
  481. 'WebZip',  
  482. 'Wotbox',  
  483. 'wsr-agent',  
  484. 'WWW-Collector-E',  
  485. 'Xenu',  
  486. 'Zao',  
  487. 'Zeus',  
  488. 'ZyBORG',  
  489. 'coccoc',  
  490. 'Incutio',  
  491. 'lmspider',  
  492. 'memoryBot',  
  493. 'SemrushBot',  
  494. 'serf',  
  495. 'Unknown',  
  496. 'uptime files',  
  497. ); 
  498.  
  499. return $botlist; 
  500.  
  501. function is_bad_bot() { 
  502. $botlist = $this->default_bad_bots(); 
  503. $botlist = apply_filters( $this->prefix . 'badbotlist', $botlist ); 
  504. if ( ! empty( $botlist ) ) { 
  505. if ( ! isset( $_SERVER['HTTP_USER_AGENT'] ) ) { 
  506. return false; 
  507. $ua = $_SERVER['HTTP_USER_AGENT']; 
  508. $uas = $this->quote_list_for_regex( $botlist ); 
  509. if ( preg_match( '/' . $uas . '/i', $ua ) ) { 
  510. return true; 
  511.  
  512. return false; 
  513.  
  514. function default_bad_referers() { 
  515. $referlist = array( 
  516. 'semalt.com',  
  517. 'kambasoft.com',  
  518. 'savetubevideo.com',  
  519. 'buttons-for-website.com',  
  520. 'sharebutton.net',  
  521. 'soundfrost.org',  
  522. 'srecorder.com',  
  523. 'softomix.com',  
  524. 'softomix.net',  
  525. 'myprintscreen.com',  
  526. 'joinandplay.me',  
  527. 'fbfreegifts.com',  
  528. 'openmediasoft.com',  
  529. 'zazagames.org',  
  530. 'extener.org',  
  531. 'openfrost.com',  
  532. 'openfrost.net',  
  533. 'googlsucks.com',  
  534. 'best-seo-offer.com',  
  535. 'buttons-for-your-website.com',  
  536. 'www.Get-Free-Traffic-Now.com',  
  537. 'best-seo-solution.com',  
  538. 'buy-cheap-online.info',  
  539. 'site3.free-share-buttons.com',  
  540. 'webmaster-traffic.com',  
  541. ); 
  542.  
  543. return $referlist; 
  544.  
  545. function is_bad_referer() { 
  546. $referlist = $this->default_bad_referers(); 
  547. $referlist = apply_filters( $this->prefix . 'badreferlist', $referlist ); 
  548.  
  549. if ( ! empty( $referlist ) && ! empty( $_SERVER ) && ! empty( $_SERVER['HTTP_REFERER'] ) ) { 
  550. $ref = $_SERVER['HTTP_REFERER']; 
  551. $regex = $this->quote_list_for_regex( $referlist ); 
  552. if ( preg_match( '/' . $regex . '/i', $ref ) ) { 
  553. return true; 
  554.  
  555. return false; 
  556.  
  557. function allow_bot() { 
  558. $allow_bot = true; 
  559. if ( ( ! $this->is_good_bot() ) && $this->is_bad_bot() && ! is_user_logged_in() ) { 
  560. $allow_bot = false; 
  561.  
  562. return apply_filters( $this->prefix . 'allow_bot', $allow_bot ); 
  563.  
  564. /** 
  565. * Displays tabs for tabbed locations on a settings page. 
  566. */ 
  567. function display_tabs( $location ) { 
  568. if ( ( $location != null ) && isset( $locations[ $location ]['tabs'] ) ) { 
  569. $tabs = $locations['location']['tabs']; 
  570. } else { 
  571. $tabs = $this->tabs; 
  572. if ( ! empty( $tabs ) ) { 
  573. ?> 
  574. <div class="aioseop_tabs_div"><label class="aioseop_head_nav"> 
  575. <?php 
  576. foreach ( $tabs as $k => $v ) { 
  577. ?> 
  578. <a class="aioseop_head_nav_tab aioseop_head_nav_<?php if ( $this->current_tab != $k ) { 
  579. echo 'in'; 
  580. } ?>active" 
  581. href="<?php echo esc_url( add_query_arg( 'tab', $k ) ); ?>"><?php echo $v['name']; ?></a> 
  582. <?php 
  583. ?> 
  584. </label></div> 
  585. <?php 
  586.  
  587. function get_object_labels( $post_objs ) { 
  588. $pt = array_keys( $post_objs ); 
  589. $post_types = array(); 
  590. foreach ( $pt as $p ) { 
  591. if ( ! empty( $post_objs[ $p ]->label ) ) { 
  592. $post_types[ $p ] = $post_objs[ $p ]->label; 
  593. } else { 
  594. $post_types[ $p ] = $p; 
  595.  
  596. return $post_types; 
  597.  
  598. function get_term_labels( $post_objs ) { 
  599. $post_types = array(); 
  600. foreach ( $post_objs as $p ) { 
  601. if ( ! empty( $p->name ) ) { 
  602. $post_types[ $p->term_id ] = $p->name; 
  603.  
  604. return $post_types; 
  605.  
  606. function get_post_type_titles( $args = array() ) { 
  607. return $this->get_object_labels( get_post_types( $args, 'objects' ) ); 
  608.  
  609. function get_taxonomy_titles( $args = array() ) { 
  610. return $this->get_object_labels( get_taxonomies( $args, 'objects' ) ); 
  611.  
  612. function get_category_titles( $args = array() ) { 
  613. return $this->get_term_labels( get_categories( $args ) ); 
  614.  
  615. /** 
  616. * Helper function for exporting settings on post data. 
  617. */ 
  618. function post_data_export( $prefix = '_aioseop', $query = array( 'posts_per_page' => - 1 ) ) { 
  619. $buf = ''; 
  620. $posts_query = new WP_Query( $query ); 
  621. while ( $posts_query->have_posts() ) { 
  622. $posts_query->the_post(); 
  623. global $post; 
  624. $guid = $post->guid; 
  625. $type = $post->post_type; 
  626. $title = $post->post_title; 
  627. $date = $post->post_date; 
  628. $data = ''; 
  629. $post_custom_fields = get_post_custom( $post->ID ); 
  630. $has_data = null; 
  631.  
  632. if ( is_array( $post_custom_fields ) ) { 
  633. foreach ( $post_custom_fields as $field_name => $field ) { 
  634. if ( ( $this->strpos( $field_name, $prefix ) === 0 ) && $field[0] ) { 
  635. $has_data = true; 
  636. $data .= $field_name . " = '" . $field[0] . "'\n"; 
  637. if ( ! empty( $data ) ) { 
  638. $has_data = true; 
  639.  
  640. if ( $has_data != null ) { 
  641. $post_info = "\n[post_data]\n\n"; 
  642. $post_info .= "post_title = '" . $title . "'\n"; 
  643. $post_info .= "post_guid = '" . $guid . "'\n"; 
  644. $post_info .= "post_date = '" . $date . "'\n"; 
  645. $post_info .= "post_type = '" . $type . "'\n"; 
  646. if ( $data ) { 
  647. $buf .= $post_info . $data . "\n"; 
  648. wp_reset_postdata(); 
  649.  
  650. return $buf; 
  651.  
  652. /** 
  653. * Handles exporting settings data for a module. 
  654. */ 
  655. function settings_export( $buf ) { 
  656. global $aiosp; 
  657. $post_types = null; 
  658. $has_data = null; 
  659. $general_settings = null; 
  660. $exporter_choices = ''; 
  661. if ( ! empty( $_REQUEST['aiosp_importer_exporter_export_choices'] ) ) { 
  662. $exporter_choices = $_REQUEST['aiosp_importer_exporter_export_choices']; 
  663. if ( ! empty( $exporter_choices ) && is_array( $exporter_choices ) ) { 
  664. foreach ( $exporter_choices as $ex ) { 
  665. if ( $ex == 1 ) { 
  666. $general_settings = true; 
  667. if ( $ex == 2 && isset( $_REQUEST['aiosp_importer_exporter_export_post_types'] ) ) { 
  668. $post_types = $_REQUEST['aiosp_importer_exporter_export_post_types']; 
  669.  
  670. if ( ( $post_types != null ) && ( $this === $aiosp ) ) { 
  671. $buf .= $this->post_data_export( '_aioseop', array( 
  672. 'posts_per_page' => - 1,  
  673. 'post_type' => $post_types,  
  674. ) ); 
  675.  
  676. /** Add all active settings to settings file */ 
  677. $name = $this->get_option_name(); 
  678. $options = $this->get_class_option(); 
  679. if ( ! empty( $options ) && $general_settings != null ) { 
  680. $buf .= "\n[$name]\n\n"; 
  681. foreach ( $options as $key => $value ) { 
  682. if ( ( $name == $this->parent_option ) && ( $key == 'modules' ) ) { 
  683. continue; 
  684. } // don't re-export all module settings -- pdb 
  685. if ( is_array( $value ) ) { 
  686. $value = "'" . str_replace( array( "'", "\n", "\r" ), array( 
  687. "\'",  
  688. '\n',  
  689. '\r',  
  690. ), trim( serialize( $value ) ) ) . "'"; 
  691. } else { 
  692. $value = str_replace( array( "\n", "\r" ), array( 
  693. '\n',  
  694. '\r',  
  695. ), trim( var_export( $value, true ) ) ); 
  696. $buf .= "$key = $value\n"; 
  697.  
  698. return $buf; 
  699.  
  700. /** 
  701. * Order for adding the menus for the aioseop_modules_add_menus hook. 
  702. */ 
  703. function menu_order() { 
  704. return 10; 
  705.  
  706. /** 
  707. * Print a basic error message. 
  708. */ 
  709. function output_error( $error ) { 
  710. echo "<div class='aioseop_module error'>$error</div>"; 
  711.  
  712. return false; 
  713.  
  714. /*** 
  715. * Backwards compatibility - see http://php.net/manual/en/function.str-getcsv.php 
  716. */ 
  717. function str_getcsv( $input, $delimiter = ', ', $enclosure = '"', $escape = "\\" ) { 
  718. $fp = fopen( 'php://memory', 'r+' ); 
  719. fputs( $fp, $input ); 
  720. rewind( $fp ); 
  721. $data = fgetcsv( $fp, null, $delimiter, $enclosure ); // $escape only got added in 5.3.0 
  722. fclose( $fp ); 
  723.  
  724. return $data; 
  725.  
  726. /*** 
  727. * Helper function to convert csv in key/value pair format to an associative array. 
  728. */ 
  729. function csv_to_array( $csv ) { 
  730. $args = array(); 
  731. if ( ! function_exists( 'str_getcsv' ) ) { 
  732. $v = $this->str_getcsv( $csv ); 
  733. } else { 
  734. $v = str_getcsv( $csv ); 
  735. $size = count( $v ); 
  736. if ( is_array( $v ) && isset( $v[0] ) && $size >= 2 ) { 
  737. for ( $i = 0; $i < $size; $i += 2 ) { 
  738. $args[ $v[ $i ] ] = $v[ $i + 1 ]; 
  739.  
  740. return $args; 
  741.  
  742. /** Allow modules to use WP Filesystem if available and desired, fall back to PHP filesystem access otherwise. */ 
  743. function use_wp_filesystem( $method = '', $form_fields = false, $url = '', $error = false ) { 
  744. if ( empty( $method ) ) { 
  745. $this->credentials = request_filesystem_credentials( $url ); 
  746. } else { 
  747. $this->credentials = request_filesystem_credentials( $url, $method, $error, false, $form_fields ); 
  748.  
  749. return $this->credentials; 
  750.  
  751. /** 
  752. * Wrapper function to get filesystem object. 
  753. */ 
  754. function get_filesystem_object() { 
  755. $cred = get_transient( 'aioseop_fs_credentials' ); 
  756. if ( ! empty( $cred ) ) { 
  757. $this->credentials = $cred; 
  758.  
  759. if ( function_exists( 'WP_Filesystem' ) && WP_Filesystem( $this->credentials ) ) { 
  760. global $wp_filesystem; 
  761.  
  762. return $wp_filesystem; 
  763. } else { 
  764. require_once( ABSPATH . 'wp-admin/includes/template.php' ); 
  765. require_once( ABSPATH . 'wp-admin/includes/screen.php' ); 
  766. require_once( ABSPATH . 'wp-admin/includes/file.php' ); 
  767.  
  768. if ( ! WP_Filesystem( $this->credentials ) ) { 
  769. $this->use_wp_filesystem(); 
  770.  
  771. if ( ! empty( $this->credentials ) ) { 
  772. set_transient( 'aioseop_fs_credentials', $this->credentials, 10800 ); 
  773. global $wp_filesystem; 
  774. if ( is_object( $wp_filesystem ) ) { 
  775. return $wp_filesystem; 
  776.  
  777. return false; 
  778.  
  779. /** 
  780. * See if a file exists using WP Filesystem. 
  781. */ 
  782. function file_exists( $filename ) { 
  783. $wpfs = $this->get_filesystem_object(); 
  784. if ( is_object( $wpfs ) ) { 
  785. return $wpfs->exists( $filename ); 
  786.  
  787. return $wpfs; 
  788.  
  789. /** 
  790. * See if the directory entry is a file using WP Filesystem. 
  791. */ 
  792. function is_file( $filename ) { 
  793. $wpfs = $this->get_filesystem_object(); 
  794. if ( is_object( $wpfs ) ) { 
  795. return $wpfs->is_file( $filename ); 
  796.  
  797. return $wpfs; 
  798.  
  799. /** 
  800. * List files in a directory using WP Filesystem. 
  801. */ 
  802. function scandir( $path ) { 
  803. $wpfs = $this->get_filesystem_object(); 
  804. if ( is_object( $wpfs ) ) { 
  805. $dirlist = $wpfs->dirlist( $path ); 
  806. if ( empty( $dirlist ) ) { 
  807. return $dirlist; 
  808.  
  809. return array_keys( $dirlist ); 
  810.  
  811. return $wpfs; 
  812.  
  813. /** 
  814. * Load a file through WP Filesystem; implement basic support for offset and maxlen. 
  815. */ 
  816. function load_file( $filename, $use_include_path = false, $context = null, $offset = - 1, $maxlen = - 1 ) { 
  817. $wpfs = $this->get_filesystem_object(); 
  818. if ( is_object( $wpfs ) ) { 
  819. if ( ! $wpfs->exists( $filename ) ) { 
  820. return false; 
  821. if ( ( $offset > 0 ) || ( $maxlen >= 0 ) ) { 
  822. if ( $maxlen === 0 ) { 
  823. return ''; 
  824. if ( $offset < 0 ) { 
  825. $offset = 0; 
  826. $file = $wpfs->get_contents( $filename ); 
  827. if ( ! is_string( $file ) || empty( $file ) ) { 
  828. return $file; 
  829. if ( $maxlen < 0 ) { 
  830. return $this->substr( $file, $offset ); 
  831. } else { 
  832. return $this->substr( $file, $offset, $maxlen ); 
  833. } else { 
  834. return $wpfs->get_contents( $filename ); 
  835.  
  836. return false; 
  837.  
  838. /** 
  839. * Save a file through WP Filesystem. 
  840. */ 
  841. function save_file( $filename, $contents ) { 
  842. $failed_str = __( sprintf( "Failed to write file %s!\n", $filename ), 'all-in-one-seo-pack' ); 
  843. $readonly_str = __( sprintf( "File %s isn't writable!\n", $filename ), 'all-in-one-seo-pack' ); 
  844. $wpfs = $this->get_filesystem_object(); 
  845. if ( is_object( $wpfs ) ) { 
  846. $file_exists = $wpfs->exists( $filename ); 
  847. if ( ! $file_exists || $wpfs->is_writable( $filename ) ) { 
  848. if ( $wpfs->put_contents( $filename, $contents ) === false ) { 
  849. return $this->output_error( $failed_str ); 
  850. } else { 
  851. return $this->output_error( $readonly_str ); 
  852.  
  853. return true; 
  854.  
  855. return false; 
  856.  
  857. /** 
  858. * Delete a file through WP Filesystem. 
  859. */ 
  860. function delete_file( $filename ) { 
  861. $wpfs = $this->get_filesystem_object(); 
  862. if ( is_object( $wpfs ) ) { 
  863. if ( $wpfs->exists( $filename ) ) { 
  864. if ( $wpfs->delete( $filename ) === false ) { 
  865. $this->output_error( __( sprintf( "Failed to delete file %s!\n", $filename ), 'all-in-one-seo-pack' ) ); 
  866. } else { 
  867. return true; 
  868. } else { 
  869. $this->output_error( __( sprintf( "File %s doesn't exist!\n", $filename ), 'all-in-one-seo-pack' ) ); 
  870.  
  871. return false; 
  872.  
  873. /** 
  874. * Rename a file through WP Filesystem. 
  875. */ 
  876. function rename_file( $filename, $newname ) { 
  877. $wpfs = $this->get_filesystem_object(); 
  878. if ( is_object( $wpfs ) ) { 
  879. $file_exists = $wpfs->exists( $filename ); 
  880. $newfile_exists = $wpfs->exists( $newname ); 
  881. if ( $file_exists && ! $newfile_exists ) { 
  882. if ( $wpfs->move( $filename, $newname ) === false ) { 
  883. $this->output_error( __( sprintf( "Failed to rename file %s!\n", $filename ), 'all-in-one-seo-pack' ) ); 
  884. } else { 
  885. return true; 
  886. } else { 
  887. if ( ! $file_exists ) { 
  888. $this->output_error( __( sprintf( "File %s doesn't exist!\n", $filename ), 'all-in-one-seo-pack' ) ); 
  889. } elseif ( $newfile_exists ) { 
  890. $this->output_error( __( sprintf( "File %s already exists!\n", $newname ), 'all-in-one-seo-pack' ) ); 
  891.  
  892. return false; 
  893.  
  894. /** 
  895. * Load multiple files. 
  896. */ 
  897. function load_files( $options, $opts, $prefix ) { 
  898. foreach ( $opts as $opt => $file ) { 
  899. $opt = $prefix . $opt; 
  900. $file = ABSPATH . $file; 
  901. $contents = $this->load_file( $file ); 
  902. if ( $contents !== false ) { 
  903. $options[ $opt ] = $contents; 
  904.  
  905. return $options; 
  906.  
  907. /** 
  908. * Save multiple files. 
  909. */ 
  910. function save_files( $opts, $prefix ) { 
  911. foreach ( $opts as $opt => $file ) { 
  912. $opt = $prefix . $opt; 
  913. if ( isset( $_POST[ $opt ] ) ) { 
  914. $output = stripslashes_deep( $_POST[ $opt ] ); 
  915. $file = ABSPATH . $file; 
  916. $this->save_file( $file, $output ); 
  917.  
  918. /** 
  919. * Delete multiple files. 
  920. */ 
  921. function delete_files( $opts ) { 
  922. foreach ( $opts as $opt => $file ) { 
  923. $file = ABSPATH . $file; 
  924. $this->delete_file( $file ); 
  925.  
  926. function get_all_images_by_type( $options = null, $p = null ) { 
  927. $img = array(); 
  928. if ( empty( $img ) ) { 
  929. $size = apply_filters( 'post_thumbnail_size', 'large' ); 
  930.  
  931. global $aioseop_options, $wp_query, $aioseop_opengraph; 
  932.  
  933. if ( $p === null ) { 
  934. global $post; 
  935. } else { 
  936. $post = $p; 
  937.  
  938. $count = 1; 
  939.  
  940. if ( ! empty( $post ) ) { 
  941. if ( ! is_object( $post ) ) { 
  942. $post = get_post( $post ); 
  943. if ( is_object( $post ) && function_exists( 'get_post_thumbnail_id' ) ) { 
  944. if ( $post->post_type == 'attachment' ) { 
  945. $post_thumbnail_id = $post->ID; 
  946. } else { 
  947. $post_thumbnail_id = get_post_thumbnail_id( $post->ID ); 
  948. if ( ! empty( $post_thumbnail_id ) ) { 
  949. $image = wp_get_attachment_image_src( $post_thumbnail_id, $size ); 
  950. if ( is_array( $image ) ) { 
  951. $img[] = array( 'type' => 'featured', 'id' => $post_thumbnail_id, 'link' => $image[0] ); 
  952.  
  953. $post_id = $post->ID; 
  954. $p = $post; 
  955. $w = $wp_query; 
  956.  
  957. $meta_key = ''; 
  958. if ( is_array( $options ) && isset( $options['meta_key'] ) ) { 
  959. $meta_key = $options['meta_key']; 
  960.  
  961. if ( ! empty( $meta_key ) && ! empty( $post ) ) { 
  962. $meta_key = explode( ', ', $meta_key ); 
  963. $image = $this->get_the_image_by_meta_key( array( 
  964. 'post_id' => $post->ID,  
  965. 'meta_key' => $meta_key,  
  966. ) ); 
  967. if ( ! empty( $image ) ) { 
  968. $img[] = array( 'type' => 'meta_key', 'id' => $meta_key, 'link' => $image ); 
  969.  
  970. if ( ! $post->post_modified_gmt != '' ) { 
  971. $wp_query = new WP_Query( array( 'p' => $post_id, 'post_type' => $post->post_type ) ); 
  972. if ( $post->post_type == 'page' ) { 
  973. $wp_query->is_page = true; 
  974. } elseif ( $post->post_type == 'attachment' ) { 
  975. $wp_query->is_attachment = true; 
  976. } else { 
  977. $wp_query->is_single = true; 
  978. if ( get_option( 'show_on_front' ) == 'page' && $post->ID == get_option( 'page_for_posts' ) ) { 
  979. $wp_query->is_home = true; 
  980. $args['options']['type'] = 'html'; 
  981. $args['options']['nowrap'] = false; 
  982. $args['options']['save'] = false; 
  983. $wp_query->queried_object = $post; 
  984.  
  985. $attachments = get_children( array( 
  986. 'post_parent' => $post->ID,  
  987. 'post_status' => 'inherit',  
  988. 'post_type' => 'attachment',  
  989. 'post_mime_type' => 'image',  
  990. 'order' => 'ASC',  
  991. 'orderby' => 'menu_order ID',  
  992. ) ); 
  993. if ( ! empty( $attachments ) ) { 
  994. foreach ( $attachments as $id => $attachment ) { 
  995. $image = wp_get_attachment_image_src( $id, $size ); 
  996. if ( is_array( $image ) ) { 
  997. $img[] = array( 'type' => 'attachment', 'id' => $id, 'link' => $image[0] ); 
  998. $matches = array(); 
  999. preg_match_all( '|<img.*?src=[\'"](.*?)[\'"].*?>|i', get_post_field( 'post_content', $post->ID ), $matches ); 
  1000. if ( isset( $matches ) && ! empty( $matches[1] ) && ! empty( $matches[1][0] ) ) { 
  1001. foreach ( $matches[1] as $i => $m ) { 
  1002. $img[] = array( 'type' => 'post_content', 'id' => 'post' . $count ++, 'link' => $m ); 
  1003. wp_reset_postdata(); 
  1004. $wp_query = $w; 
  1005. $post = $p; 
  1006.  
  1007. return $img; 
  1008.  
  1009. function get_all_images( $options = null, $p = null ) { 
  1010. $img = $this->get_all_images_by_type( $options, $p ); 
  1011. $legacy = array(); 
  1012. foreach ( $img as $k => $v ) { 
  1013. if ( $v['type'] == 'featured' ) { 
  1014. $legacy[ $v['link'] ] = 1; 
  1015. } else { 
  1016. $legacy[ $v['link'] ] = $v['id']; 
  1017.  
  1018. return $legacy; 
  1019.  
  1020. /*** Thanks to Justin Tadlock for the original get-the-image code - http://themehybrid.com/plugins/get-the-image ***/ 
  1021.  
  1022. function get_the_image( $options = null, $p = null ) { 
  1023.  
  1024. if ( $p === null ) { 
  1025. global $post; 
  1026. } else { 
  1027. $post = $p; 
  1028.  
  1029. $meta_key = ''; 
  1030. if ( is_array( $options ) && isset( $options['meta_key'] ) ) { 
  1031. $meta_key = $options['meta_key']; 
  1032.  
  1033. if ( ! empty( $meta_key ) && ! empty( $post ) ) { 
  1034. $meta_key = explode( ', ', $meta_key ); 
  1035. $image = $this->get_the_image_by_meta_key( array( 
  1036. 'post_id' => $post->ID,  
  1037. 'meta_key' => $meta_key,  
  1038. ) ); 
  1039. if ( empty( $image ) ) { 
  1040. $image = $this->get_the_image_by_post_thumbnail( $post ); 
  1041. if ( empty( $image ) ) { 
  1042. $image = $this->get_the_image_by_attachment( $post ); 
  1043. if ( empty( $image ) ) { 
  1044. $image = $this->get_the_image_by_scan( $post ); 
  1045. if ( empty( $image ) ) { 
  1046. $image = $this->get_the_image_by_default( $post ); 
  1047.  
  1048. return $image; 
  1049.  
  1050. function get_the_image_by_default( $p = null ) { 
  1051. return ''; 
  1052.  
  1053. function get_the_image_by_meta_key( $args = array() ) { 
  1054.  
  1055. /** If $meta_key is not an array. */ 
  1056. if ( ! is_array( $args['meta_key'] ) ) { 
  1057. $args['meta_key'] = array( $args['meta_key'] ); 
  1058.  
  1059. /** Loop through each of the given meta keys. */ 
  1060. foreach ( $args['meta_key'] as $meta_key ) { 
  1061. /** Get the image URL by the current meta key in the loop. */ 
  1062. $image = get_post_meta( $args['post_id'], $meta_key, true ); 
  1063. /** If a custom key value has been given for one of the keys, return the image URL. */ 
  1064. if ( ! empty( $image ) ) { 
  1065. return $image; 
  1066.  
  1067. return false; 
  1068.  
  1069. function get_the_image_by_post_thumbnail( $p = null ) { 
  1070.  
  1071. if ( $p === null ) { 
  1072. global $post; 
  1073. } else { 
  1074. $post = $p; 
  1075.  
  1076. $post_thumbnail_id = null; 
  1077. if ( function_exists( 'get_post_thumbnail_id' ) ) { 
  1078. $post_thumbnail_id = get_post_thumbnail_id( $post->ID ); 
  1079.  
  1080. if ( empty( $post_thumbnail_id ) ) { 
  1081. return false; 
  1082.  
  1083. $size = apply_filters( 'post_thumbnail_size', 'large' ); // Check if someone is using built-in WP filter. 
  1084. $size = apply_filters( 'aioseop_thumbnail_size', $size ); 
  1085. $image = wp_get_attachment_image_src( $post_thumbnail_id, $size ); 
  1086.  
  1087. return $image[0]; 
  1088.  
  1089. function get_the_image_by_attachment( $p = null ) { 
  1090.  
  1091. if ( $p === null ) { 
  1092. global $post; 
  1093. } else { 
  1094. $post = $p; 
  1095.  
  1096. $attachments = get_children( array( 
  1097. 'post_parent' => $post->ID,  
  1098. 'post_status' => 'inherit',  
  1099. 'post_type' => 'attachment',  
  1100. 'post_mime_type' => 'image',  
  1101. 'order' => 'ASC',  
  1102. 'orderby' => 'menu_order ID',  
  1103. ) ); 
  1104.  
  1105. if ( empty( $attachments ) && 'attachment' == get_post_type( $post->ID ) ) { 
  1106. $size = 'large'; 
  1107. $size = apply_filters( 'aioseop_attachment_size', $size ); 
  1108. $image = wp_get_attachment_image_src( $post->ID, $size ); 
  1109.  
  1110. /** If no attachments or image is found, return false. */ 
  1111. if ( empty( $attachments ) && empty( $image ) ) { 
  1112. return false; 
  1113.  
  1114. /** Set the default iterator to 0. */ 
  1115. $i = 0; 
  1116.  
  1117. /** Loop through each attachment. Once the $order_of_image (default is '1') is reached, break the loop. */ 
  1118. foreach ( $attachments as $id => $attachment ) { 
  1119. if ( ++ $i == 1 ) { 
  1120. $size = 'large'; 
  1121. $size = apply_filters( 'aioseop_attachment_size', $size ); 
  1122. $image = wp_get_attachment_image_src( $id, $size ); 
  1123. $alt = trim( strip_tags( get_post_field( 'post_excerpt', $id ) ) ); 
  1124. break; 
  1125.  
  1126. /** Return the image URL. */ 
  1127.  
  1128. return $image[0]; 
  1129.  
  1130.  
  1131. function get_the_image_by_scan( $p = null ) { 
  1132.  
  1133. if ( $p === null ) { 
  1134. global $post; 
  1135. } else { 
  1136. $post = $p; 
  1137.  
  1138. /** Search the post's content for the <img /> tag and get its URL. */ 
  1139. preg_match_all( '|<img.*?src=[\'"](.*?)[\'"].*?>|i', get_post_field( 'post_content', $post->ID ), $matches ); 
  1140.  
  1141. /** If there is a match for the image, return its URL. */ 
  1142. if ( isset( $matches ) && ! empty( $matches[1][0] ) ) { 
  1143. return $matches[1][0]; 
  1144.  
  1145. return false; 
  1146.  
  1147. /** crude approximization of whether current user is an admin */ 
  1148. function is_admin() { 
  1149. return current_user_can( 'level_8' ); 
  1150.  
  1151. function help_text_helper( &$default_options, $options, $help_link = '' ) { 
  1152. foreach ( $options as $o ) { 
  1153. $ht = ''; 
  1154. if ( ! empty( $this->help_text[ $o ] ) ) { 
  1155. $ht = $this->help_text[ $o ]; 
  1156. } elseif ( ! empty( $default_options[ $o ]['help_text'] ) ) { 
  1157. $ht = $default_options[ $o ]['help_text']; 
  1158. if ( $ht && ! is_array( $ht ) ) { 
  1159. $ha = ''; 
  1160. $hl = $help_link; 
  1161. if ( strpos( $o, 'ga_' ) === 0 ) { // special case -- pdb 
  1162. $hl = 'http://semperplugins.com/documentation/advanced-google-analytics-settings/'; 
  1163. if ( ! empty( $this->help_anchors[ $o ] ) ) { 
  1164. $ha = $this->help_anchors[ $o ]; 
  1165. if ( ! empty( $ha ) && ( $pos = strrpos( $hl, '#' ) ) ) { 
  1166. $hl = substr( $hl, 0, $pos ); 
  1167. if ( ! empty( $ha ) && ( $ha[0] == 'h' ) ) { 
  1168. $hl = ''; 
  1169. if ( ! empty( $ha ) || ! isset( $this->help_anchors[ $o ] ) ) { 
  1170. $ht .= "<br /><a href='" . $hl . $ha . "' target='_blank'>" . __( 'Click here for documentation on this setting', 'all-in-one-seo-pack' ) . '</a>'; 
  1171. $default_options[ $o ]['help_text'] = $ht; 
  1172.  
  1173. function add_help_text_links() { 
  1174. if ( ! empty( $this->help_text ) ) { 
  1175. foreach ( $this->layout as $k => $v ) { 
  1176. $this->help_text_helper( $this->default_options, $v['options'], $v['help_link'] ); 
  1177. if ( ! empty( $this->locations ) ) { 
  1178. foreach ( $this->locations as $k => $v ) { 
  1179. if ( ! empty( $v['default_options'] ) && ! empty( $v['options'] ) ) { 
  1180. $this->help_text_helper( $this->locations[ $k ]['default_options'], $v['options'], $v['help_link'] ); 
  1181.  
  1182. /** 
  1183. * Load scripts and styles for metaboxes. 
  1184. * edit-tags exists only for pre 4.5 support... remove when we drop 4.5 support. 
  1185. * Also, that check and others should be pulled out into their own functions 
  1186. */ 
  1187. function enqueue_metabox_scripts() { 
  1188. $screen = ''; 
  1189. if ( function_exists( 'get_current_screen' ) ) { 
  1190. $screen = get_current_screen(); 
  1191. $bail = false; 
  1192. if ( empty( $screen ) ) { 
  1193. $bail = true; 
  1194. if( $bail != true ) { 
  1195. if ( ( $screen->base != 'post' ) && ( $screen->base != 'term' ) && ( $screen->base != 'edit-tags' ) && ( $screen->base != 'toplevel_page_shopp-products' ) ) { 
  1196. $bail = true; 
  1197. $prefix = $this->get_prefix(); 
  1198. $bail = apply_filters( $prefix . 'bail_on_enqueue', $bail, $screen ); 
  1199. if ( $bail ) { 
  1200. return; 
  1201. $this->form = 'post'; 
  1202. if ( $screen->base == 'term' || $screen->base == 'edit-tags' ) { 
  1203. $this->form = 'edittag'; 
  1204. if ( $screen->base == 'toplevel_page_shopp-products' ) { 
  1205. $this->form = 'product'; 
  1206. $this->form = apply_filters( $prefix . 'set_form_on_enqueue', $this->form, $screen ); 
  1207. foreach ( $this->locations as $k => $v ) { 
  1208. if ( $v['type'] === 'metabox' && isset( $v['display'] ) && ! empty( $v['display'] ) ) { 
  1209. $enqueue_scripts = false; 
  1210. $enqueue_scripts = ( ( ( $screen->base == 'toplevel_page_shopp-products' ) && in_array( 'shopp_product', $v['display'] ) ) ) || in_array( $screen->post_type, $v['display'] ); 
  1211. $enqueue_scripts = apply_filters( $prefix . 'enqueue_metabox_scripts', $enqueue_scripts, $screen, $v ); 
  1212. if ( $enqueue_scripts ) { 
  1213. add_filter( 'aioseop_localize_script_data', array( $this, 'localize_script_data' ) ); 
  1214. add_action( 'admin_print_scripts', array( $this, 'enqueue_scripts' ), 20 ); 
  1215. add_action( 'admin_print_scripts', array( $this, 'enqueue_styles' ), 20 ); 
  1216.  
  1217. /** 
  1218. * Load styles for module. 
  1219. */ 
  1220. function enqueue_styles() { 
  1221. wp_enqueue_style( 'thickbox' ); 
  1222. if ( ! empty( $this->pointers ) ) { 
  1223. wp_enqueue_style( 'wp-pointer' ); 
  1224. wp_enqueue_style( 'aioseop-module-style', AIOSEOP_PLUGIN_URL . 'css/modules/aioseop_module.css' ); 
  1225. if ( function_exists( 'is_rtl' ) && is_rtl() ) { 
  1226. wp_enqueue_style( 'aioseop-module-style-rtl', AIOSEOP_PLUGIN_URL . 'css/modules/aioseop_module-rtl.css', array( 'aioseop-module-style' ) ); 
  1227.  
  1228. /** 
  1229. * Load scripts for module, can pass data to module script. 
  1230. */ 
  1231. function enqueue_scripts() { 
  1232. wp_enqueue_script( 'sack' ); 
  1233. wp_enqueue_script( 'jquery' ); 
  1234. wp_enqueue_script( 'media-upload' ); 
  1235. wp_enqueue_script( 'thickbox' ); 
  1236. wp_enqueue_script( 'common' ); 
  1237. wp_enqueue_script( 'wp-lists' ); 
  1238. wp_enqueue_script( 'postbox' ); 
  1239. if ( ! empty( $this->pointers ) ) { 
  1240. wp_enqueue_script( 'wp-pointer', false, array( 'jquery' ) ); 
  1241. wp_enqueue_script( 'aioseop-module-script', AIOSEOP_PLUGIN_URL . 'js/modules/aioseop_module.js', array(), AIOSEOP_VERSION ); 
  1242. if ( ! empty( $this->script_data ) ) { 
  1243. aioseop_localize_script_data(); 
  1244.  
  1245. function localize_script_data( $data ) { 
  1246. if ( ! is_array( $data ) ) { 
  1247. $data = array( 0 => $data ); 
  1248. if ( empty( $this->script_data ) ) { 
  1249. $this->script_data = array(); 
  1250. if ( ! empty( $this->pointers ) ) { 
  1251. $this->script_data['pointers'] = $this->pointers; 
  1252. if ( empty( $data[0]['condshow'] ) ) { 
  1253. $data[0]['condshow'] = array(); 
  1254. if ( empty( $this->script_data['condshow'] ) ) { 
  1255. $this->script_data['condshow'] = array(); 
  1256. $condshow = $this->script_data['condshow']; 
  1257. $data[0]['condshow'] = array_merge( $data[0]['condshow'], $condshow ); 
  1258. unset( $this->script_data['condshow'] ); 
  1259. $data[0] = array_merge( $this->script_data, $data[0] ); 
  1260. $this->script_data['condshow'] = $condshow; 
  1261.  
  1262. return $data; 
  1263.  
  1264. /** 
  1265. * Override this to run code at the beginning of the settings page. 
  1266. */ 
  1267. function settings_page_init() { 
  1268.  
  1269.  
  1270. /** 
  1271. * Filter out admin pointers that have already been clicked. 
  1272. */ 
  1273. function filter_pointers() { 
  1274. if ( ! empty( $this->pointers ) ) { 
  1275. $dismissed = explode( ', ', (string) get_user_meta( get_current_user_id(), 'dismissed_wp_pointers', true ) ); 
  1276. foreach ( $dismissed as $d ) { 
  1277. if ( isset( $this->pointers[ $d ] ) ) { 
  1278. unset( $this->pointers[ $d ] ); 
  1279.  
  1280. /** 
  1281. * Add basic hooks when on the module's page. 
  1282. */ 
  1283. function add_page_hooks() { 
  1284. $hookname = current_filter(); 
  1285. if ( $this->strpos( $hookname, 'load-' ) === 0 ) { 
  1286. $this->pagehook = $this->substr( $hookname, 5 ); 
  1287. add_action( 'admin_print_scripts', array( $this, 'enqueue_scripts' ) ); 
  1288. add_action( 'admin_print_styles', array( $this, 'enqueue_styles' ) ); 
  1289. add_filter( 'aioseop_localize_script_data', array( $this, 'localize_script_data' ) ); 
  1290. add_action( $this->prefix . 'settings_header', array( $this, 'display_tabs' ) ); 
  1291.  
  1292. function get_admin_links() { 
  1293. if ( ! empty( $this->menu_name ) ) { 
  1294. $name = $this->menu_name; 
  1295. } else { 
  1296. $name = $this->name; 
  1297.  
  1298. $hookname = plugin_basename( $this->file ); 
  1299.  
  1300. $links = array(); 
  1301. $url = ''; 
  1302. if ( function_exists( 'menu_page_url' ) ) { 
  1303. $url = menu_page_url( $hookname, 0 ); 
  1304. if ( empty( $url ) ) { 
  1305. $url = esc_url( admin_url( 'admin.php?page=' . $hookname ) ); 
  1306.  
  1307. if ( $this->locations === null ) { 
  1308. array_unshift( $links, array( 
  1309. 'parent' => AIOSEOP_PLUGIN_DIRNAME,  
  1310. 'title' => $name,  
  1311. 'id' => $hookname,  
  1312. 'href' => $url,  
  1313. 'order' => $this->menu_order(),  
  1314. ) ); 
  1315. } else { 
  1316. foreach ( $this->locations as $k => $v ) { 
  1317. if ( $v['type'] === 'settings' ) { 
  1318. if ( $k === 'default' ) { 
  1319. array_unshift( $links, array( 
  1320. 'parent' => AIOSEOP_PLUGIN_DIRNAME,  
  1321. 'title' => $name,  
  1322. 'id' => $hookname,  
  1323. 'href' => $url,  
  1324. 'order' => $this->menu_order(),  
  1325. ) ); 
  1326. } else { 
  1327. if ( ! empty( $v['menu_name'] ) ) { 
  1328. $name = $v['menu_name']; 
  1329. } else { 
  1330. $name = $v['name']; 
  1331. array_unshift( $links, array( 
  1332. 'parent' => AIOSEOP_PLUGIN_DIRNAME,  
  1333. 'title' => $name,  
  1334. 'id' => $this->get_prefix( $k ) . $k,  
  1335. 'href' => esc_url( admin_url( 'admin.php?page=' . $this->get_prefix( $k ) . $k ) ),  
  1336. 'order' => $this->menu_order(),  
  1337. ) ); 
  1338.  
  1339. return $links; 
  1340.  
  1341. function add_admin_bar_submenu() { 
  1342. global $aioseop_admin_menu, $wp_admin_bar; 
  1343.  
  1344. if ( $aioseop_admin_menu ) { 
  1345. $links = $this->get_admin_links(); 
  1346. if ( ! empty( $links ) ) { 
  1347. foreach ( $links as $l ) { 
  1348. $wp_admin_bar->add_menu( $l ); 
  1349.  
  1350. /** 
  1351. * Collect metabox data together for tabbed metaboxes. 
  1352. */ 
  1353. function filter_return_metaboxes( $args ) { 
  1354. return array_merge( $args, $this->post_metaboxes ); 
  1355.  
  1356. /** Add submenu for module, call page hooks, set up metaboxes. */ 
  1357. function add_menu( $parent_slug ) { 
  1358. if ( ! empty( $this->menu_name ) ) { 
  1359. $name = $this->menu_name; 
  1360. } else { 
  1361. $name = $this->name; 
  1362. if ( $this->locations === null ) { 
  1363. $hookname = add_submenu_page( $parent_slug, $name, $name, apply_filters( 'manage_aiosp', 'aiosp_manage_seo' ), plugin_basename( $this->file ), array( 
  1364. $this,  
  1365. 'display_settings_page',  
  1366. ) ); 
  1367. add_action( "load-{$hookname}", array( $this, 'add_page_hooks' ) ); 
  1368.  
  1369. return true; 
  1370. foreach ( $this->locations as $k => $v ) { 
  1371. if ( $v['type'] === 'settings' ) { 
  1372. if ( $k === 'default' ) { 
  1373. if ( ! empty( $this->menu_name ) ) { 
  1374. $name = $this->menu_name; 
  1375. } else { 
  1376. $name = $this->name; 
  1377. $hookname = add_submenu_page( $parent_slug, $name, $name, apply_filters( 'manage_aiosp', 'aiosp_manage_seo' ), plugin_basename( $this->file ), array( 
  1378. $this,  
  1379. 'display_settings_page',  
  1380. ) ); 
  1381. } else { 
  1382. if ( ! empty( $v['menu_name'] ) ) { 
  1383. $name = $v['menu_name']; 
  1384. } else { 
  1385. $name = $v['name']; 
  1386. $hookname = add_submenu_page( $parent_slug, $name, $name, apply_filters( 'manage_aiosp', 'aiosp_manage_seo' ), $this->get_prefix( $k ) . $k, array( 
  1387. $this,  
  1388. "display_settings_page_$k",  
  1389. ) ); 
  1390. add_action( "load-{$hookname}", array( $this, 'add_page_hooks' ) ); 
  1391. } elseif ( $v['type'] === 'metabox' ) { 
  1392. $this->setting_options( $k ); // hack -- make sure this runs anyhow, for now -- pdb 
  1393. add_action( 'edit_post', array( $this, 'save_post_data' ) ); 
  1394. add_action( 'publish_post', array( $this, 'save_post_data' ) ); 
  1395. add_action( 'add_attachment', array( $this, 'save_post_data' ) ); 
  1396. add_action( 'edit_attachment', array( $this, 'save_post_data' ) ); 
  1397. add_action( 'save_post', array( $this, 'save_post_data' ) ); 
  1398. add_action( 'edit_page_form', array( $this, 'save_post_data' ) ); 
  1399. if ( isset( $v['display'] ) && ! empty( $v['display'] ) ) { 
  1400. add_action( 'admin_print_scripts', array( $this, 'enqueue_metabox_scripts' ), 5 ); 
  1401. if ( $this->tabbed_metaboxes ) { 
  1402. add_filter( 'aioseop_add_post_metabox', array( $this, 'filter_return_metaboxes' ) ); 
  1403. foreach ( $v['display'] as $posttype ) { 
  1404. $v['location'] = $k; 
  1405. $v['posttype'] = $posttype; 
  1406. if ( ! isset( $v['context'] ) ) { 
  1407. $v['context'] = 'advanced'; 
  1408. if ( ! isset( $v['priority'] ) ) { 
  1409. $v['priority'] = 'default'; 
  1410. if ( $this->tabbed_metaboxes ) { 
  1411. $this->post_metaboxes[] = array( 
  1412. 'id' => $v['prefix'] . $k,  
  1413. 'title' => $v['name'],  
  1414. 'callback' => array( $this, 'display_metabox' ),  
  1415. 'post_type' => $posttype,  
  1416. 'context' => $v['context'],  
  1417. 'priority' => $v['priority'],  
  1418. 'callback_args' => $v,  
  1419. ); 
  1420. } else { 
  1421. $title = $v['name']; 
  1422. if ( $title != $this->plugin_name ) { 
  1423. $title = $this->plugin_name . ' - ' . $title; 
  1424. if ( ! empty( $v['help_link'] ) ) { 
  1425. $title .= "<a class='aioseop_help_text_link aioseop_meta_box_help' target='_blank' href='" . $lopts['help_link'] . "'><span>" . __( 'Help', 'all-in-one-seo-pack' ) . '</span></a>'; 
  1426. add_meta_box( $v['prefix'] . $k, $title, array( 
  1427. $this,  
  1428. 'display_metabox',  
  1429. ), $posttype, $v['context'], $v['priority'], $v ); 
  1430.  
  1431. /** 
  1432. * Update postmeta for metabox. 
  1433. */ 
  1434. function save_post_data( $post_id ) { 
  1435. static $update = false; 
  1436. if ( $update ) { 
  1437. return; 
  1438. if ( $this->locations !== null ) { 
  1439. foreach ( $this->locations as $k => $v ) { 
  1440. if ( isset( $v['type'] ) && ( $v['type'] === 'metabox' ) ) { 
  1441. $opts = $this->default_options( $k ); 
  1442. $options = array(); 
  1443. $update = false; 
  1444. foreach ( $opts as $l => $o ) { 
  1445. if ( isset( $_POST[ $l ] ) ) { 
  1446. $options[ $l ] = stripslashes_deep( $_POST[ $l ] ); 
  1447. $options[ $l ] = esc_attr( $options[ $l ] ); 
  1448. $update = true; 
  1449. if ( $update ) { 
  1450. $prefix = $this->get_prefix( $k ); 
  1451. $options = apply_filters( $prefix . 'filter_metabox_options', $options, $k, $post_id ); 
  1452. update_post_meta( $post_id, '_' . $prefix . $k, $options ); 
  1453.  
  1454. /** 
  1455. * Outputs radio buttons, checkboxes, selects, multiselects, handles groups. 
  1456. */ 
  1457. function do_multi_input( $args ) { 
  1458. extract( $args ); 
  1459. $buf1 = ''; 
  1460. $type = $options['type']; 
  1461. if ( ( $type == 'radio' ) || ( $type == 'checkbox' ) ) { 
  1462. $strings = array( 
  1463. 'block' => "%s\n",  
  1464. 'group' => "\t<b>%s</b><br>\n%s\n",  
  1465. 'item' => "\t<label class='aioseop_option_setting_label'><input type='$type' %s name='%s' value='%s' %s> %s</label>\n",  
  1466. 'item_args' => array( 'sel', 'name', 'v', 'attr', 'subopt' ),  
  1467. 'selected' => 'checked ',  
  1468. ); 
  1469. } else { 
  1470. $strings = array( 
  1471. 'block' => "<select name='$name' $attr>%s\n</select>\n",  
  1472. 'group' => "\t<optgroup label='%s'>\n%s\t</optgroup>\n",  
  1473. 'item' => "\t<option %s value='%s'>%s</option>\n",  
  1474. 'item_args' => array( 'sel', 'v', 'subopt' ),  
  1475. 'selected' => 'selected ',  
  1476. ); 
  1477. $setsel = $strings['selected']; 
  1478. if ( isset( $options['initial_options'] ) && is_array( $options['initial_options'] ) ) { 
  1479. foreach ( $options['initial_options'] as $l => $option ) { 
  1480. $is_group = is_array( $option ); 
  1481. if ( ! $is_group ) { 
  1482. $option = array( $l => $option ); 
  1483. $buf2 = ''; 
  1484. foreach ( $option as $v => $subopt ) { 
  1485. $sel = ''; 
  1486. $is_arr = is_array( $value ); 
  1487. if ( is_string( $v ) || is_string( $value ) ) { 
  1488. if ( is_string( $value ) ) { 
  1489. $cmp = ! strcmp( $v, $value ); 
  1490. } else { 
  1491. $cmp = ! strcmp( $v, '' ); 
  1492. // $cmp = !strcmp( (string)$v, (string)$value ); 
  1493. } else { 
  1494. $cmp = ( $value == $v ); 
  1495. if ( ( ! $is_arr && $cmp ) || ( $is_arr && in_array( $v, $value ) ) ) { 
  1496. $sel = $setsel; 
  1497. $item_arr = array(); 
  1498. foreach ( $strings['item_args'] as $arg ) { 
  1499. $item_arr[] = $$arg; 
  1500. $buf2 .= vsprintf( $strings['item'], $item_arr ); 
  1501. if ( $is_group ) { 
  1502. $buf1 .= sprintf( $strings['group'], $l, $buf2 ); 
  1503. } else { 
  1504. $buf1 .= $buf2; 
  1505. $buf1 = sprintf( $strings['block'], $buf1 ); 
  1506.  
  1507. return $buf1; 
  1508.  
  1509. /** 
  1510. * Outputs a setting item for settings pages and metaboxes. 
  1511. */ 
  1512. function get_option_html( $args ) { 
  1513. static $n = 0; 
  1514. extract( $args ); 
  1515. if ( $options['type'] == 'custom' ) { 
  1516. return apply_filters( "{$prefix}output_option", '', $args ); 
  1517. if ( in_array( $options['type'], array( 
  1518. 'multiselect',  
  1519. 'select',  
  1520. 'multicheckbox',  
  1521. 'radio',  
  1522. 'checkbox',  
  1523. 'textarea',  
  1524. 'text',  
  1525. 'submit',  
  1526. 'hidden',  
  1527. ) ) && is_string( $value ) 
  1528. ) { 
  1529. $value = esc_attr( $value ); 
  1530. $buf = ''; 
  1531. $onload = ''; 
  1532. if ( ! empty( $options['count'] ) ) { 
  1533. $n ++; 
  1534. $attr .= " onKeyDown='if (typeof countChars == \"function\") countChars(document.{$this->form}.$name, document.{$this->form}.{$prefix}length$n)' onKeyUp='if (typeof countChars == \"function\") countChars(document.{$this->form}.$name, document.{$this->form}.{$prefix}length$n)'"; 
  1535. $onload = "if (typeof countChars == \"function\") countChars(document.{$this->form}.$name, document.{$this->form}.{$prefix}length$n);"; 
  1536. if ( isset( $opts['id'] ) ) { 
  1537. $attr .= " id=\"{$opts['id']}\" "; 
  1538. switch ( $options['type'] ) { 
  1539. case 'multiselect': 
  1540. $attr .= ' MULTIPLE'; 
  1541. $args['attr'] = $attr; 
  1542. $args['name'] = $name = "{$name}[]"; 
  1543. case 'select': 
  1544. $buf .= $this->do_multi_input( $args ); 
  1545. break; 
  1546. case 'multicheckbox': 
  1547. $args['name'] = $name = "{$name}[]"; 
  1548. $args['options']['type'] = $options['type'] = 'checkbox'; 
  1549. case 'radio': 
  1550. $buf .= $this->do_multi_input( $args ); 
  1551. break; 
  1552. case 'checkbox': 
  1553. if ( $value ) { 
  1554. $attr .= ' CHECKED'; 
  1555. $buf .= "<input name='$name' type='{$options['type']}' $attr>\n"; 
  1556. break; 
  1557. case 'textarea': 
  1558. $buf .= "<textarea name='$name' $attr>$value</textarea>"; 
  1559. break; 
  1560. case 'image': 
  1561. $buf .= "<input class='aioseop_upload_image_button button-primary' type='button' value='Upload Image' style='float:left;' />" . 
  1562. "<input class='aioseop_upload_image_label' name='$name' type='text' $attr value='$value' size=57 style='float:left;clear:left;'>\n"; 
  1563. break; 
  1564. case 'html': 
  1565. $buf .= $value; 
  1566. break; 
  1567. case 'esc_html': 
  1568. $buf .= "<pre>" . esc_html( $value ) . "</pre>\n"; 
  1569. break; 
  1570. default: 
  1571. $buf .= "<input name='$name' type='{$options['type']}' $attr value='$value'>\n"; 
  1572. if ( ! empty( $options['count'] ) ) { 
  1573. $size = 60; 
  1574. if ( isset( $options['size'] ) ) { 
  1575. $size = $options['size']; 
  1576. } elseif ( isset( $options['rows'] ) && isset( $options['cols'] ) ) { 
  1577. $size = $options['rows'] * $options['cols']; 
  1578. if ( isset( $options['count_desc'] ) ) { 
  1579. $count_desc = $options['count_desc']; 
  1580. } else { 
  1581. $count_desc = __( ' characters. Most search engines use a maximum of %s chars for the %s.', 'all-in-one-seo-pack' ); 
  1582. $buf .= "<br /><input readonly type='text' name='{$prefix}length$n' size='3' maxlength='3' style='width:53px;height:23px;margin:0px;padding:0px 0px 0px 10px;' value='" . $this->strlen( $value ) . "' />" 
  1583. . sprintf( $count_desc, $size, trim( $this->strtolower( $options['name'] ), ':' ) ); 
  1584. if ( ! empty( $onload ) ) { 
  1585. $buf .= "<script>jQuery( document ).ready(function() { {$onload} });</script>"; 
  1586.  
  1587. return $buf; 
  1588.  
  1589. const DISPLAY_HELP_START = '<a class="aioseop_help_text_link" style="cursor:pointer;" title="%s" onclick="toggleVisibility(\'%s_tip\');"><label class="aioseop_label textinput">%s</label></a>'; 
  1590. const DISPLAY_HELP_END = '<div class="aioseop_help_text_div" style="display:none" id="%s_tip"><label class="aioseop_help_text">%s</label></div>'; 
  1591. const DISPLAY_LABEL_FORMAT = '<span class="aioseop_option_label" style="text-align:%s;vertical-align:top;">%s</span>'; 
  1592. const DISPLAY_TOP_LABEL = "</div>\n<div class='aioseop_input aioseop_top_label'>\n"; 
  1593. const DISPLAY_ROW_TEMPLATE = '<div class="aioseop_wrapper%s" id="%s_wrapper"><div class="aioseop_input">%s<span class="aioseop_option_input"><div class="aioseop_option_div" %s>%s</div>%s</span><p style="clear:left"></p></div></div>'; 
  1594.  
  1595. /** 
  1596. * Format a row for an option on a settings page. 
  1597. */ 
  1598. function get_option_row( $name, $opts, $args ) { 
  1599. $label_text = $input_attr = $help_text_2 = $id_attr = ''; 
  1600. if ( $opts['label'] == 'top' ) { 
  1601. $align = 'left'; 
  1602. } else { 
  1603. $align = 'right'; 
  1604. if ( isset( $opts['id'] ) ) { 
  1605. $id_attr .= " id=\"{$opts['id']}_div\" "; 
  1606. if ( $opts['label'] != 'none' ) { 
  1607. if ( isset( $opts['help_text'] ) ) { 
  1608. $help_text = sprintf( All_in_One_SEO_Pack_Module::DISPLAY_HELP_START, __( 'Click for Help!', 'all-in-one-seo-pack' ), $name, $opts['name'] ); 
  1609. $help_text_2 = sprintf( All_in_One_SEO_Pack_Module::DISPLAY_HELP_END, $name, $opts['help_text'] ); 
  1610. } else { 
  1611. $help_text = $opts['name']; 
  1612. $label_text = sprintf( All_in_One_SEO_Pack_Module::DISPLAY_LABEL_FORMAT, $align, $help_text ); 
  1613. } else { 
  1614. $input_attr .= ' aioseop_no_label '; 
  1615. if ( $opts['label'] == 'top' ) { 
  1616. $label_text .= All_in_One_SEO_Pack_Module::DISPLAY_TOP_LABEL; 
  1617. $input_attr .= " aioseop_{$opts['type']}_type"; 
  1618.  
  1619. return sprintf( All_in_One_SEO_Pack_Module::DISPLAY_ROW_TEMPLATE, $input_attr, $name, $label_text, $id_attr, $this->get_option_html( $args ), $help_text_2 ); 
  1620.  
  1621. /** 
  1622. * Display options for settings pages and metaboxes, allows for filtering settings, custom display options. 
  1623. */ 
  1624. function display_options( $location = null, $meta_args = null ) { 
  1625. static $location_settings = array(); 
  1626. $defaults = null; 
  1627. $prefix = $this->get_prefix( $location ); 
  1628. $help_link = ''; 
  1629. if ( is_array( $meta_args['args'] ) && ! empty( $meta_args['args']['default_options'] ) ) { 
  1630. $defaults = $meta_args['args']['default_options']; 
  1631. if ( ! empty( $meta_args['callback_args'] ) && ! empty( $meta_args['callback_args']['help_link'] ) ) { 
  1632. $help_link = $meta_args['callback_args']['help_link']; 
  1633. if ( ! empty( $help_link ) ) { 
  1634. echo "<a class='aioseop_help_text_link aioseop_meta_box_help' target='_blank' href='" . $help_link . "'><span>" . __( 'Help', 'all-in-one-seo-pack' ) . '</span></a>'; 
  1635.  
  1636. if ( ! isset( $location_settings[ $prefix ] ) ) { 
  1637. $current_options = apply_filters( "{$this->prefix}display_options", $this->get_current_options( array(), $location, $defaults ), $location ); 
  1638. $settings = apply_filters( "{$this->prefix}display_settings", $this->setting_options( $location, $defaults ), $location, $current_options ); 
  1639. $current_options = apply_filters( "{$this->prefix}override_options", $current_options, $location, $settings ); 
  1640. $location_settings[ $prefix ]['current_options'] = $current_options; 
  1641. $location_settings[ $prefix ]['settings'] = $settings; 
  1642. } else { 
  1643. $current_options = $location_settings[ $prefix ]['current_options']; 
  1644. $settings = $location_settings[ $prefix ]['settings']; 
  1645. // $opts["snippet"]["default"] = sprintf( $opts["snippet"]["default"], "foo", "bar", "moby" ); 
  1646. $container = "<div class='aioseop aioseop_options {$this->prefix}settings'>"; 
  1647. if ( is_array( $meta_args['args'] ) && ! empty( $meta_args['args']['options'] ) ) { 
  1648. $args = array(); 
  1649. $arg_keys = array(); 
  1650. foreach ( $meta_args['args']['options'] as $a ) { 
  1651. if ( ! empty( $location ) ) { 
  1652. $key = $prefix . $location . '_' . $a; 
  1653. if ( ! isset( $settings[ $key ] ) ) { 
  1654. $key = $a; 
  1655. } else { 
  1656. $key = $prefix . $a; 
  1657. if ( isset( $settings[ $key ] ) ) { 
  1658. $arg_keys[ $key ] = 1; 
  1659. } elseif ( isset( $settings[ $a ] ) ) { 
  1660. $arg_keys[ $a ] = 1; 
  1661. $setting_keys = array_keys( $settings ); 
  1662. foreach ( $setting_keys as $s ) { 
  1663. if ( ! empty( $arg_keys[ $s ] ) ) { 
  1664. $args[ $s ] = $settings[ $s ]; 
  1665. } else { 
  1666. $args = $settings; 
  1667. foreach ( $args as $name => $opts ) { 
  1668. $attr_list = array( 'class', 'style', 'readonly', 'disabled', 'size', 'placeholder' ); 
  1669. if ( $opts['type'] == 'textarea' ) { 
  1670. $attr_list = array_merge( $attr_list, array( 'rows', 'cols' ) ); 
  1671. $attr = ''; 
  1672. foreach ( $attr_list as $a ) { 
  1673. if ( isset( $opts[ $a ] ) ) { 
  1674. $attr .= ' ' . $a . '="' . esc_attr( $opts[ $a ] ) . '" '; 
  1675. $opt = ''; 
  1676. if ( isset( $current_options[ $name ] ) ) { 
  1677. $opt = $current_options[ $name ]; 
  1678. if ( $opts['label'] == 'none' && $opts['type'] == 'submit' && $opts['save'] == false ) { 
  1679. $opt = $opts['name']; 
  1680. if ( $opts['type'] == 'html' && empty( $opt ) && $opts['save'] == false ) { 
  1681. $opt = $opts['default']; 
  1682.  
  1683. $args = array( 
  1684. 'name' => $name,  
  1685. 'options' => $opts,  
  1686. 'attr' => $attr,  
  1687. 'value' => $opt,  
  1688. 'prefix' => $prefix,  
  1689. ); 
  1690. if ( ! empty( $opts['nowrap'] ) ) { 
  1691. echo $this->get_option_html( $args ); 
  1692. } else { 
  1693. if ( $container ) { 
  1694. echo $container; 
  1695. $container = ''; 
  1696. echo $this->get_option_row( $name, $opts, $args ); 
  1697. if ( ! $container ) { 
  1698. echo '</div>'; 
  1699.  
  1700. function sanitize_domain( $domain ) { 
  1701. $domain = trim( $domain ); 
  1702. $domain = $this->strtolower( $domain ); 
  1703. if ( $this->strpos( $domain, 'http://' ) === 0 ) { 
  1704. $domain = $this->substr( $domain, 7 ); 
  1705. } elseif ( $this->strpos( $domain, 'https://' ) === 0 ) { 
  1706. $domain = $this->substr( $domain, 8 ); 
  1707. $domain = untrailingslashit( $domain ); 
  1708.  
  1709. return $domain; 
  1710.  
  1711. /** Sanitize options */ 
  1712. function sanitize_options( $location = null ) { 
  1713. foreach ( $this->setting_options( $location ) as $k => $v ) { 
  1714. if ( isset( $this->options[ $k ] ) ) { 
  1715. if ( ! empty( $v['sanitize'] ) ) { 
  1716. $type = $v['sanitize']; 
  1717. } else { 
  1718. $type = $v['type']; 
  1719. switch ( $type ) { 
  1720. case 'multiselect': 
  1721. case 'multicheckbox': 
  1722. $this->options[ $k ] = urlencode_deep( $this->options[ $k ] ); 
  1723. break; 
  1724. case 'textarea': 
  1725. $this->options[ $k ] = wp_kses_post( $this->options[ $k ] ); 
  1726. $this->options[ $k ] = htmlspecialchars( $this->options[ $k ], ENT_QUOTES ); 
  1727. break; 
  1728. case 'filename': 
  1729. $this->options[ $k ] = sanitize_file_name( $this->options[ $k ] ); 
  1730. break; 
  1731. case 'text': 
  1732. $this->options[ $k ] = wp_kses_post( $this->options[ $k ] ); 
  1733. case 'checkbox': 
  1734. case 'radio': 
  1735. case 'select': 
  1736. default: 
  1737. if ( ! is_array( $this->options[ $k ] ) ) { 
  1738. $this->options[ $k ] = esc_attr( $this->options[ $k ] ); 
  1739.  
  1740. /** 
  1741. * Display metaboxes with display_options() 
  1742. */ 
  1743. function display_metabox( $post, $metabox ) { 
  1744. $this->display_options( $metabox['args']['location'], $metabox ); 
  1745.  
  1746. /** 
  1747. * Handle resetting options to defaults. 
  1748. */ 
  1749. function reset_options( $location = null, $delete = false ) { 
  1750. if ( $delete === true ) { 
  1751. $this->delete_class_option( $delete ); 
  1752. $this->options = array(); 
  1753. $default_options = $this->default_options( $location ); 
  1754. foreach ( $default_options as $k => $v ) { 
  1755. $this->options[ $k ] = $v; 
  1756. $this->update_class_option( $this->options ); 
  1757.  
  1758. /** handle option resetting and updating */ 
  1759. function handle_settings_updates( $location = null ) { 
  1760. $message = ''; 
  1761. if ( ( isset( $_POST['action'] ) && $_POST['action'] == 'aiosp_update_module' && 
  1762. ( isset( $_POST['Submit_Default'] ) || isset( $_POST['Submit_All_Default'] ) || ! empty( $_POST['Submit'] ) ) ) 
  1763. ) { 
  1764. $nonce = $_POST['nonce-aioseop']; 
  1765. if ( ! wp_verify_nonce( $nonce, 'aioseop-nonce' ) ) { 
  1766. die ( __( 'Security Check - If you receive this in error, log out and back in to WordPress', 'all-in-one-seo-pack' ) ); 
  1767. if ( isset( $_POST['Submit_Default'] ) || isset( $_POST['Submit_All_Default'] ) ) { 
  1768. $message = __( 'Options Reset.', 'all-in-one-seo-pack' ); 
  1769. if ( isset( $_POST['Submit_All_Default'] ) ) { 
  1770. $this->reset_options( $location, true ); 
  1771. do_action( 'aioseop_options_reset' ); 
  1772. } else { 
  1773. $this->reset_options( $location ); 
  1774. if ( ! empty( $_POST['Submit'] ) ) { 
  1775. $message = __( 'All in One SEO Options Updated.', 'all-in-one-seo-pack' ); 
  1776. $default_options = $this->default_options( $location ); 
  1777. foreach ( $default_options as $k => $v ) { 
  1778. if ( isset( $_POST[ $k ] ) ) { 
  1779. $this->options[ $k ] = stripslashes_deep( $_POST[ $k ] ); 
  1780. } else { 
  1781. $this->options[ $k ] = ''; 
  1782. $this->sanitize_options( $location ); 
  1783. $this->options = apply_filters( $this->prefix . 'update_options', $this->options, $location ); 
  1784. $this->update_class_option( $this->options ); 
  1785. wp_cache_flush(); 
  1786. do_action( $this->prefix . 'settings_update', $this->options, $location ); 
  1787.  
  1788. return $message; 
  1789.  
  1790. /** Update / reset settings, printing options, sanitizing, posting back */ 
  1791. function display_settings_page( $location = null ) { 
  1792. if ( $location != null ) { 
  1793. $location_info = $this->locations[ $location ]; 
  1794. $name = null; 
  1795. if ( $location && isset( $location_info['name'] ) ) { 
  1796. $name = $location_info['name']; 
  1797. if ( ! $name ) { 
  1798. $name = $this->name; 
  1799. $message = $this->handle_settings_updates( $location ); 
  1800. $this->settings_page_init(); 
  1801. ?> 
  1802. <div class="wrap <?php echo get_class( $this ); ?>"> 
  1803. <div id="aioseop_settings_header"> 
  1804. <?php if ( ! empty( $message ) ) { 
  1805. echo "<div id=\"message\" class=\"updated fade\"><p>$message</p></div>"; 
  1806. } ?> 
  1807. <div id="icon-aioseop" class="icon32"><br></div> 
  1808. <h2><?php echo $name; ?></h2> 
  1809. <div id="dropmessage" class="updated" style="display:none;"></div> 
  1810. </div> 
  1811. <?php 
  1812. do_action( 'aioseop_global_settings_header', $location ); 
  1813. do_action( $this->prefix . 'settings_header', $location ); 
  1814. ?> 
  1815. <form id="aiosp_settings_form" name="dofollow" enctype="multipart/form-data" action="" method="post"> 
  1816. <div id="aioseop_top_button"> 
  1817. <div id="aiosp_ajax_settings_message"></div> 
  1818. <?php 
  1819.  
  1820. $submit_options = array( 
  1821. 'action' => array( 'type' => 'hidden', 'value' => 'aiosp_update_module' ),  
  1822. 'module' => array( 'type' => 'hidden', 'value' => get_class( $this ) ),  
  1823. 'location' => array( 'type' => 'hidden', 'value' => $location ),  
  1824. 'nonce-aioseop' => array( 
  1825. 'type' => 'hidden',  
  1826. 'value' => wp_create_nonce( 'aioseop-nonce' ),  
  1827. ),  
  1828. 'page_options' => array( 'type' => 'hidden', 'value' => 'aiosp_home_description' ),  
  1829. 'Submit' => array( 
  1830. 'type' => 'submit',  
  1831. 'class' => 'button-primary',  
  1832. 'value' => __( 'Update Options', 'all-in-one-seo-pack' ) . ' »',  
  1833. ),  
  1834. 'Submit_Default' => array( 
  1835. 'type' => 'submit',  
  1836. 'class' => 'button-secondary',  
  1837. 'value' => __( sprintf( 'Reset %s Settings to Defaults', $name ), 'all-in-one-seo-pack' ) . ' »',  
  1838. ),  
  1839. ); 
  1840. $submit_options = apply_filters( "{$this->prefix}submit_options", $submit_options, $location ); 
  1841. foreach ( $submit_options as $k => $s ) { 
  1842. if ( $s['type'] == 'submit' && $k != 'Submit' ) { 
  1843. continue; 
  1844. $class = ''; 
  1845. if ( isset( $s['class'] ) ) { 
  1846. $class = " class='{$s['class']}' "; 
  1847. echo $this->get_option_html( array( 
  1848. 'name' => $k,  
  1849. 'options' => $s,  
  1850. 'attr' => $class,  
  1851. 'value' => $s['value'],  
  1852. ) ); 
  1853. ?> 
  1854. </div> 
  1855. <div class="aioseop_options_wrapper aioseop_settings_left"> 
  1856. <?php $opts = $this->get_class_option(); 
  1857. if ( $opts !== false ) { 
  1858. $this->options = $opts; 
  1859. if ( is_array( $this->layout ) ) { 
  1860. foreach ( $this->layout as $l => $lopts ) { 
  1861. if ( ! isset( $lopts['tab'] ) || ( $this->current_tab == $lopts['tab'] ) ) { 
  1862. $title = $lopts['name']; 
  1863. if ( ! empty( $lopts['help_link'] ) ) { 
  1864. $title .= "<a class='aioseop_help_text_link aioseop_meta_box_help' target='_blank' href='" . $lopts['help_link'] . "'><span>" . __( 'Help', 'all-in-one-seo-pack' ) . '</span></a>'; 
  1865. add_meta_box( $this->get_prefix( $location ) . $l . '_metabox', $title, array( 
  1866. $this,  
  1867. 'display_options',  
  1868. ),  
  1869. "{$this->prefix}settings", 'advanced', 'default', $lopts ); 
  1870. } else { 
  1871. add_meta_box( $this->get_prefix( $location ) . 'metabox', $name, array( 
  1872. $this,  
  1873. 'display_options',  
  1874. ), "{$this->prefix}settings", 'advanced' ); 
  1875. do_meta_boxes( "{$this->prefix}settings", 'advanced', $location ); 
  1876. ?> <p class="submit" style="clear:both;"><?php 
  1877. foreach ( array( 'action', 'nonce-aioseop', 'page_options' ) as $submit_field ) { 
  1878. if ( isset( $submit_field ) ) { 
  1879. unset( $submit_field ); 
  1880. foreach ( $submit_options as $k => $s ) { 
  1881. $class = ''; 
  1882. if ( isset( $s['class'] ) ) { 
  1883. $class = " class='{$s['class']}' "; 
  1884. echo $this->get_option_html( array( 
  1885. 'name' => $k,  
  1886. 'options' => $s,  
  1887. 'attr' => $class,  
  1888. 'value' => $s['value'],  
  1889. ) ); 
  1890. ?> </p> 
  1891. </div> 
  1892. </form> 
  1893. <?php do_action( $this->prefix . 'settings_footer', $location ); 
  1894. do_action( 'aioseop_global_settings_footer', $location ); ?> 
  1895. </div> <?php 
  1896.  
  1897. /** 
  1898. * Get the prefix used for a given location. 
  1899. */ 
  1900. function get_prefix( $location = null ) { 
  1901. if ( ( $location != null ) && isset( $this->locations[ $location ]['prefix'] ) ) { 
  1902. return $this->locations[ $location ]['prefix']; 
  1903.  
  1904. return $this->prefix; 
  1905.  
  1906. /** Sets up initial settings */ 
  1907. function setting_options( $location = null, $defaults = null ) { 
  1908. if ( $defaults === null ) { 
  1909. $defaults = $this->default_options; 
  1910. $prefix = $this->get_prefix( $location ); 
  1911. $opts = array(); 
  1912. if ( $location == null || $this->locations[ $location ]['options'] === null ) { 
  1913. $options = $defaults; 
  1914. } else { 
  1915. $options = array(); 
  1916. $prefix = "{$prefix}{$location}_"; 
  1917. if ( ! empty( $this->locations[ $location ]['default_options'] ) ) { 
  1918. $options = $this->locations[ $location ]['default_options']; 
  1919. foreach ( $this->locations[ $location ]['options'] as $opt ) { 
  1920. if ( isset( $defaults[ $opt ] ) ) { 
  1921. $options[ $opt ] = $defaults[ $opt ]; 
  1922. if ( ! $prefix ) { 
  1923. $prefix = $this->prefix; 
  1924. if ( ! empty( $options ) ) { 
  1925. foreach ( $options as $k => $v ) { 
  1926. if ( ! isset( $v['name'] ) ) { 
  1927. $v['name'] = $this->ucwords( strtr( $k, '_', ' ' ) ); 
  1928. if ( ! isset( $v['type'] ) ) { 
  1929. $v['type'] = 'checkbox'; 
  1930. if ( ! isset( $v['default'] ) ) { 
  1931. $v['default'] = null; 
  1932. if ( ! isset( $v['initial_options'] ) ) { 
  1933. $v['initial_options'] = $v['default']; 
  1934. if ( $v['type'] == 'custom' && ( ! isset( $v['nowrap'] ) ) ) { 
  1935. $v['nowrap'] = true; 
  1936. } elseif ( ! isset( $v['nowrap'] ) ) { 
  1937. $v['nowrap'] = null; 
  1938. if ( isset( $v['condshow'] ) ) { 
  1939. if ( ! is_array( $this->script_data ) ) { 
  1940. $this->script_data = array(); 
  1941. if ( ! isset( $this->script_data['condshow'] ) ) { 
  1942. $this->script_data['condshow'] = array(); 
  1943. $this->script_data['condshow'][ $prefix . $k ] = $v['condshow']; 
  1944. if ( $v['type'] == 'submit' ) { 
  1945. if ( ! isset( $v['save'] ) ) { 
  1946. $v['save'] = false; 
  1947. if ( ! isset( $v['label'] ) ) { 
  1948. $v['label'] = 'none'; 
  1949. if ( ! isset( $v['prefix'] ) ) { 
  1950. $v['prefix'] = false; 
  1951. } else { 
  1952. if ( ! isset( $v['label'] ) ) { 
  1953. $v['label'] = null; 
  1954. if ( $v['type'] == 'hidden' ) { 
  1955. if ( ! isset( $v['label'] ) ) { 
  1956. $v['label'] = 'none'; 
  1957. if ( ! isset( $v['prefix'] ) ) { 
  1958. $v['prefix'] = false; 
  1959. if ( ( $v['type'] == 'text' ) && ( ! isset( $v['size'] ) ) ) { 
  1960. $v['size'] = 57; 
  1961. if ( $v['type'] == 'textarea' ) { 
  1962. if ( ! isset( $v['cols'] ) ) { 
  1963. $v['cols'] = 57; 
  1964. if ( ! isset( $v['rows'] ) ) { 
  1965. $v['rows'] = 2; 
  1966. if ( ! isset( $v['save'] ) ) { 
  1967. $v['save'] = true; 
  1968. if ( ! isset( $v['prefix'] ) ) { 
  1969. $v['prefix'] = true; 
  1970. if ( $v['prefix'] ) { 
  1971. $opts[ $prefix . $k ] = $v; 
  1972. } else { 
  1973. $opts[ $k ] = $v; 
  1974.  
  1975. return $opts; 
  1976.  
  1977. /** Generates just the default option names and values */ 
  1978. function default_options( $location = null, $defaults = null ) { 
  1979. $options = $this->setting_options( $location, $defaults ); 
  1980. $opts = array(); 
  1981. foreach ( $options as $k => $v ) { 
  1982. if ( $v['save'] ) { 
  1983. $opts[ $k ] = $v['default']; 
  1984.  
  1985. return $opts; 
  1986.  
  1987. /** Gets the current options stored for a given location. */ 
  1988. function get_current_options( $opts = array(), $location = null, $defaults = null, $post = null ) { 
  1989. $prefix = $this->get_prefix( $location ); 
  1990. $get_opts = ''; 
  1991. if ( empty( $location ) ) { 
  1992. $type = 'settings'; 
  1993. } else { 
  1994. $type = $this->locations[ $location ]['type']; 
  1995. if ( $type === 'settings' ) { 
  1996. $get_opts = $this->get_class_option(); 
  1997. } elseif ( $type == 'metabox' ) { 
  1998. if ( $post == null ) { 
  1999. global $post; 
  2000.  
  2001. if ( ( isset( $_GET['taxonomy'] ) && isset( $_GET['tag_ID'] ) ) || is_category() || is_tag() || is_tax() ) { 
  2002.  
  2003. if ( AIOSEOPPRO ) { 
  2004. $get_opts = AIO_ProGeneral::getprotax( $get_opts ); 
  2005.  
  2006. } elseif ( isset( $post ) ) { 
  2007. $get_opts = get_post_meta( $post->ID, '_' . $prefix . $location, true ); 
  2008. $defs = $this->default_options( $location, $defaults ); 
  2009. if ( $get_opts == '' ) { 
  2010. $get_opts = $defs; 
  2011. } else { 
  2012. $get_opts = wp_parse_args( $get_opts, $defs ); 
  2013. $opts = wp_parse_args( $opts, $get_opts ); 
  2014.  
  2015. return $opts; 
  2016.  
  2017. /** Updates the options array in the module; loads saved settings with get_option() or uses defaults */ 
  2018. function update_options( $opts = array(), $location = null, $defaults = null ) { 
  2019. if ( $location === null ) { 
  2020. $type = 'settings'; 
  2021. } else { 
  2022. $type = $this->locations[ $location ][ $type ]; 
  2023. if ( $type === 'settings' ) { 
  2024. $get_opts = $this->get_class_option(); 
  2025. if ( $get_opts === false ) { 
  2026. $get_opts = $this->default_options( $location, $defaults ); 
  2027. } else { 
  2028. $this->setting_options( $location, $defaults ); 
  2029. } // hack -- make sure this runs anyhow, for now -- pdb 
  2030. $this->options = wp_parse_args( $opts, $get_opts );