/lib/admin.php

  1. <?php 
  2. /** 
  3. * License: GPLv3 
  4. * License URI: https://www.gnu.org/licenses/gpl.txt 
  5. * Copyright 2012-2017 Jean-Sebastien Morisset (https://surniaulula.com/) 
  6. */ 
  7.  
  8. if ( ! defined( 'ABSPATH' ) ) { 
  9. die( 'These aren\'t the droids you\'re looking for...' ); 
  10.  
  11. if ( ! class_exists( 'NgfbAdmin' ) ) { 
  12.  
  13. class NgfbAdmin { 
  14.  
  15. protected $p; 
  16. protected $menu_id; 
  17. protected $menu_name; 
  18. protected $menu_lib; 
  19. protected $menu_ext; // lowercase acronyn for plugin or extension 
  20. protected $pagehook; 
  21. protected $pageref_url; 
  22. protected $pageref_title; 
  23.  
  24. public static $pkg = array(); 
  25. public static $readme = array(); // array for the readme of each extension 
  26.  
  27. public $form = null; 
  28. public $lang = array(); 
  29. public $submenu = array(); 
  30.  
  31. public function __construct( &$plugin ) { 
  32. $this->p =& $plugin; 
  33.  
  34. if ( $this->p->debug->enabled ) { 
  35. $this->p->debug->mark(); 
  36.  
  37. $lca = $this->p->cf['lca']; 
  38.  
  39. /** 
  40. * The NgfbScript add_plugin_install_script() method includes jQuery in the thickbox iframe  
  41. * to add the iframe_parent arguments when the Install or Update button is clicked. 
  42. * 
  43. * These class properties are used by both the NgfbAdmin plugin_complete_actions() and  
  44. * plugin_complete_redirect() methods to direct the user back to the thickbox iframe parent 
  45. * (aka the plugin licenses settings page) after plugin installation / activation / update. 
  46. */ 
  47. foreach ( array( 
  48. 'pageref_url' => 'esc_url',  
  49. 'pageref_title' => 'esc_html',  
  50. ) as $pageref => $esc_func ) { 
  51. if ( ! empty( $_GET[$lca.'_'.$pageref] ) ) { 
  52. $this->$pageref = call_user_func( $esc_func,  
  53. urldecode( $_GET[$lca.'_'.$pageref] ) ); 
  54.  
  55. if ( SucomUtil::get_const( 'DOING_AJAX' ) ) { 
  56. // nothing to do 
  57. } else { 
  58. // admin_menu is run before admin_init 
  59. add_action( 'admin_menu', array( &$this, 'load_menu_objects' ), -1000 ); 
  60. add_action( 'admin_menu', array( &$this, 'add_admin_menus' ), NGFB_ADD_MENU_PRIORITY ); 
  61. add_action( 'admin_menu', array( &$this, 'add_admin_submenus' ), NGFB_ADD_SUBMENU_PRIORITY ); 
  62. add_action( 'admin_init', array( &$this, 'register_setting' ) ); 
  63.  
  64. // hook in_admin_header to allow for setting changes, plugin activation / loading, etc. 
  65. add_action( 'in_admin_header', array( &$this, 'conflict_warnings' ), 10 ); 
  66. add_action( 'in_admin_header', array( &$this, 'required_notices' ), 20 ); 
  67.  
  68. add_action( 'after_switch_theme', array( &$this, 'reset_check_head_count' ), 10 ); 
  69. add_action( 'upgrader_process_complete', array( &$this, 'reset_check_head_count' ), 10 ); 
  70.  
  71. add_action( 'after_switch_theme', array( &$this, 'check_tmpl_head_attributes' ), 20 ); 
  72. add_action( 'upgrader_process_complete', array( &$this, 'check_tmpl_head_attributes' ), 20 ); 
  73.  
  74. add_filter( 'plugin_action_links', array( &$this, 'add_plugin_action_links' ), 10, 2 ); 
  75. add_filter( 'wp_redirect', array( &$this, 'profile_updated_redirect' ), -100, 2 ); 
  76.  
  77. if ( is_multisite() ) { 
  78. add_action( 'network_admin_menu', array( &$this, 'load_network_menu_objects' ), -1000 ); 
  79. add_action( 'network_admin_menu', array( &$this, 'add_network_admin_menus' ), NGFB_ADD_MENU_PRIORITY ); 
  80. add_action( 'network_admin_edit_'.NGFB_SITE_OPTIONS_NAME, array( &$this, 'save_site_options' ) ); 
  81. add_filter( 'network_admin_plugin_action_links', array( &$this, 'add_plugin_action_links' ), 10, 2 ); 
  82.  
  83. /** 
  84. * Provide plugin data from the readme for extensions not hosted on wordpress.org. 
  85. * Skip if the update manager extension is active, since it provides more complete  
  86. * plugin data than what's available from the readme. 
  87. * 
  88. * Note: Update manager versions before 1.6.0 hooked the 'plugins_api' filter,  
  89. * which is fired before 'plugins_api_result'. external_plugin_data() returns 
  90. * the plugin object as-is if the slug is defined properly, so it should work 
  91. * fine with older versions (we require 1.6.0 anyway, just in case). 
  92. */ 
  93. if ( empty( $this->p->avail['p_ext']['um'] ) ) { // since um v1.6.0 
  94. add_filter( 'plugins_api_result', array( &$this, 'external_plugin_data' ), 1000, 3 ); // since wp v2.7 
  95.  
  96. add_filter( 'http_request_args', array( &$this, 'add_expect_header' ), 1000, 2 ); 
  97. add_filter( 'http_request_host_is_external', array( &$this, 'allow_install_hosts' ), 1000, 3 ); 
  98.  
  99. add_filter( 'install_plugin_complete_actions', array( &$this, 'plugin_complete_actions' ), 1000, 1 ); 
  100. add_filter( 'update_plugin_complete_actions', array( &$this, 'plugin_complete_actions' ), 1000, 1 ); 
  101.  
  102. add_filter( 'wp_redirect', array( &$this, 'plugin_complete_redirect' ), 1000, 1 ); 
  103.  
  104. public function load_network_menu_objects() { 
  105. if ( $this->p->debug->enabled ) { 
  106. $this->p->debug->mark(); 
  107. // some network menu pages extend the site menu pages 
  108. $this->load_menu_objects( array( 'submenu', 'sitesubmenu' ) ); 
  109.  
  110. public function load_menu_objects( $menu_libs = array() ) { 
  111. if ( $this->p->debug->enabled ) { 
  112. $this->p->debug->mark(); 
  113.  
  114. $lca = $this->p->cf['lca']; 
  115.  
  116. if ( empty( $menu_libs ) ) { 
  117. // 'setting' must follow 'submenu' to extend submenu/advanced.php 
  118. $menu_libs = array( 'submenu', 'setting', 'profile' ); 
  119.  
  120. foreach ( $this->p->cf['plugin'] as $ext => $info ) { 
  121. self::$pkg[$ext]['pdir'] = $this->p->check->aop( $ext, false, $this->p->avail['*']['p_dir'] ); 
  122. self::$pkg[$ext]['aop'] = ! empty( $this->p->options['plugin_'.$ext.'_tid'] ) && 
  123. $this->p->check->aop( $lca, true, $this->p->avail['*']['p_dir'] ) && 
  124. $this->p->check->aop( $ext, true, NGFB_UNDEF_INT ) === NGFB_UNDEF_INT ? 
  125. true : false; 
  126. self::$pkg[$ext]['type'] = self::$pkg[$ext]['aop'] ? 
  127. _x( 'Pro', 'package type', 'nextgen-facebook' ) : 
  128. _x( 'Free', 'package type', 'nextgen-facebook' ); 
  129. self::$pkg[$ext]['short'] = $info['short'].' '.self::$pkg[$ext]['type']; 
  130. self::$pkg[$ext]['name'] = $info['name'].' '.self::$pkg[$ext]['type']; 
  131.  
  132. foreach ( $menu_libs as $menu_lib ) { 
  133. foreach ( $this->p->cf['plugin'] as $ext => $info ) { 
  134. if ( ! isset( $info['lib'][$menu_lib] ) ) // not all extensions have submenus 
  135. continue; 
  136. foreach ( $info['lib'][$menu_lib] as $menu_id => $menu_name ) { 
  137. $classname = apply_filters( $ext.'_load_lib', false, $menu_lib.'/'.$menu_id ); 
  138. if ( is_string( $classname ) && class_exists( $classname ) ) { 
  139. if ( ! empty( $info['text_domain'] ) ) 
  140. $menu_name = _x( $menu_name, 'lib file description', $info['text_domain'] ); 
  141. $this->submenu[$menu_id] = new $classname( $this->p,  
  142. $menu_id, $menu_name, $menu_lib, $ext ); 
  143.  
  144. public function add_network_admin_menus() { 
  145. if ( $this->p->debug->enabled ) { 
  146. $this->p->debug->mark(); 
  147. $this->add_admin_menus( 'sitesubmenu' ); 
  148.  
  149. // add a new main menu, and its sub-menu items 
  150. public function add_admin_menus( $menu_lib = '' ) { 
  151. if ( $this->p->debug->enabled ) { 
  152. $this->p->debug->mark(); 
  153.  
  154. $lca = $this->p->cf['lca']; 
  155.  
  156. if ( empty( $menu_lib ) ) { 
  157. $menu_lib = 'submenu'; 
  158.  
  159. $libs = $this->p->cf['*']['lib'][$menu_lib]; 
  160. $this->menu_id = key( $libs ); 
  161. $this->menu_name = $libs[$this->menu_id]; 
  162. $this->menu_lib = $menu_lib; 
  163. $this->menu_ext = $lca; // lowercase acronyn for plugin or extension 
  164.  
  165. if ( isset( $this->submenu[$this->menu_id] ) ) { 
  166. $menu_slug = $lca.'-'.$this->menu_id; 
  167. $this->submenu[$this->menu_id]->add_menu_page( $menu_slug ); 
  168.  
  169. $sorted_menu = array(); 
  170. $unsorted_menu = array(); 
  171. foreach ( $this->p->cf['plugin'] as $ext => $info ) { 
  172. if ( ! isset( $info['lib'][$menu_lib] ) ) // not all extensions have submenus 
  173. continue; 
  174. foreach ( $info['lib'][$menu_lib] as $menu_id => $menu_name ) { 
  175. $parent_slug = $this->p->cf['lca'].'-'.$this->menu_id; 
  176. if ( $lca === $ext ) 
  177. $unsorted_menu[] = array( $parent_slug, $menu_id, $menu_name, $menu_lib, $ext ); 
  178. else { 
  179. $name_text = wp_strip_all_tags( $menu_name, true ); // just in case 
  180. $sorted_key = $name_text.'-'.$menu_id; 
  181. $sorted_menu[$sorted_key] = array( $parent_slug, $menu_id, $menu_name, $menu_lib, $ext ); 
  182. ksort( $sorted_menu ); 
  183.  
  184. foreach ( array_merge( $unsorted_menu, $sorted_menu ) as $key => $arg ) { 
  185. if ( isset( $this->submenu[$arg[1]] ) ) 
  186. $this->submenu[$arg[1]]->add_submenu_page( $arg[0] ); 
  187. else $this->add_submenu_page( $arg[0], $arg[1], $arg[2], $arg[3], $arg[4] ); 
  188.  
  189. // add sub-menu items to existing menus (profile and setting) 
  190. public function add_admin_submenus() { 
  191. foreach ( array( 'profile', 'setting' ) as $menu_lib ) { 
  192.  
  193. // match wordpress behavior (users page for admins, profile page for everyone else) 
  194. if ( $menu_lib === 'profile' && current_user_can( 'list_users' ) ) { 
  195. $parent_slug = $this->p->cf['wp']['admin']['users']['page']; 
  196. } else { 
  197. $parent_slug = $this->p->cf['wp']['admin'][$menu_lib]['page']; 
  198.  
  199. $sorted_menu = array(); 
  200. foreach ( $this->p->cf['plugin'] as $ext => $info ) { 
  201. if ( ! isset( $info['lib'][$menu_lib] ) ) // not all extensions have submenus 
  202. continue; 
  203. foreach ( $info['lib'][$menu_lib] as $menu_id => $menu_name ) { 
  204. $name_text = wp_strip_all_tags( $menu_name, true ); // just in case 
  205. $sorted_menu[$name_text.'-'.$menu_id] = array( $parent_slug,  
  206. $menu_id, $menu_name, $menu_lib, $ext ); // add_submenu_page() args 
  207. ksort( $sorted_menu ); 
  208.  
  209. foreach ( $sorted_menu as $key => $arg ) { 
  210. if ( isset( $this->submenu[$arg[1]] ) ) 
  211. $this->submenu[$arg[1]]->add_submenu_page( $arg[0] ); 
  212. else $this->add_submenu_page( $arg[0], $arg[1], $arg[2], $arg[3], $arg[4] ); 
  213.  
  214. /** 
  215. * Called by the show_setting_page() method, and extended by the  
  216. * sitesubmenu classes to load the site options instead. 
  217. */ 
  218. protected function set_form_object( $menu_ext ) { // $menu_ext required for text_domain 
  219. $def_opts = $this->p->opt->get_defaults(); 
  220. $this->form = new SucomForm( $this->p, NGFB_OPTIONS_NAME,  
  221. $this->p->options, $def_opts, $menu_ext ); 
  222.  
  223. protected function &get_form_object( $menu_ext ) { // $menu_ext required for text_domain 
  224. if ( ! isset( $this->form ) || 
  225. $this->form->get_menu_ext() !== $menu_ext ) { // just in case 
  226. $this->set_form_object( $menu_ext ); 
  227. return $this->form; 
  228.  
  229. public function register_setting() { 
  230. register_setting( $this->p->cf['lca'].'_setting', NGFB_OPTIONS_NAME,  
  231. array( &$this, 'registered_setting_sanitation' ) ); 
  232.  
  233. protected function add_menu_page( $menu_slug ) { 
  234. global $wp_version; 
  235. $lca = $this->p->cf['lca']; 
  236.  
  237. // add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $position ); 
  238. $this->pagehook = add_menu_page( 
  239. self::$pkg[$lca]['short'].' — '.$this->menu_name,  
  240. $this->p->cf['menu']['label'].' '.self::$pkg[$lca]['type'],  
  241. ( isset( $this->p->cf['wp']['admin'][$this->menu_lib]['cap'] ) ? 
  242. $this->p->cf['wp']['admin'][$this->menu_lib]['cap'] : 
  243. 'manage_options' ), // fallback to manage_options capability 
  244. $menu_slug,  
  245. array( &$this, 'show_setting_page' ),  
  246. ( version_compare( $wp_version, 3.8, '<' ) ? null : 'dashicons-share' ),  
  247. NGFB_MENU_ORDER 
  248. ); 
  249.  
  250. add_action( 'load-'.$this->pagehook, array( &$this, 'load_setting_page' ) ); 
  251.  
  252. protected function add_submenu_page( $parent_slug, $menu_id = '', $menu_name = '', $menu_lib = '', $menu_ext = '' ) { 
  253.  
  254. if ( empty( $menu_id ) ) { 
  255. $menu_id = $this->menu_id; 
  256. if ( empty( $menu_name ) ) { 
  257. $menu_name = $this->menu_name; 
  258. if ( empty( $menu_lib ) ) { 
  259. $menu_lib = $this->menu_lib; 
  260. if ( empty( $menu_ext ) ) { 
  261. $menu_ext = $this->menu_ext; // lowercase acronyn for plugin or extension 
  262. if ( empty( $menu_ext ) ) { 
  263. $menu_ext = $this->p->cf['lca']; 
  264.  
  265. global $wp_version; 
  266. if ( $menu_ext === $this->p->cf['lca'] || // plugin menu and sub-menu items 
  267. version_compare( $wp_version, 3.8, '<' ) ) { // wp v3.8 required for dashicons 
  268. $menu_title = $menu_name; 
  269. } else { 
  270. $menu_title = '<div class="extension-plugin'. // add plugin icon for extensions 
  271. ' dashicons-before dashicons-admin-plugins"></div>'. 
  272. '<div class="extension-plugin">'.$menu_name.'</div>'; 
  273.  
  274. if ( strpos( $menu_title, '<color>' ) !== false ) 
  275. $menu_title = preg_replace( array( '/<color>/', '/<\/color>/' ),  
  276. array( '<span style="color:#'.$this->p->cf['menu']['color'].';">', '</span>' ), $menu_title ); 
  277.  
  278. $page_title = self::$pkg[$menu_ext]['short'].' — '.$menu_title; 
  279. $capability = isset( $this->p->cf['wp']['admin'][$menu_lib]['cap'] ) ? 
  280. $this->p->cf['wp']['admin'][$menu_lib]['cap'] : 'manage_options'; 
  281. $menu_slug = $this->p->cf['lca'].'-'.$menu_id; 
  282. $function = array( &$this, 'show_setting_page' ); 
  283.  
  284. $this->pagehook = add_submenu_page( $parent_slug, $page_title, $menu_title,  
  285. $capability, $menu_slug, $function ); 
  286.  
  287. if ( $function ) { 
  288. add_action( 'load-'.$this->pagehook, array( &$this, 'load_setting_page' ) ); 
  289.  
  290. // add links on the main plugins page 
  291. public function add_plugin_action_links( $links, $plugin_base, $utm_source = 'plugin-action-links', &$tabindex = false ) { 
  292.  
  293. if ( ! isset( $this->p->cf['*']['base'][$plugin_base] ) ) { 
  294. return $links; 
  295.  
  296. $ext = $this->p->cf['*']['base'][$plugin_base]; 
  297. $info = $this->p->cf['plugin'][$ext]; 
  298. $tabindex = is_integer( $tabindex ) ? $tabindex : false; // just in case 
  299.  
  300. foreach ( $links as $num => $val ) { 
  301. if ( strpos( $val, '>Edit<' ) !== false ) { 
  302. unset ( $links[$num] ); 
  303.  
  304. if ( ! empty( $info['url']['faqs'] ) ) { 
  305. $links[] = '<a href="'.$info['url']['faqs'].'"'. 
  306. ( $tabindex !== false ? ' tabindex="'.++$tabindex.'"' : '' ).'>'. 
  307. _x( 'FAQ', 'plugin action link', 'nextgen-facebook' ).'</a>'; 
  308.  
  309. if ( ! empty( $info['url']['notes'] ) ) { 
  310. $links[] = '<a href="'.$info['url']['notes'].'"'. 
  311. ( $tabindex !== false ? ' tabindex="'.++$tabindex.'"' : '' ).'>'. 
  312. _x( 'Notes', 'plugin action link', 'nextgen-facebook' ).'</a>'; 
  313.  
  314. if ( ! empty( $info['url']['support'] ) && self::$pkg[$ext]['aop'] ) { 
  315. $links[] = '<a href="'.$info['url']['support'].'"'. 
  316. ( $tabindex !== false ? ' tabindex="'.++$tabindex.'"' : '' ).'>'. 
  317. _x( 'Support', 'plugin action link', 'nextgen-facebook' ).'</a>'; 
  318. } elseif ( ! empty( $info['url']['forum'] ) ) { 
  319. $links[] = '<a href="'.$info['url']['forum'].'"'. 
  320. ( $tabindex !== false ? ' tabindex="'.++$tabindex.'"' : '' ).'>'. 
  321. _x( 'Forum', 'plugin action link', 'nextgen-facebook' ).'</a>'; 
  322.  
  323. if ( ! empty( $info['url']['purchase'] ) ) { 
  324. if ( ! empty( $utm_source ) ) { 
  325. $purchase_url = add_query_arg( 'utm_source', $utm_source, $info['url']['purchase'] ); 
  326. $links[] = $this->p->msgs->get( 'pro-purchase-text',  
  327. array( 'ext' => $ext, 'url' => $purchase_url,  
  328. 'tabindex' => ( $tabindex !== false ? ++$tabindex : false ) ) ); 
  329.  
  330. return $links; 
  331.  
  332. // define and disable the "Expect: 100-continue" header 
  333. // use checks to make sure other filters aren't giving us a string or boolean 
  334. public function add_expect_header( $req, $url ) { 
  335. if ( ! is_array( $req ) ) { 
  336. $req = array(); 
  337. if ( ! isset( $req['headers'] ) || ! is_array( $req['headers'] ) ) { 
  338. $req['headers'] = array(); 
  339. $req['headers']['Expect'] = ''; 
  340. return $req; 
  341.  
  342. public function allow_install_hosts( $is_allowed, $ip, $url ) { 
  343. if ( ! $is_allowed ) { // don't bother if already allowed 
  344. if ( isset( $this->p->cf['install_hosts'] ) ) { 
  345. foreach ( $this->p->cf['install_hosts'] as $host ) { 
  346. if ( strpos( $url, $host ) === 0 ) { 
  347. return true; 
  348. return $is_allowed; 
  349.  
  350. /** 
  351. * Provide plugin data from the readme for extensions not hosted on wordpress.org. 
  352. */ 
  353. public function external_plugin_data( $res, $action = null, $args = null ) { 
  354.  
  355. // this filter only provides plugin data 
  356. if ( $action !== 'plugin_information' ) { 
  357. return $res; 
  358. // make sure we have a slug in the request 
  359. } elseif ( empty( $args->slug ) ) { 
  360. return $res; 
  361. // make sure the plugin slug is one of ours 
  362. } elseif ( empty( $this->p->cf['*']['slug'][$args->slug] ) ) { 
  363. return $res; 
  364. // if the object from wordpress looks complete, return it as-is 
  365. } elseif ( isset( $res->slug ) && $res->slug === $args->slug ) { 
  366. return $res; 
  367.  
  368. // get the extension acronym for the config 
  369. $ext = $this->p->cf['*']['slug'][$args->slug]; 
  370.  
  371. // make sure we have a config for that slug 
  372. if ( empty( $this->p->cf['plugin'][$ext] ) ) { 
  373. return $res; 
  374.  
  375. // get plugin data from the plugin readme 
  376. $plugin_data = $this->get_plugin_data( $ext ); 
  377.  
  378. // make sure we have something to return 
  379. if ( empty( $plugin_data ) ) { 
  380. return $res; 
  381.  
  382. // let wordpress known that this is not a wordpress.org plugin 
  383. $plugin_data->external = true; 
  384.  
  385. return $plugin_data; 
  386.  
  387. /** 
  388. * Get the plugin readme and cache on disk. Convert the readme array to a plugin data object. 
  389. */ 
  390. public function get_plugin_data( $ext, $use_cache = true ) { 
  391.  
  392. $data = new StdClass; 
  393. $info = $this->p->cf['plugin'][$ext]; 
  394. $readme = $this->get_readme_info( $ext, $use_cache ); 
  395.  
  396. // make sure we got something back 
  397. if ( empty( $readme ) ) { 
  398. return array(); 
  399.  
  400. foreach ( array( 
  401. // readme array => plugin object 
  402. 'plugin_name' => 'name',  
  403. 'plugin_slug' => 'slug',  
  404. 'base' => 'plugin',  
  405. 'stable_tag' => 'version',  
  406. 'tested_up_to' => 'tested',  
  407. 'requires_at_least' => 'requires',  
  408. 'home' => 'homepage',  
  409. 'latest' => 'download_link',  
  410. 'author' => 'author',  
  411. 'upgrade_notice' => 'upgrade_notice',  
  412. 'downloaded' => 'downloaded',  
  413. 'last_updated' => 'last_updated',  
  414. 'sections' => 'sections',  
  415. 'remaining_content' => 'other_notes', // added to sections 
  416. 'banners' => 'banners',  
  417. ) as $key_name => $prop_name ) { 
  418. switch ( $key_name ) { 
  419. case 'base': // from plugin config 
  420. if ( ! empty( $info[$key_name] ) ) { 
  421. $data->$prop_name = $info[$key_name]; 
  422. break; 
  423. case 'home': // from plugin config 
  424. if ( ! empty( $info['url']['purchase'] ) ) { // check for purchase url first 
  425. $data->$prop_name = $info['url']['purchase']; 
  426. break; 
  427. // no break - override with home url (if one is defined) 
  428. case 'latest': // from plugin config 
  429. if ( ! empty( $info['url'][$key_name] ) ) { 
  430. $data->$prop_name = $info['url'][$key_name]; 
  431. break; 
  432. case 'banners': // from plugin config 
  433. if ( ! empty( $info['img'][$key_name] ) ) { 
  434. $data->$prop_name = $info['img'][$key_name]; // array with low/high images 
  435. break; 
  436. case 'remaining_content': 
  437. if ( ! empty( $readme[$key_name] ) ) { 
  438. $data->sections[$prop_name] = $readme[$key_name]; 
  439. break; 
  440. default: 
  441. if ( ! empty( $readme[$key_name] ) ) { 
  442. $data->$prop_name = $readme[$key_name]; 
  443. break; 
  444. return $data; 
  445.  
  446. /** 
  447. * This method receives only a partial options array, so re-create a full one. 
  448. * WordPress handles the actual saving of the options to the database table. 
  449. */ 
  450. public function registered_setting_sanitation( $opts ) { 
  451.  
  452. $lca = $this->p->cf['lca']; 
  453. $network = false; 
  454.  
  455. if ( ! is_array( $opts ) ) { 
  456. add_settings_error( NGFB_OPTIONS_NAME, 'notarray', '<b>'.strtoupper( $lca ).' Error</b> : '. 
  457. __( 'Submitted options are not an array.', 'nextgen-facebook' ), 'error' ); 
  458. return $opts; 
  459.  
  460. // get default values, including css from default stylesheets 
  461. $def_opts = $this->p->opt->get_defaults(); 
  462. $opts = SucomUtil::restore_checkboxes( $opts ); 
  463. $opts = array_merge( $this->p->options, $opts ); 
  464. $this->p->notice->trunc(); // clear all messages before sanitation checks 
  465. $opts = $this->p->opt->sanitize( $opts, $def_opts, $network ); 
  466. $opts = apply_filters( $lca.'_save_options', $opts, NGFB_OPTIONS_NAME, $network ); 
  467.  
  468. if ( empty( $this->p->options['plugin_clear_on_save'] ) ) { 
  469.  
  470. // admin url will redirect to the essential settings since we're not on a settings page 
  471. $clear_cache_link = $this->p->util->get_admin_url( wp_nonce_url( '?'.$lca.'-action=clear_all_cache',  
  472. NgfbAdmin::get_nonce(), NGFB_NONCE ), _x( 'Clear All Caches', 'submit button', 'nextgen-facebook' ) ); 
  473.  
  474. $this->p->notice->upd( '<strong>'.__( 'Plugin settings have been saved.', 'nextgen-facebook' ).'</strong> <em>'. 
  475. __( 'Please note that webpage content may take several days to reflect changes.', 'nextgen-facebook' ).' '. 
  476. sprintf( __( '%s now to force a refresh.', 'nextgen-facebook' ), $clear_cache_link ).'</em>' ); 
  477. } else { 
  478. $this->p->util->clear_all_cache( true, __FUNCTION__.'_clear_all_cache', true ); // can be dismissed 
  479.  
  480. $this->p->notice->upd( '<strong>'.__( 'Plugin settings have been saved.', 'nextgen-facebook' ).'</strong> <em>'. 
  481. sprintf( __( 'All caches have also been cleared (the %s option is enabled).', 'nextgen-facebook' ),  
  482. $this->p->util->get_admin_url( 'advanced#sucom-tabset_plugin-tab_cache',  
  483. _x( 'Clear All Cache on Save Settings', 'option label', 'nextgen-facebook' ) ) ).'</em>' ); 
  484.  
  485. if ( empty( $opts['plugin_filter_content'] ) ) { 
  486. $this->p->notice->warn( $this->p->msgs->get( 'notice-content-filters-disabled' ),  
  487. true, 'notice-content-filters-disabled', true ); // can be dismissed 
  488.  
  489. $this->check_tmpl_head_attributes(); 
  490.  
  491. return $opts; 
  492.  
  493. public function save_site_options() { 
  494. $network = true; 
  495.  
  496. if ( ! $page = SucomUtil::get_request_value( 'page', 'POST' ) ) { // uses sanitize_text_field 
  497. $page = key( $this->p->cf['*']['lib']['sitesubmenu'] ); 
  498.  
  499. if ( empty( $_POST[ NGFB_NONCE ] ) ) { // NGFB_NONCE is an md5() string 
  500. if ( $this->p->debug->enabled ) { 
  501. $this->p->debug->log( 'nonce token validation post field missing' ); 
  502. wp_redirect( $this->p->util->get_admin_url( $page ) ); 
  503. exit; 
  504. } elseif ( ! wp_verify_nonce( $_POST[ NGFB_NONCE ], NgfbAdmin::get_nonce() ) ) { 
  505. $this->p->notice->err( __( 'Nonce token validation failed for network options (update ignored).',  
  506. 'nextgen-facebook' ) ); 
  507. wp_redirect( $this->p->util->get_admin_url( $page ) ); 
  508. exit; 
  509. } elseif ( ! current_user_can( 'manage_network_options' ) ) { 
  510. $this->p->notice->err( __( 'Insufficient privileges to modify network options.',  
  511. 'nextgen-facebook' ) ); 
  512. wp_redirect( $this->p->util->get_admin_url( $page ) ); 
  513. exit; 
  514.  
  515. $def_opts = $this->p->opt->get_site_defaults(); 
  516. $opts = empty( $_POST[NGFB_SITE_OPTIONS_NAME] ) ? $def_opts : 
  517. SucomUtil::restore_checkboxes( $_POST[NGFB_SITE_OPTIONS_NAME] ); 
  518. $opts = array_merge( $this->p->site_options, $opts ); 
  519. $this->p->notice->trunc(); // clear all messages before sanitation checks 
  520. $opts = $this->p->opt->sanitize( $opts, $def_opts, $network ); 
  521. $opts = apply_filters( $this->p->cf['lca'].'_save_site_options', $opts, $def_opts, $network ); 
  522. update_site_option( NGFB_SITE_OPTIONS_NAME, $opts ); 
  523. $this->p->notice->upd( '<strong>'.__( 'Plugin settings have been saved.', // green status w check mark 
  524. 'nextgen-facebook' ).'</strong>' ); 
  525. wp_redirect( $this->p->util->get_admin_url( $page ).'&settings-updated=true' ); 
  526. exit; // stop here 
  527.  
  528. public function load_setting_page() { 
  529. $lca = $this->p->cf['lca']; 
  530. $action_query = $lca.'-action'; 
  531. wp_enqueue_script( 'postbox' ); 
  532.  
  533. if ( ! empty( $_GET[$action_query] ) ) { 
  534. $action_name = SucomUtil::sanitize_hookname( $_GET[$action_query] ); 
  535. if ( empty( $_GET[ NGFB_NONCE ] ) ) { // NGFB_NONCE is an md5() string 
  536. if ( $this->p->debug->enabled ) { 
  537. $this->p->debug->log( 'nonce token validation query field missing' ); 
  538. } elseif ( ! wp_verify_nonce( $_GET[ NGFB_NONCE ], NgfbAdmin::get_nonce() ) ) { 
  539. $this->p->notice->err( sprintf( __( 'Nonce token validation failed for %1$s action "%2$s".',  
  540. 'nextgen-facebook' ), 'admin', $action_name ) ); 
  541. } else { 
  542. $_SERVER['REQUEST_URI'] = remove_query_arg( array( $action_query, NGFB_NONCE ) ); 
  543.  
  544. switch ( $action_name ) { 
  545.  
  546. case 'check_for_updates': 
  547.  
  548. $info = $this->p->cf['plugin']['ngfb']; 
  549. $um_info = $this->p->cf['plugin']['ngfbum']; 
  550.  
  551. if ( SucomUtil::active_plugins( $um_info['base'] ) ) { 
  552.  
  553. // refresh the readme for all extensions 
  554. foreach ( $this->p->cf['plugin'] as $ext => $info ) { 
  555. $this->get_readme_info( $ext, false ); // $use_cache = false 
  556.  
  557. $ngfbum =& NgfbUm::get_instance(); 
  558.  
  559. if ( isset( $ngfbum->update ) ) { // just in case 
  560. /** 
  561. * Check for updates for all extensions, show a notice for success or failure,  
  562. * and don't use cached update data from the options table (fetch new update json). 
  563. */ 
  564. $ngfbum->update->check_for_updates( null, true, false ); // $use_cache = false 
  565. } else { 
  566. $this->p->notice->err( sprintf( __( 'The <b>%2$s</b> extension is not initialized properly. Please make sure you are using the latest versions of %1$s and %2$s.', 'nextgen-facebook' ), $info['name'], $um_info['name'] ) ); 
  567. } else { 
  568. $this->p->notice->err( sprintf( __( 'The <b>%1$s</b> extension must be active in order to check for Pro version updates.', 'nextgen-facebook' ), $um_info['name'] ) ); 
  569. break; 
  570.  
  571. case 'clear_all_cache': 
  572. $this->p->util->clear_all_cache( true ); // $clear_ext = true 
  573. break; 
  574.  
  575. case 'clear_metabox_prefs': 
  576. $user_id = get_current_user_id(); 
  577. $user = get_userdata( $user_id ); 
  578. $user_name = $user->display_name; 
  579. NgfbUser::delete_metabox_prefs( $user_id ); 
  580. $this->p->notice->upd( sprintf( __( 'Metabox layout preferences for user ID #%d "%s" have been reset.',  
  581. 'nextgen-facebook' ), $user_id, $user_name ) ); 
  582. break; 
  583.  
  584. case 'clear_hidden_notices': 
  585. $user_id = get_current_user_id(); 
  586. $user = get_userdata( $user_id ); 
  587. //$user_name = trim( $user->first_name.' '.$user->last_name ); 
  588. $user_name = $user->display_name; 
  589. delete_user_option( $user_id, NGFB_DISMISS_NAME ); 
  590. $this->p->notice->upd( sprintf( __( 'Hidden notices for user ID #%d "%s" have been cleared.',  
  591. 'nextgen-facebook' ), $user_id, $user_name ) ); 
  592. break; 
  593.  
  594. case 'change_show_options': 
  595. if ( isset( $this->p->cf['form']['show_options'][$_GET['show-opts']] ) ) { 
  596. $this->p->notice->upd( sprintf( 'Option preference saved — viewing "%s" by default.',  
  597. $this->p->cf['form']['show_options'][$_GET['show-opts']] ) ); 
  598. NgfbUser::save_pref( array( 'show_opts' => $_GET['show-opts'] ) ); 
  599. $_SERVER['REQUEST_URI'] = remove_query_arg( array( 'show-opts' ) ); 
  600. break; 
  601.  
  602. case 'modify_tmpl_head_attributes': 
  603. $this->modify_tmpl_head_attributes(); 
  604. break; 
  605.  
  606. case 'reload_default_sizes': 
  607. $opts =& $this->p->options; // update the existing options array 
  608. $def_opts = $this->p->opt->get_defaults(); 
  609. $img_opts = SucomUtil::preg_grep_keys( '/_img_(width|height|crop|crop_x|crop_y)$/', $def_opts ); 
  610. $opts = array_merge( $this->p->options, $img_opts ); 
  611. $this->p->opt->save_options( NGFB_OPTIONS_NAME, $opts, false ); 
  612. $this->p->notice->upd( __( 'All image dimensions have been reloaded with their default value and saved.',  
  613. 'nextgen-facebook' ) ); 
  614. break; 
  615.  
  616. default: 
  617. do_action( $lca.'_load_setting_page_'.$action_name,  
  618. $this->pagehook, $this->menu_id, $this->menu_name, $this->menu_lib ); 
  619. break; 
  620.  
  621. $this->add_plugin_hooks(); 
  622. $this->add_meta_boxes(); 
  623. $this->add_side_meta_boxes(); 
  624.  
  625. protected function add_side_meta_boxes() { 
  626. $lca = $this->p->cf['lca']; 
  627. if ( ! self::$pkg[$lca]['aop'] ) { 
  628.  
  629. add_meta_box( $this->pagehook.'_purchase_pro',  
  630. _x( 'Pro Version Available', 'metabox title', 'nextgen-facebook' ),  
  631. array( &$this, 'show_metabox_purchase_pro' ), $this->pagehook, 'side_fixed' ); 
  632.  
  633. add_meta_box( $this->pagehook.'_about_free',  
  634. _x( 'About the Free Version', 'metabox title', 'nextgen-facebook' ),  
  635. array( &$this, 'show_metabox_about_free' ), $this->pagehook, 'side' ); 
  636.  
  637. add_meta_box( $this->pagehook.'_install_pro',  
  638. _x( 'Updating to Pro is Easy', 'metabox title', 'nextgen-facebook' ),  
  639. array( &$this, 'show_metabox_install_pro' ), $this->pagehook, 'side' ); 
  640.  
  641. NgfbUser::reset_metabox_prefs( $this->pagehook, array( 'purchase_pro' ), '', '', true ); 
  642.  
  643. protected function add_plugin_hooks() { 
  644. // method is extended by each submenu page 
  645.  
  646. protected function add_meta_boxes() { 
  647. // method is extended by each submenu page 
  648.  
  649. public function show_setting_page() { 
  650.  
  651. if ( ! $this->is_setting() ) { 
  652. settings_errors( NGFB_OPTIONS_NAME ); 
  653.  
  654. $lca = $this->p->cf['lca']; 
  655. $menu_ext = $this->menu_ext; // lowercase acronyn for plugin or extension 
  656.  
  657. if ( empty( $menu_ext ) ) { 
  658. $menu_ext = $this->p->cf['lca']; 
  659.  
  660. // set the form for side boxes and show_form_content() 
  661. $this->set_form_object( $menu_ext ); 
  662.  
  663. echo '<div class="wrap" id="'.$this->pagehook.'">'."\n"; 
  664. echo '<h1>'.self::$pkg[$this->menu_ext]['short'].' – '.$this->menu_name.'</h1>'."\n"; 
  665.  
  666. if ( ! self::$pkg[$lca]['aop'] ) { 
  667. echo '<div id="poststuff" class="metabox-holder has-right-sidebar">'."\n"; 
  668. echo '<div id="side-info-column" class="inner-sidebar">'."\n"; 
  669.  
  670. do_meta_boxes( $this->pagehook, 'side_fixed', null ); 
  671. do_meta_boxes( $this->pagehook, 'side', null ); 
  672.  
  673. echo '</div><!-- #side-info-column -->'."\n"; 
  674. echo '<div id="post-body" class="has-sidebar">'."\n"; 
  675. echo '<div id="post-body-content" class="has-sidebar-content">'."\n"; 
  676. } else { 
  677. echo '<div id="poststuff" class="metabox-holder no-right-sidebar">'."\n"; 
  678. echo '<div id="post-body" class="no-sidebar">'."\n"; 
  679. echo '<div id="post-body-content" class="no-sidebar-content">'."\n"; 
  680.  
  681. $this->show_form_content(); ?> 
  682.  
  683. </div><!-- #post-body-content --> 
  684. </div><!-- #post-body --> 
  685. </div><!-- #poststuff --> 
  686. </div><!-- .wrap --> 
  687. <script type="text/javascript"> 
  688. //<![CDATA[ 
  689. jQuery(document).ready( 
  690. function($) { 
  691. // close postboxes that should be closed 
  692. $('.if-js-closed').removeClass('if-js-closed').addClass('closed'); 
  693. // postboxes setup 
  694. postboxes.add_postbox_toggles('<?php echo $this->pagehook; ?>'); 
  695. ); 
  696. //]]> 
  697. </script> 
  698. <?php 
  699.  
  700. public function profile_updated_redirect( $url, $status ) { 
  701. if ( strpos( $url, 'updated=' ) !== false && strpos( $url, 'wp_http_referer=' ) ) { 
  702.  
  703. // match wordpress behavior (users page for admins, profile page for everyone else) 
  704. $menu_lib = current_user_can( 'list_users' ) ? 'users' : 'profile'; 
  705. $parent_slug = $this->p->cf['wp']['admin'][$menu_lib]['page']; 
  706. $referer_match = '/'.$parent_slug.'?page='.$this->p->cf['lca'].'-'; 
  707.  
  708. parse_str( parse_url( $url, PHP_URL_QUERY ), $parts ); 
  709.  
  710. if ( strpos( $parts['wp_http_referer'], $referer_match ) ) { 
  711. $this->p->notice->upd( __( 'Profile updated.' ) ); // green status w check mark 
  712. $url = add_query_arg( 'updated', true, $parts['wp_http_referer'] ); 
  713. return $url; 
  714.  
  715. protected function show_form_content() { 
  716.  
  717. $lca = $this->p->cf['lca']; 
  718.  
  719. if ( $this->menu_lib === 'profile' ) { 
  720.  
  721. $user_id = get_current_user_id(); 
  722. $profileuser = get_user_to_edit( $user_id ); 
  723. $current_color = get_user_option( 'admin_color', $user_id ); 
  724. if ( empty( $current_color ) ) 
  725. $current_color = 'fresh'; 
  726.  
  727. // match wordpress behavior (users page for admins, profile page for everyone else) 
  728. $admin_url = current_user_can( 'list_users' ) ? 
  729. $this->p->util->get_admin_url( $this->menu_id, null, 'users' ) : 
  730. $this->p->util->get_admin_url( $this->menu_id, null, $this->menu_lib ); 
  731.  
  732. echo '<form name="'.$lca.'" id="'.$lca.'_setting_form" action="user-edit.php" method="post">'."\n"; 
  733. echo '<input type="hidden" name="wp_http_referer" value="'.$admin_url.'" />'."\n"; 
  734. echo '<input type="hidden" name="action" value="update" />'."\n"; 
  735. echo '<input type="hidden" name="user_id" value="'.$user_id.'" />'."\n"; 
  736. echo '<input type="hidden" name="nickname" value="'.$profileuser->nickname.'" />'."\n"; 
  737. echo '<input type="hidden" name="email" value="'.$profileuser->user_email.'" />'."\n"; 
  738. echo '<input type="hidden" name="admin_color" value="'.$current_color.'" />'."\n"; 
  739. echo '<input type="hidden" name="rich_editing" value="'.$profileuser->rich_editing.'" />'."\n"; 
  740. echo '<input type="hidden" name="comment_shortcuts" value="'.$profileuser->comment_shortcuts.'" />'."\n"; 
  741. echo '<input type="hidden" name="admin_bar_front" value="'._get_admin_bar_pref( 'front', $user_id ).'" />'."\n"; 
  742.  
  743. wp_nonce_field( 'update-user_'.$user_id ); 
  744.  
  745. } elseif ( $this->menu_lib === 'setting' || $this->menu_lib === 'submenu' ) { 
  746.  
  747. echo '<form name="'.$lca.'" id="'.$lca.'_setting_form" action="options.php" method="post">'."\n"; 
  748.  
  749. settings_fields( $lca.'_setting' ); 
  750.  
  751. } elseif ( $this->menu_lib === 'sitesubmenu' ) { 
  752.  
  753. echo '<form name="'.$lca.'" id="'.$lca.'_setting_form" action="edit.php?action='. 
  754. NGFB_SITE_OPTIONS_NAME.'" method="post">'."\n"; 
  755. echo '<input type="hidden" name="page" value="'.$this->menu_id.'" />'; 
  756.  
  757. } else { 
  758. return; 
  759.  
  760. wp_nonce_field( NgfbAdmin::get_nonce(), NGFB_NONCE ); // NGFB_NONCE is an md5() string 
  761. wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); 
  762. wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false ); 
  763.  
  764. do_meta_boxes( $this->pagehook, 'normal', null ); 
  765.  
  766. do_action( $this->p->cf['lca'].'_form_content_metaboxes_'. 
  767. SucomUtil::sanitize_hookname( $this->menu_id ), $this->pagehook ); 
  768.  
  769. if ( $this->menu_lib === 'profile' ) { 
  770. echo $this->get_submit_buttons( _x( 'Save All Profile Settings',  
  771. 'submit button', 'nextgen-facebook' ) ); 
  772. } else { 
  773. echo $this->get_submit_buttons(); 
  774.  
  775. echo '</form>', "\n"; 
  776.  
  777. protected function get_submit_buttons( $submit_label = '' ) { 
  778.  
  779. $lca = $this->p->cf['lca']; 
  780.  
  781. if ( empty( $submit_label ) ) { 
  782. $submit_label = _x( 'Save All Plugin Settings', 'submit button', 'nextgen-facebook' ); 
  783.  
  784. $view_next = SucomUtil::next_key( NgfbUser::show_opts(), $this->p->cf['form']['show_options'] ); 
  785. $view_name = _x( $this->p->cf['form']['show_options'][$view_next], 'option value', 'nextgen-facebook' ); 
  786. $view_label = sprintf( _x( 'View %s by Default', 'submit button', 'nextgen-facebook' ), $view_name ); 
  787.  
  788. if ( is_multisite() ) { 
  789. $clear_label = sprintf( _x( 'Clear All Caches for Site %d',  
  790. 'submit button', 'nextgen-facebook' ), get_current_blog_id() ); 
  791. } else { 
  792. $clear_label = _x( 'Clear All Caches',  
  793. 'submit button', 'nextgen-facebook' ); 
  794.  
  795. $action_buttons = apply_filters( $lca.'_action_buttons', array( 
  796. array( 
  797. 'submit' => $submit_label,  
  798. 'change_show_options&show-opts='.$view_next => $view_label,  
  799. ),  
  800. array( 
  801. 'clear_all_cache' => $clear_label,  
  802. 'clear_metabox_prefs' => _x( 'Reset Metabox Layout', 'submit button', 'nextgen-facebook' ),  
  803. 'clear_hidden_notices' => _x( 'Reset Hidden Notices', 'submit button', 'nextgen-facebook' ),  
  804. ),  
  805. ), $this->menu_id, $this->menu_name, $this->menu_lib ); 
  806.  
  807. $submit_buttons = ''; 
  808.  
  809. foreach ( $action_buttons as $row => $row_buttons ) { 
  810. $css_class = $row ? 
  811. 'button-secondary' : 
  812. 'button-secondary button-highlight'; // highlight the first row 
  813.  
  814. foreach ( $row_buttons as $action_arg => $button_label ) { 
  815. if ( $action_arg === 'submit' ) { 
  816. $submit_buttons .= '<input type="'.$action_arg.'" class="button-primary" value="'.$button_label.'" />'; 
  817. } else { 
  818. $button_url = wp_nonce_url( $this->p->util->get_admin_url( '?'.$lca.'-action='.$action_arg ),  
  819. NgfbAdmin::get_nonce(), NGFB_NONCE ); 
  820. $submit_buttons .= $this->form->get_button( $button_label, $css_class, '', $button_url ); 
  821. $submit_buttons .= '<br/>'; 
  822.  
  823. return '<div class="submit-buttons">'.$submit_buttons.'</div>'; 
  824.  
  825. public function show_metabox_version_info() { 
  826.  
  827. $lca = $this->p->cf['lca']; 
  828.  
  829. echo '<table class="sucom-settings '.$lca.' column-metabox version-info" style="table-layout:fixed;">'; 
  830. echo '<colgroup><col style="width:70px;"/><col/></colgroup>'; // required for chrome to display fixed table layout 
  831.  
  832. foreach ( $this->p->cf['plugin'] as $ext => $info ) { 
  833.  
  834. if ( empty( $info['version'] ) ) { // only active extensions 
  835. continue; 
  836.  
  837. $installed_version = $info['version']; // static value from config 
  838. $installed_style = ''; 
  839. $stable_version = __( 'Not Available', 'nextgen-facebook' ); // default value 
  840. $latest_version = __( 'Not Available', 'nextgen-facebook' ); // default value 
  841. $latest_notice = ''; 
  842. $changelog_url = $info['url']['changelog']; 
  843. $readme_info = $this->get_readme_info( $ext, true ); // $use_cache = true 
  844.  
  845. if ( ! empty( $readme_info['stable_tag'] ) ) { 
  846.  
  847. $stable_version = $readme_info['stable_tag']; 
  848.  
  849. if ( is_array( $readme_info['upgrade_notice'] ) ) { 
  850.  
  851. // hooked by the update manager to apply the version filter 
  852. $upgrade_notice = apply_filters( $lca.'_readme_upgrade_notices',  
  853. $readme_info['upgrade_notice'], $ext ); 
  854.  
  855. reset( $upgrade_notice ); 
  856.  
  857. $latest_version = key( $upgrade_notice ); 
  858. $latest_notice = $upgrade_notice[$latest_version]; 
  859.  
  860. // hooked by the update manager to check installed version against 
  861. // the latest version, if a non-stable filter is selected for that 
  862. // plugin / extension 
  863. if ( apply_filters( $lca.'_newer_version_available',  
  864. version_compare( $installed_version, $stable_version, '<' ),  
  865. $ext, $installed_version, $stable_version, $latest_version ) ) { 
  866. $installed_style = 'style="background-color:#f00;"'; // red 
  867. // version is current but not stable (alpha characters found in version string) 
  868. } elseif ( preg_match( '/[a-z]/', $installed_version ) ) { 
  869. $installed_style = 'style="background-color:#ff0;"'; // yellow 
  870. // version is current 
  871. } else { 
  872. $installed_style = 'style="background-color:#0f0;"'; // green 
  873.  
  874. echo '<tr><td colspan="2"><h4>'.self::$pkg[$ext]['short'].'</h4></td></tr>'; 
  875.  
  876. echo '<tr><th class="version-label">'._x( 'Installed', 'option label', 'nextgen-facebook' ).':</th> 
  877. <td class="version-number" '.$installed_style.'>'.$installed_version.'</td></tr>'; 
  878.  
  879. echo '<tr><th class="version-label">'._x( 'Stable', 'option label', 'nextgen-facebook' ).':</th> 
  880. <td class="version-number">'.$stable_version.'</td></tr>'; 
  881.  
  882. echo '<tr><th class="version-label">'._x( 'Latest', 'option label', 'nextgen-facebook' ).':</th> 
  883. <td class="version-number">'.$latest_version.'</td></tr>'; 
  884.  
  885. echo '<tr><td colspan="2" class="latest-notice">'. 
  886. '<p><em><strong>Version '.$latest_version.'</strong> '.$latest_notice.'</em></p>'. 
  887. '<p><a href="'.$changelog_url.'" target="_blank">'. 
  888. sprintf( __( 'View %s changelog...', 'nextgen-facebook' ),  
  889. $info['short'] ).'</a></p></td></tr>'; 
  890.  
  891. if ( ! empty( $this->p->avail['p_ext']['um'] ) ) { // since um v1.6.0 
  892. echo '<tr><td colspan="2">'; 
  893. echo $this->form->get_button( _x( 'Check for Updates', 'submit button', 'nextgen-facebook' ), 'button-secondary',  
  894. 'column-check-for-updates', wp_nonce_url( $this->p->util->get_admin_url( '?'.$lca.'-action=check_for_updates' ),  
  895. NgfbAdmin::get_nonce(), NGFB_NONCE ) ); 
  896. echo '</td></tr>'; 
  897.  
  898. echo '</table>'; 
  899.  
  900. public function show_metabox_status_gpl() { 
  901.  
  902. $lca = $this->p->cf['lca']; 
  903. $ext_num = 0; 
  904.  
  905. echo '<table class="sucom-settings '.$lca.' column-metabox module-status">'; 
  906.  
  907. /** 
  908. * GPL version features 
  909. */ 
  910. foreach ( $this->p->cf['plugin'] as $ext => $info ) { 
  911.  
  912. if ( ! isset( $info['lib']['gpl'] ) ) { 
  913. continue; 
  914.  
  915. $ext_num++; 
  916.  
  917. if ( $ext === $lca ) { // features for this plugin 
  918. $features = array( 
  919. '(tool) Debug Logging Enabled' => array( 
  920. 'classname' => 'SucomDebug',  
  921. ),  
  922. '(code) Facebook / Open Graph Meta Tags' => array( 
  923. 'status' => class_exists( $lca.'opengraph' ) ? 'on' : 'rec',  
  924. ),  
  925. '(code) Google Author / Person Markup' => array( 
  926. 'status' => $this->p->options['schema_person_json'] ? 'on' : 'off',  
  927. ),  
  928. '(code) Google Publisher / Organization Markup' => array( 
  929. 'status' => $this->p->options['schema_organization_json'] ? 'on' : 'off',  
  930. ),  
  931. '(code) Google Website Markup' => array( 
  932. 'status' => $this->p->options['schema_website_json'] ? 'on' : 'rec',  
  933. ),  
  934. '(code) Schema Meta Property Containers' => array( 
  935. 'status' => apply_filters( $lca.'_add_schema_noscript_array',  
  936. $this->p->options['schema_add_noscript'] ) ? 'on' : 'off',  
  937. ),  
  938. '(code) Twitter Card Meta Tags' => array( 
  939. 'status' => class_exists( $lca.'twittercard' ) ? 'on' : 'rec',  
  940. ),  
  941. ); 
  942. } else { 
  943. $features = array(); 
  944.  
  945. self::$pkg[$ext]['purchase'] = ''; 
  946.  
  947. $features = apply_filters( $ext.'_status_gpl_features', $features, $ext, $info, self::$pkg[$ext] ); 
  948.  
  949. if ( ! empty( $features ) ) { 
  950. echo '<tr><td colspan="3"><h4'.( $ext_num > 1 ? ' style="margin-top:10px;"' : '' ).'>'. 
  951. $info['short'].'</h4></td></tr>'; 
  952. $this->show_plugin_status( $ext, $info, $features ); 
  953. echo '</table>'; 
  954.  
  955. public function show_metabox_status_pro() { 
  956.  
  957. $lca = $this->p->cf['lca']; 
  958. $ext_num = 0; 
  959.  
  960. echo '<table class="sucom-settings '.$lca.' column-metabox module-status">'; 
  961.  
  962. /** 
  963. * Pro version features 
  964. */ 
  965. foreach ( $this->p->cf['plugin'] as $ext => $info ) { 
  966.  
  967. if ( ! isset( $info['lib']['pro'] ) ) { 
  968. continue; 
  969.  
  970. $ext_num++; 
  971. $features = array(); 
  972.  
  973. self::$pkg[$ext]['purchase'] = empty( $info['url']['purchase'] ) ? 
  974. '' : add_query_arg( 'utm_source', 'status-pro-feature', $info['url']['purchase'] ); 
  975.  
  976. foreach ( $info['lib']['pro'] as $sub => $libs ) { 
  977. if ( $sub === 'admin' ) // skip status for admin menus and tabs 
  978. continue; 
  979. foreach ( $libs as $id_key => $label ) { 
  980. /** 
  981. * Example: 
  982. * 'article' => 'Item Type Article',  
  983. * 'article#news:no_load' => 'Item Type NewsArticle',  
  984. * 'article#tech:no_load' => 'Item Type TechArticle',  
  985. */ 
  986. list( $id, $stub, $action ) = SucomUtil::get_lib_stub_action( $id_key ); 
  987. $classname = SucomUtil::sanitize_classname( $ext.'pro'.$sub.$id, false ); // $underscore = false 
  988. $status_off = $this->p->avail[$sub][$id] ? 'rec' : 'off'; 
  989. $features[$label] = array( 
  990. 'td_class' => self::$pkg[$ext]['aop'] ? '' : 'blank',  
  991. 'purchase' => self::$pkg[$ext]['purchase'],  
  992. 'status' => class_exists( $classname ) ? 
  993. ( self::$pkg[$ext]['aop'] ? 
  994. 'on' : $status_off ) : $status_off,  
  995. ); 
  996.  
  997. $features = apply_filters( $ext.'_status_pro_features', $features, $ext, $info, self::$pkg[$ext] ); 
  998.  
  999. if ( ! empty( $features ) ) { 
  1000. echo '<tr><td colspan="3"><h4'.( $ext_num > 1 ? ' style="margin-top:10px;"' : '' ).'>'. 
  1001. $info['short'].'</h4></td></tr>'; 
  1002. $this->show_plugin_status( $ext, $info, $features ); 
  1003. echo '</table>'; 
  1004.  
  1005. private function show_plugin_status( &$ext = '', &$info = array(), &$features = array() ) { 
  1006.  
  1007. $status_info = array( 
  1008. 'on' => array( 
  1009. 'img' => 'green-circle.png',  
  1010. 'title' => __( 'Module is enabled', 'nextgen-facebook' ),  
  1011. ),  
  1012. 'off' => array( 
  1013. 'img' => 'gray-circle.png',  
  1014. 'title' => __( 'Module is disabled / not loaded', 'nextgen-facebook' ),  
  1015. ),  
  1016. 'rec' => array( 
  1017. 'img' => 'red-circle.png',  
  1018. 'title' => __( 'Module recommended but disabled / not available', 'nextgen-facebook' ),  
  1019. ),  
  1020. ); 
  1021.  
  1022. uksort( $features, array( __CLASS__, 'sort_plugin_features' ) ); 
  1023.  
  1024. foreach ( $features as $label => $arr ) { 
  1025. if ( isset( $arr['classname'] ) ) 
  1026. $status_key = class_exists( $arr['classname'] ) ? 'on' : 'off'; 
  1027. elseif ( isset( $arr['constant'] ) ) 
  1028. $status_key = SucomUtil::get_const( $arr['constant'] ) ? 'on' : 'off'; 
  1029. elseif ( isset( $arr['status'] ) ) 
  1030. $status_key = $arr['status']; 
  1031. else $status_key = ''; 
  1032.  
  1033. if ( ! empty( $status_key ) ) { 
  1034. $td_class = empty( $arr['td_class'] ) ? '' : ' '.$arr['td_class']; 
  1035. $icon_type = preg_match( '/^\(([a-z\-]+)\) (.*)/', $label, $match ) ? $match[1] : 'admin-generic'; 
  1036. $icon_title = __( 'Generic feature module', 'nextgen-facebook' ); 
  1037. $label_text = empty( $match[2] ) ? $label : $match[2]; 
  1038. $label_text = empty( $arr['label'] ) ? $label_text : $arr['label']; 
  1039. $purchase_url = $status_key === 'rec' && ! empty( $arr['purchase'] ) ? $arr['purchase'] : ''; 
  1040.  
  1041. switch ( $icon_type ) { 
  1042. case 'api': 
  1043. $icon_type = 'controls-repeat'; 
  1044. $icon_title = __( 'Service API module', 'nextgen-facebook' ); 
  1045. break; 
  1046. case 'code': 
  1047. $icon_type = 'editor-code'; 
  1048. $icon_title = __( 'Meta tag and markup module', 'nextgen-facebook' ); 
  1049. break; 
  1050. case 'plugin': 
  1051. $icon_type = 'admin-plugins'; 
  1052. $icon_title = __( 'Plugin integration module', 'nextgen-facebook' ); 
  1053. break; 
  1054. case 'sharing': 
  1055. $icon_type = 'screenoptions'; 
  1056. $icon_title = __( 'Sharing functionality module', 'nextgen-facebook' ); 
  1057. break; 
  1058. case 'tool': 
  1059. $icon_type = 'admin-tools'; 
  1060. $icon_title = __( 'Additional functionality module', 'nextgen-facebook' ); 
  1061. break; 
  1062.  
  1063. echo '<tr>'. 
  1064. '<td><span class="dashicons dashicons-'.$icon_type.'" title="'.$icon_title.'"></span></td>'. 
  1065. '<td class="'.trim( $td_class ).'">'.$label_text.'</td>'. 
  1066. '<td>'. 
  1067. ( $purchase_url ? '<a href="'.$purchase_url.'" target="_blank">' : '' ). 
  1068. '<img src="'.NGFB_URLPATH.'images/'. 
  1069. $status_info[$status_key]['img'].'" width="12" height="12" title="'. 
  1070. $status_info[$status_key]['title'].'"/>'. 
  1071. ( $purchase_url ? '</a>' : '' ). 
  1072. '</td>'. 
  1073. '</tr>'."\n"; 
  1074.  
  1075. private static function sort_plugin_features( $feature_a, $feature_b ) { 
  1076. return strcasecmp( self::feature_priority( $feature_a ),  
  1077. self::feature_priority( $feature_b ) ); 
  1078.  
  1079. private static function feature_priority( $feature ) { 
  1080. if ( strpos( $feature, '(tool)' ) === 0 ) 
  1081. return '(10) '.$feature; 
  1082. else return $feature; 
  1083.  
  1084. public function show_metabox_about_free() { 
  1085. $lca = $this->p->cf['lca']; 
  1086. echo '<table class="sucom-settings '.$lca.' column-metabox"><tr><td>'; 
  1087. echo '<div class="column-metabox-icon">'; 
  1088. echo $this->get_ext_img_icon( $lca ); 
  1089. echo '</div>'; 
  1090. echo '<div class="column-metabox-content">'; 
  1091. echo $this->p->msgs->get( 'column-about-free' ); 
  1092. echo '</div>'; 
  1093. echo '</td></tr></table>'; 
  1094.  
  1095. public function show_metabox_purchase_pro() { 
  1096. $lca = $this->p->cf['lca']; 
  1097. $info =& $this->p->cf['plugin'][$lca]; 
  1098. $purchase_url = empty( $info['url']['purchase'] ) ? 
  1099. '' : add_query_arg( 'utm_source', 'column-purchase-pro', $info['url']['purchase'] ); 
  1100. echo '<table class="sucom-settings '.$lca.' column-metabox"><tr><td>'; 
  1101. echo '<div class="column-metabox-content has-buttons">'; 
  1102. echo $this->p->msgs->get( 'column-purchase-pro' ); 
  1103. echo '</div>'; 
  1104. echo '<div class="column-metabox-buttons">'; 
  1105. echo $this->form->get_button( _x( 'Purchase Pro Version', 'plugin action link', 'nextgen-facebook' ),  
  1106. 'button-primary', 'column-purchase-pro', $purchase_url, true ); 
  1107. echo '</div>'; 
  1108. echo '</td></tr></table>'; 
  1109.  
  1110. public function show_metabox_install_pro() { 
  1111. $lca = $this->p->cf['lca']; 
  1112. echo '<table class="sucom-settings '.$lca.' column-metabox"><tr><td>'; 
  1113. echo '<div class="column-metabox-content">'; 
  1114. echo $this->p->msgs->get( 'column-install-pro' ); 
  1115. echo '</div>'; 
  1116. echo '</td></tr></table>'; 
  1117.  
  1118. public function show_metabox_help_support() { 
  1119.  
  1120. $lca = $this->p->cf['lca']; 
  1121. echo '<table class="sucom-settings '.$lca.' column-metabox"><tr><td>'; 
  1122. $this->show_follow_icons(); 
  1123. echo $this->p->msgs->get( 'column-help-support' ); 
  1124.  
  1125. foreach ( $this->p->cf['plugin'] as $ext => $info ) { 
  1126.  
  1127. if ( empty( $info['version'] ) ) { // filter out extensions that are not installed 
  1128. continue; 
  1129.  
  1130. $links = array(); 
  1131.  
  1132. if ( ! empty( $info['url']['faqs'] ) ) { 
  1133. $links[] = sprintf( __( 'Read the <a href="%s" target="_blank">Frequently Asked Questions</a>',  
  1134. 'nextgen-facebook' ), $info['url']['faqs'] ).( ! empty( $info['url']['notes'] ) ? 
  1135. ' '.sprintf( __( 'and <a href="%s" target="_blank">Other Notes</a>',  
  1136. 'nextgen-facebook' ), $info['url']['notes'] ) : '' ); 
  1137.  
  1138. if ( ! empty( $info['url']['support'] ) && self::$pkg[$ext]['aop'] ) { 
  1139. $links[] = sprintf( __( 'Open a <a href="%s" target="_blank">Priority Support Ticket</a>',  
  1140. 'nextgen-facebook' ), $info['url']['support'] ).' ('.__( 'Pro version', 'nextgen-facebook' ).')'; 
  1141. } elseif ( ! empty( $info['url']['forum'] ) ) { 
  1142. $links[] = sprintf( __( 'Post in the <a href="%s" target="_blank">Community Support Forum</a>',  
  1143. 'nextgen-facebook' ), $info['url']['forum'] ).' ('.__( 'Free version', 'nextgen-facebook' ).')'; 
  1144.  
  1145. if ( ! empty( $links ) ) { 
  1146. echo '<h4>'.$info['short'].'</h4>'."\n"; 
  1147. echo '<ul><li>'.implode( '</li><li>', $links ).'</li></ul>'."\n"; 
  1148.  
  1149. echo '</td></tr></table>'; 
  1150.  
  1151. public function show_metabox_rate_review() { 
  1152. $lca = $this->p->cf['lca']; 
  1153. echo '<table class="sucom-settings '.$lca.' column-metabox"><tr><td>'; 
  1154. echo $this->p->msgs->get( 'column-rate-review' ); 
  1155.  
  1156. foreach ( $this->p->cf['plugin'] as $ext => $info ) { 
  1157. if ( empty( $info['version'] ) ) { // filter out extensions that are not installed 
  1158. continue; 
  1159.  
  1160. $links = array(); 
  1161.  
  1162. if ( ! empty( $info['url']['review'] ) ) { 
  1163.  
  1164. $rate_stars = '<span class="ngfb-rate-stars"></span>'; 
  1165. $plugin_name = '<em>'.$info['name'].'</em>'; 
  1166.  
  1167. $links[] = '<a href="'.$info['url']['review'].'" target="_blank">'. 
  1168. sprintf( __( 'Rate %1$s the %2$s plugin.', 'nextgen-facebook' ),  
  1169. $rate_stars, $plugin_name ).'</a>'; 
  1170.  
  1171. if ( ! empty( $links ) ) { 
  1172. echo '<ul><li>'.implode( '</li><li>', $links ).'</li></ul>'."\n"; 
  1173.  
  1174. echo '</td></tr></table>'; 
  1175.  
  1176. protected function show_follow_icons() { 
  1177. echo '<div class="follow-icons">'; 
  1178. $img_size = $this->p->cf['follow']['size']; 
  1179. foreach ( $this->p->cf['follow']['src'] as $img_rel => $url ) { 
  1180. echo '<a href="'.$url.'" target="_blank"><img src="'.NGFB_URLPATH.$img_rel.'" 
  1181. width="'.$img_size.'" height="'.$img_size.'" border="0" /></a>'; 
  1182. echo '</div>'; 
  1183.  
  1184. public static function get_nonce() { 
  1185. return __FILE__.'::'. 
  1186. SucomUtil::get_const( 'NONCE_KEY' ).'::'. 
  1187. SucomUtil::get_const( 'NONCE_SALT' ); 
  1188.  
  1189. private function is_profile( $menu_id = false ) { 
  1190. return $this->is_lib( 'profile', $menu_id ); 
  1191.  
  1192. private function is_setting( $menu_id = false ) { 
  1193. return $this->is_lib( 'setting', $menu_id ); 
  1194.  
  1195. private function is_submenu( $menu_id = false ) { 
  1196. return $this->is_lib( 'submenu', $menu_id ); 
  1197.  
  1198. private function is_sitesubmenu( $menu_id = false ) { 
  1199. return $this->is_lib( 'sitesubmenu', $menu_id ); 
  1200.  
  1201. private function is_lib( $lib_name, $menu_id = false ) { 
  1202. if ( $menu_id === false ) { 
  1203. $menu_id = $this->menu_id; 
  1204. return isset( $this->p->cf['*']['lib'][$lib_name][$menu_id] ) ? true : false; 
  1205.  
  1206. public function licenses_metabox_content( $network = false ) { 
  1207. $num = 0; 
  1208. $tabindex = 0; 
  1209. $lca = $this->p->cf['lca']; 
  1210. $total = count( $this->p->cf['plugin'] ); 
  1211. $row_span = $network ? 4 : 3; 
  1212. $col_span = $network ? 2 : 3; 
  1213.  
  1214. echo '<table class="sucom-settings '.$lca.' licenses-metabox" 
  1215. style="padding-bottom:10px">'."\n"; 
  1216.  
  1217. echo '<tr><td colspan="'.( $col_span + 1 ).'">'. 
  1218. $this->p->msgs->get( 'info-plugin-tid'.( $network ? '-network' : '' ) ). 
  1219. '</td></tr>'."\n"; 
  1220.  
  1221. foreach ( NgfbConfig::get_ext_sorted( true ) as $ext => $info ) { 
  1222. $num++; 
  1223. $links = array(); 
  1224.  
  1225. if ( ! empty( $info['base'] ) ) { 
  1226.  
  1227. $details_url = add_query_arg( array( 
  1228. 'tab' => 'plugin-information',  
  1229. 'plugin' => $info['slug'],  
  1230. 'TB_iframe' => 'true',  
  1231. 'width' => $this->p->cf['wp']['tb_iframe']['width'],  
  1232. 'height' => $this->p->cf['wp']['tb_iframe']['height'] 
  1233. ), is_multisite() ? 
  1234. network_admin_url( 'plugin-install.php', null ) : 
  1235. get_admin_url( null, 'plugin-install.php' ) ); 
  1236.  
  1237. if ( SucomUtil::installed_plugins( $info['base'] ) ) { 
  1238.  
  1239. if ( SucomUtil::plugin_has_update( $info['base'] ) ) { 
  1240. $links[] = '<a href="'.$details_url.'" class="thickbox" tabindex="'.++$tabindex.'">'. 
  1241. '<font color="red">'._x( 'Plugin Details and Update', 'plugin action link',  
  1242. 'nextgen-facebook' ).'</font></a>'; 
  1243. } else { 
  1244. $links[] = '<a href="'.$details_url.'" class="thickbox" tabindex="'.++$tabindex.'">'. 
  1245. _x( 'Plugin Details', 'plugin action link', 'nextgen-facebook' ).'</a>'; 
  1246. } else { 
  1247. $links[] = '<a href="'.$details_url.'" class="thickbox" tabindex="'.++$tabindex.'">'. 
  1248. _x( 'Plugin Details and Install', 'plugin action link', 'nextgen-facebook' ).'</a>'; 
  1249.  
  1250. } elseif ( ! empty( $info['url']['home'] ) ) { 
  1251. $links[] = '<a href="'.$info['url']['home'].'" target="_blank" tabindex="'.++$tabindex.'">'. 
  1252. _x( 'Plugin Description', 'plugin action link', 'nextgen-facebook' ).'</a>'; 
  1253.  
  1254. if ( ! empty( $info['base'] ) ) { 
  1255. $links = $this->add_plugin_action_links( $links, $info['base'], 'license-action-links', $tabindex ); 
  1256.  
  1257. // logo image 
  1258. echo '<tr><td style="width:168px; padding:10px 30px 10px 10px; vertical-align:top;"'. 
  1259. ' width="168" rowspan="'.$row_span.'" valign="top" align="left">'."\n"; 
  1260. echo $this->get_ext_img_icon( $ext ); 
  1261. echo '</td>'."\n"; 
  1262.  
  1263. // plugin name 
  1264. echo '<td colspan="'.$col_span.'" style="padding:10px 0 0 0; width:100%;"><p><strong>'.$info['name'].'</strong></p>'; 
  1265.  
  1266. if ( ! empty( $info['desc'] ) ) { 
  1267. echo '<p>'._x( $info['desc'], 'plugin description', 'nextgen-facebook' ).'</p>'; 
  1268.  
  1269. if ( ! empty( $links ) ) { 
  1270. echo '<div class="row-actions visible">'.implode( ' | ', $links ).'</div>'; 
  1271.  
  1272. echo '</td></tr>'."\n"; 
  1273.  
  1274. if ( ! empty( $info['update_auth'] ) || 
  1275. ! empty( $this->p->options['plugin_'.$ext.'_tid'] ) ) { 
  1276.  
  1277. echo '<tr>'; 
  1278. echo $this->form->get_th_html( sprintf( _x( '%s Authentication ID',  
  1279. 'option label', 'nextgen-facebook' ), $info['short'] ), 'medium nowrap' ); 
  1280.  
  1281. if ( $lca === $ext || self::$pkg[$lca]['aop'] ) { 
  1282. echo '<td'.( $network ? ' width="100%"' : '' ).'>'. 
  1283. $this->form->get_input( 'plugin_'.$ext.'_tid',  
  1284. 'tid mono', '', 0, '', false, ++$tabindex ).'</td>'; 
  1285.  
  1286. if ( $network ) { 
  1287. echo '</tr><tr>'; 
  1288. echo self::get_option_site_use( 'plugin_'.$ext.'_tid',  
  1289. $this->form, $network, true ); // th and td 
  1290. } else { 
  1291. $qty_used = class_exists( 'SucomUpdate' ) ? 
  1292. SucomUpdate::get_option( $ext, 'qty_used' ) : false; 
  1293. echo '<td width="100%"><p>'.( empty( $qty_used ) ? 
  1294. '' : $qty_used.' Licenses Assigned' ).'</p></td>'; 
  1295. } else { 
  1296. echo '<td class="blank">'.( empty( $this->p->options['plugin_'.$ext.'_tid'] ) ? 
  1297. $this->form->get_no_input( 'plugin_'.$ext.'_tid', 'tid mono' ) : 
  1298. $this->form->get_input( 'plugin_'.$ext.'_tid',  
  1299. 'tid mono', '', 0, '', false, ++$tabindex ) ).'</td>'; 
  1300. echo '</tr>'."\n"; 
  1301. } else { 
  1302. if ( $network ) { 
  1303. echo '<tr></tr>'."\n"; 
  1304. echo '<tr><td> </td></tr>'."\n"; 
  1305. } else { 
  1306. echo '<tr><td> </td><td></td><td width="100%"></td></tr>'."\n"; 
  1307.  
  1308. echo '<tr><td'.( $num < $total ? ' style="border-bottom:1px dotted #ddd; height:5px;"' : '' ). 
  1309. ' colspan="'.$col_span.'"></td></tr>'."\n"; 
  1310. echo '</table>'."\n"; 
  1311.  
  1312. public function conflict_warnings() { 
  1313. if ( ! is_admin() ) // just in case 
  1314. return; 
  1315.  
  1316. $lca = $this->p->cf['lca']; 
  1317. $err_pre = __( 'Plugin conflict detected', 'nextgen-facebook' ) . ' — '; 
  1318. $log_pre = 'plugin conflict detected - '; // don't translate the debug 
  1319.  
  1320. // PHP 
  1321. foreach ( $this->p->cf['php']['extensions'] as $php_ext => $php_label ) { 
  1322. if ( ! extension_loaded( $php_ext ) ) { 
  1323. if ( $this->p->debug->enabled ) { 
  1324. $this->p->debug->log( 'php '.$php_ext.' extension is not loaded' ); 
  1325. $this->p->notice->err( sprintf( __( 'The PHP <a href="%1$s" target="_blank">%2$s extension</a> is not loaded.',  
  1326. 'nextgen-facebook' ), 'https://secure.php.net/manual/en/book.'.$php_ext.'.php', $php_label ).' '. 
  1327. __( 'Please contact your hosting provider to have the missing PHP extension installed and/or enabled.',  
  1328. 'nextgen-facebook' ) ); 
  1329.  
  1330. // WordPress 
  1331. if ( ! get_option( 'blog_public' ) ) { 
  1332. if ( $this->p->debug->enabled ) { 
  1333. $this->p->debug->log( 'blog_public option is disabled' ); 
  1334. $warn_dis_key = 'wordpress-search-engine-visibility-disabled'; 
  1335. if ( $this->p->notice->is_admin_pre_notices( $warn_dis_key ) ) { // don't bother if already dismissed 
  1336. $this->p->notice->warn( sprintf( __( 'The WordPress <a href="%s">Search Engine Visibility</a> option is set to discourage search engine and social crawlers from indexing this site. This is not compatible with the purpose of sharing content on social sites — please uncheck the option to allow search engines and social crawlers to access your content.', 'nextgen-facebook' ), get_admin_url( null, 'options-reading.php' ) ), true, $warn_dis_key, MONTH_IN_SECONDS * 3 ); 
  1337.  
  1338. // Yoast SEO 
  1339. if ( $this->p->avail['seo']['wpseo'] ) { 
  1340. $opts = get_option( 'wpseo_social' ); 
  1341. if ( ! empty( $opts['opengraph'] ) ) { 
  1342. if ( $this->p->debug->enabled ) { 
  1343. $this->p->debug->log( $log_pre.'wpseo opengraph meta data option is enabled' ); 
  1344. $this->p->notice->err( $err_pre.sprintf( __( 'please uncheck the <strong>Add Open Graph meta data</strong> option under the <a href="%s">Yoast SEO / Social / Facebook</a> settings tab.', 'nextgen-facebook' ), get_admin_url( null, 'admin.php?page=wpseo_social#top#facebook' ) ) ); 
  1345. if ( ! empty( $opts['twitter'] ) ) { 
  1346. if ( $this->p->debug->enabled ) { 
  1347. $this->p->debug->log( $log_pre.'wpseo twitter meta data option is enabled' ); 
  1348. $this->p->notice->err( $err_pre.sprintf( __( 'please uncheck the <strong>Add Twitter card meta data</strong> option under the <a href="%s">Yoast SEO / Social / Twitter</a> settings tab.', 'nextgen-facebook' ), get_admin_url( null, 'admin.php?page=wpseo_social#top#twitterbox' ) ) ); 
  1349. if ( ! empty( $opts['googleplus'] ) ) { 
  1350. if ( $this->p->debug->enabled ) { 
  1351. $this->p->debug->log( $log_pre.'wpseo googleplus meta data option is enabled' ); 
  1352. $this->p->notice->err( $err_pre.sprintf( __( 'please uncheck the <strong>Add Google+ specific post meta data</strong> option under the <a href="%s">Yoast SEO / Social / Google+</a> settings tab.', 'nextgen-facebook' ), get_admin_url( null, 'admin.php?page=wpseo_social#top#google' ) ) ); 
  1353. if ( ! empty( $opts['plus-publisher'] ) ) { 
  1354. if ( $this->p->debug->enabled ) { 
  1355. $this->p->debug->log( $log_pre.'wpseo google plus publisher option is defined' ); 
  1356. $this->p->notice->err( $err_pre.sprintf( __( 'please remove the <strong>Google Publisher Page</strong> value entered under the <a href="%s">Yoast SEO / Social / Google+</a> settings tab.', 'nextgen-facebook' ), get_admin_url( null, 'admin.php?page=wpseo_social#top#google' ) ) ); 
  1357.  
  1358. // SEO Ultimate 
  1359. if ( $this->p->avail['seo']['seou'] ) { 
  1360. $opts = get_option( 'seo_ultimate' ); 
  1361. if ( ! empty( $opts['modules'] ) && is_array( $opts['modules'] ) ) { 
  1362. if ( array_key_exists( 'opengraph', $opts['modules'] ) && $opts['modules']['opengraph'] !== -10 ) { 
  1363. if ( $this->p->debug->enabled ) { 
  1364. $this->p->debug->log( $log_pre.'seo ultimate opengraph module is enabled' ); 
  1365. $this->p->notice->err( $err_pre.sprintf( __( 'please disable the <strong>Open Graph Integrator</strong> module in the <a href="%s">SEO Ultimate Module Manager</a>.', 'nextgen-facebook' ), get_admin_url( null, 'admin.php?page=seo' ) ) ); 
  1366.  
  1367. // All in One SEO Pack 
  1368. if ( $this->p->avail['seo']['aioseop'] ) { 
  1369. $opts = get_option( 'aioseop_options' ); 
  1370. if ( ! empty( $opts['modules']['aiosp_feature_manager_options']['aiosp_feature_manager_enable_opengraph'] ) ) { 
  1371. if ( $this->p->debug->enabled ) { 
  1372. $this->p->debug->log( $log_pre.'aioseop social meta feature is enabled' ); 
  1373. $this->p->notice->err( $err_pre.sprintf( __( 'please deactivate the <strong>Social Meta</strong> feature in the <a href="%s">All in One SEO Pack Feature Manager</a>.', 'nextgen-facebook' ), get_admin_url( null, 'admin.php?page=all-in-one-seo-pack/modules/aioseop_feature_manager.php' ) ) ); 
  1374. if ( isset( $opts['aiosp_google_disable_profile'] ) && empty( $opts['aiosp_google_disable_profile'] ) ) { 
  1375. if ( $this->p->debug->enabled ) { 
  1376. $this->p->debug->log( $log_pre.'aioseop google plus profile is enabled' ); 
  1377. $this->p->notice->err( $err_pre.sprintf( __( 'please check the <strong>Disable Google Plus Profile</strong> option in the <a href="%s">All in One SEO Pack General Settings</a>.', 'nextgen-facebook' ), get_admin_url( null, 'admin.php?page=all-in-one-seo-pack/aioseop_class.php' ) ) ); 
  1378. if ( isset( $opts['aiosp_schema_markup'] ) && ! empty( $opts['aiosp_schema_markup'] ) ) { 
  1379. if ( $this->p->debug->enabled ) { 
  1380. $this->p->debug->log( $log_pre.'aioseop schema markup is enabled' ); 
  1381. $this->p->notice->err( $err_pre.sprintf( __( 'please uncheck the <strong>Use Schema.org Markup</strong> option in the <a href="%s">All in One SEO Pack General Settings</a>.', 'nextgen-facebook' ), get_admin_url( null, 'admin.php?page=all-in-one-seo-pack/aioseop_class.php' ) ) ); 
  1382.  
  1383. // The SEO Framework 
  1384. if ( $this->p->avail['seo']['autodescription'] ) { 
  1385. $the_seo_framework = the_seo_framework(); 
  1386. if ( $the_seo_framework->use_og_tags() ) { 
  1387. if ( $this->p->debug->enabled ) { 
  1388. $this->p->debug->log( $log_pre.'autodescription open graph meta tags are enabled' ); 
  1389. $this->p->notice->err( $err_pre.sprintf( __( 'please uncheck the <strong>%1$s</strong> option in <a href="%2$s">The SEO Framework</a> Social Meta Settings.', 'nextgen-facebook' ), 'Output Open Graph meta tags?', get_admin_url( null, 'admin.php?page=theseoframework-settings' ) ) ); 
  1390. if ( $the_seo_framework->use_facebook_tags() ) { 
  1391. if ( $this->p->debug->enabled ) { 
  1392. $this->p->debug->log( $log_pre.'autodescription facebook meta tags are enabled' ); 
  1393. $this->p->notice->err( $err_pre.sprintf( __( 'please uncheck the <strong>%1$s</strong> option in <a href="%2$s">The SEO Framework</a> Social Meta Settings.', 'nextgen-facebook' ), 'Output Facebook meta tags?', get_admin_url( null, 'admin.php?page=theseoframework-settings' ) ) ); 
  1394. if ( $the_seo_framework->use_twitter_tags() ) { 
  1395. if ( $this->p->debug->enabled ) { 
  1396. $this->p->debug->log( $log_pre.'autodescription twitter meta tags are enabled' ); 
  1397. $this->p->notice->err( $err_pre.sprintf( __( 'please uncheck the <strong>%1$s</strong> option in <a href="%2$s">The SEO Framework</a> Social Meta Settings.', 'nextgen-facebook' ), 'Output Twitter meta tags?', get_admin_url( null, 'admin.php?page=theseoframework-settings' ) ) ); 
  1398. if ( $the_seo_framework->is_option_checked( 'knowledge_output' ) ) { 
  1399. if ( $this->p->debug->enabled ) { 
  1400. $this->p->debug->log( $log_pre.'autodescription knowledge graph is enabled' ); 
  1401. $this->p->notice->err( $err_pre.sprintf( __( 'please uncheck the <strong>Output Authorized Presence?</strong> option in <a href="%s">The SEO Framework</a> Schema Settings.', 'nextgen-facebook' ), get_admin_url( null, 'admin.php?page=theseoframework-settings' ) ) ); 
  1402. foreach ( array( 
  1403. 'post_publish_time' => 'Add article:published_time to Posts',  
  1404. 'page_publish_time' => 'Add article:published_time to Pages',  
  1405. 'home_publish_time' => 'Add article:published_time to Home Page',  
  1406. 'post_modify_time' => 'Add article:modified_time to Posts',  
  1407. 'page_modify_time' => 'Add article:modified_time to Pages',  
  1408. 'home_modify_time' => 'Add article:modified_time to Home Page',  
  1409. ) as $key => $label ) { 
  1410. if ( $the_seo_framework->get_option( $key ) ) { 
  1411. if ( $this->p->debug->enabled ) { 
  1412. $this->p->debug->log( $log_pre.'autodescription '.$key.' option is enabled' ); 
  1413. $this->p->notice->err( $err_pre.sprintf( __( 'please uncheck the <strong>%1$s</strong> option in <a href="%2$s">The SEO Framework</a> Social Meta Settings.', 'nextgen-facebook' ), $label, get_admin_url( null, 'admin.php?page=theseoframework-settings' ) ) ); 
  1414.  
  1415. // Squirrly SEO 
  1416. if ( $this->p->avail['seo']['sq'] ) { 
  1417. $opts = json_decode( get_option( 'sq_options' ), true ); 
  1418. if ( ! empty( $opts['sq_auto_facebook'] ) ) { 
  1419. if ( $this->p->debug->enabled ) { 
  1420. $this->p->debug->log( $log_pre.'squirrly seo open graph meta tags are enabled' ); 
  1421. $this->p->notice->err( $err_pre.sprintf( __( 'please uncheck <strong>Add the Social Open Graph objects</strong> in the <a href="%s">Squirrly SEO</a> Social Media Options.', 'nextgen-facebook' ), get_admin_url( null, 'admin.php?page=sq_seo' ) ) ); 
  1422. if ( ! empty( $opts['sq_auto_twitter'] ) ) { 
  1423. if ( $this->p->debug->enabled ) { 
  1424. $this->p->debug->log( $log_pre.'squirrly seo twitter card meta tags are enabled' ); 
  1425. $this->p->notice->err( $err_pre.sprintf( __( 'please uncheck <strong>Add the Twitter card in your tweets</strong> in the <a href="%s">Squirrly SEO</a> Social Media Options.', 'nextgen-facebook' ), get_admin_url( null, 'admin.php?page=sq_seo' ) ) ); 
  1426. if ( ! empty( $opts['sq_auto_jsonld'] ) ) { 
  1427. if ( $this->p->debug->enabled ) { 
  1428. $this->p->debug->log( $log_pre.'squirrly seo json-ld markup is enabled' ); 
  1429. $this->p->notice->err( $err_pre.sprintf( __( 'please uncheck the <strong>adds the JSON-LD metas for Semantic SEO</strong> option in the <a href="%s">Squirrly SEO</a> settings.', 'nextgen-facebook' ), get_admin_url( null, 'admin.php?page=sq_seo' ) ) ); 
  1430.  
  1431. public function required_notices() { 
  1432.  
  1433. $lca = $this->p->cf['lca']; 
  1434. $version = $this->p->cf['plugin'][$lca]['version']; 
  1435. $have_ext_tid = false; 
  1436.  
  1437. if ( $this->p->avail['*']['p_dir'] === true && 
  1438. empty( $this->p->options['plugin_'.$lca.'_tid'] ) && 
  1439. ( empty( $this->p->options['plugin_'.$lca.'_tid:is'] ) || 
  1440. $this->p->options['plugin_'.$lca.'_tid:is'] !== 'disabled' ) ) { 
  1441. $this->p->notice->nag( $this->p->msgs->get( 'notice-pro-tid-missing' ) ); 
  1442.  
  1443. foreach ( $this->p->cf['plugin'] as $ext => $info ) { 
  1444. if ( ! empty( $this->p->options['plugin_'.$ext.'_tid'] ) ) { 
  1445. // found at least one plugin with an auth id 
  1446. $have_ext_tid = true; 
  1447. if ( ! self::$pkg[$ext]['pdir'] ) { 
  1448. if ( ! empty( $info['base'] ) && ! SucomUtil::installed_plugins( $info['base'] ) ) { 
  1449. $this->p->notice->warn( $this->p->msgs->get( 'notice-pro-not-installed',  
  1450. array( 'lca' => $ext ) ) ); 
  1451. } else { 
  1452. $this->p->notice->warn( $this->p->msgs->get( 'notice-pro-not-updated',  
  1453. array( 'lca' => $ext ) ) ); 
  1454.  
  1455. if ( $have_ext_tid === true ) { 
  1456. $um_info = $this->p->cf['plugin']['ngfbum']; 
  1457. // if the update manager is active, the version should be available 
  1458. if ( ! empty( $um_info['version'] ) ) { 
  1459. // check for minimum update manager version required 
  1460. $min_version = NgfbConfig::$cf['um']['min_version']; 
  1461. if ( version_compare( $um_info['version'], $min_version, '<' ) ) { 
  1462. $this->p->notice->err( $this->p->msgs->get( 'notice-um-version-required',  
  1463. array( 'min_version' => $min_version ) ) ); 
  1464. // if the update manager is not active, check if installed 
  1465. } elseif ( SucomUtil::installed_plugins( $um_info['base'] ) ) { 
  1466. $this->p->notice->nag( $this->p->msgs->get( 'notice-um-activate-extension' ) ); 
  1467. // update manager is not active or installed 
  1468. } else { 
  1469. $this->p->notice->nag( $this->p->msgs->get( 'notice-um-extension-required' ) ); 
  1470.  
  1471. if ( current_user_can( 'manage_options' ) ) { 
  1472. foreach ( array( 'wp', 'php' ) as $key ) { 
  1473. if ( isset( NgfbConfig::$cf[$key]['rec_version'] ) ) { 
  1474. switch ( $key ) { 
  1475. case 'wp': 
  1476. global $wp_version; 
  1477. $app_version = $wp_version; 
  1478. break; 
  1479. case 'php': 
  1480. $app_version = phpversion(); 
  1481. break; 
  1482. $app_label = NgfbConfig::$cf[$key]['label']; 
  1483. $rec_version = NgfbConfig::$cf[$key]['rec_version']; 
  1484.  
  1485. if ( version_compare( $app_version, $rec_version, '<' ) ) { 
  1486. $warn_msg = $this->p->msgs->get( 'notice-recommend-version', array( 
  1487. 'app_label' => $app_label,  
  1488. 'app_version' => $app_version,  
  1489. 'rec_version' => NgfbConfig::$cf[$key]['rec_version'],  
  1490. 'version_url' => NgfbConfig::$cf[$key]['version_url'],  
  1491. ) ); 
  1492. $warn_dis_key = 'notice-recommend-version-'.$lca.'-'.$version.'-'.$app_label.'-'.$app_version; 
  1493. $this->p->notice->warn( $warn_msg, true, $warn_dis_key, MONTH_IN_SECONDS, true ); // $silent = true 
  1494.  
  1495. public function reset_check_head_count() { 
  1496. delete_option( NGFB_POST_CHECK_NAME ); 
  1497.  
  1498. public function check_tmpl_head_attributes() { 
  1499.  
  1500. if ( $this->p->debug->enabled ) { 
  1501. $this->p->debug->mark(); 
  1502.  
  1503. // only check if using the default filter name 
  1504. if ( empty( $this->p->options['plugin_head_attr_filter_name'] ) || 
  1505. $this->p->options['plugin_head_attr_filter_name'] !== 'head_attributes' || 
  1506. ! apply_filters( $this->p->cf['lca'].'_add_schema_head_attributes', true ) ) { 
  1507. return; // exit early 
  1508.  
  1509. foreach ( SucomUtil::get_header_files() as $tmpl_file ) { 
  1510. if ( ( $html = SucomUtil::get_stripped_php( $tmpl_file ) ) === false ) { 
  1511. continue; 
  1512. } elseif ( strpos( $html, '<head>' ) !== false ) { 
  1513. // skip if notices already shown 
  1514. if ( $this->p->notice->is_admin_pre_notices() ) { 
  1515. // allow warning to be dismissed until the next theme update 
  1516. $warn_dis_key = 'notice-header-tmpl-no-head-attr-'.SucomUtil::get_theme_slug_version(); 
  1517. $this->p->notice->warn( $this->p->msgs->get( 'notice-header-tmpl-no-head-attr' ),  
  1518. true, $warn_dis_key, true ); // can be dismissed 
  1519. break; 
  1520.  
  1521. public function modify_tmpl_head_attributes() { 
  1522.  
  1523. $have_changes = false; 
  1524. $header_files = SucomUtil::get_header_files(); 
  1525. $head_action_php = '<head <?php do_action( \'add_head_attributes\' ); ?'.'>>'; // breakup closing php for vim syntax highlighting 
  1526.  
  1527. if ( empty( $header_files ) ) { 
  1528. $this->p->notice->err( __( 'No header templates found in the parent or child theme directories.',  
  1529. 'nextgen-facebook' ) ); 
  1530. return; // exit early 
  1531.  
  1532. foreach ( $header_files as $tmpl_file ) { 
  1533. $tmpl_base = basename( $tmpl_file ); 
  1534. $backup_file = $tmpl_file.'~backup-'.date( 'Ymd-His' ); 
  1535. $backup_base = basename( $backup_file ); 
  1536.  
  1537. // double check in case of reloads etc. 
  1538. if ( ( $html = SucomUtil::get_stripped_php( $tmpl_file ) ) === false || 
  1539. strpos( $html, '<head>' ) === false ) { 
  1540. $this->p->notice->err( sprintf( __( 'No <head> HTML element found in the %s template.',  
  1541. 'nextgen-facebook' ), $tmpl_file ) ); 
  1542. continue; 
  1543.  
  1544. // make a backup of the original 
  1545. if ( ! copy( $tmpl_file, $backup_file ) ) { 
  1546. $this->p->notice->err( sprintf( __( 'Error copying %1$s to %2$s.', 'nextgen-facebook' ),  
  1547. $tmpl_file, $backup_base ) ); 
  1548. continue; 
  1549.  
  1550. $tmpl_contents = file_get_contents( $tmpl_file ); 
  1551. $tmpl_contents = str_replace( '<head>', $head_action_php, $tmpl_contents ); 
  1552.  
  1553. if ( ! $tmpl_fh = @fopen( $tmpl_file, 'wb' ) ) { 
  1554. $this->p->notice->err( sprintf( __( 'Failed to open %s for writing.',  
  1555. 'nextgen-facebook' ), $tmpl_file ) ); 
  1556. continue; 
  1557.  
  1558. if ( fwrite( $tmpl_fh, $tmpl_contents ) ) { 
  1559. $this->p->notice->upd( sprintf( __( 'The %1$s template has been successfully modified and saved. A backup copy of the original template is available as %2$s in the same folder.', 'nextgen-facebook' ), $tmpl_file, $backup_base ) ); 
  1560. $have_changes = true; 
  1561. } else { 
  1562. $this->p->notice->err( sprintf( __( 'Failed to write the %1$s template. You may need to restore the original template saved as %2$s in the same folder.', 'nextgen-facebook' ), $tmpl_file, $backup_base ) ); 
  1563.  
  1564. fclose( $tmpl_fh ); 
  1565.  
  1566. if ( $have_changes ) { 
  1567. $dis_key = 'notice-header-tmpl-no-head-attr-'.SucomUtil::get_theme_slug_version(); 
  1568. $this->p->notice->trunc_key( $dis_key, 'all' ); // just in case 
  1569.  
  1570. // called from the NgfbSubmenuEssential and NgfbSubmenuAdvanced classes 
  1571. protected function add_essential_advanced_table_rows( array &$table_rows, $form, $network = false ) { 
  1572.  
  1573. $table_rows['plugin_preserve'] = $form->get_th_html( _x( 'Preserve Settings on Uninstall',  
  1574. 'option label', 'nextgen-facebook' ), '', 'plugin_preserve' ). 
  1575. '<td>'.$form->get_checkbox( 'plugin_preserve' ).'</td>'. 
  1576. self::get_option_site_use( 'plugin_preserve', $form, $network, true ); 
  1577.  
  1578. $table_rows['plugin_debug'] = $form->get_th_html( _x( 'Add Hidden Debug Messages',  
  1579. 'option label', 'nextgen-facebook' ), '', 'plugin_debug' ). 
  1580. '<td>'.( ! $network && SucomUtil::get_const( 'NGFB_HTML_DEBUG' ) ? 
  1581. $form->get_no_checkbox( 'plugin_debug' ).' <em>NGFB_HTML_DEBUG constant is true</em>' : 
  1582. $form->get_checkbox( 'plugin_debug' ) ).'</td>'. 
  1583. self::get_option_site_use( 'plugin_debug', $form, $network, true ); 
  1584.  
  1585. if ( $network || ! $this->p->check->aop( $this->p->cf['lca'], true, $this->p->avail['*']['p_dir'] ) ) { 
  1586. $table_rows['plugin_hide_pro'] = $form->get_th_html( _x( 'Hide All Pro Version Options',  
  1587. 'option label', 'nextgen-facebook' ), null, 'plugin_hide_pro' ). 
  1588. '<td>'.$form->get_checkbox( 'plugin_hide_pro' ).'</td>'. 
  1589. self::get_option_site_use( 'plugin_show_opts', $form, $network, true ); 
  1590. } else { 
  1591. $form->get_hidden( 'plugin_hide_pro', 0, true ); 
  1592.  
  1593. $table_rows['plugin_show_opts'] = $form->get_th_html( _x( 'Options to Show by Default',  
  1594. 'option label', 'nextgen-facebook' ), null, 'plugin_show_opts' ). 
  1595. '<td>'.$form->get_select( 'plugin_show_opts', $this->p->cf['form']['show_options'] ).'</td>'. 
  1596. self::get_option_site_use( 'plugin_show_opts', $form, $network, true ); 
  1597.  
  1598. if ( ! empty( $this->p->cf['*']['lib']['shortcode'] ) ) { 
  1599. $table_rows['plugin_shortcodes'] = '<tr class="hide_in_basic">'. 
  1600. $form->get_th_html( _x( 'Enable Plugin Shortcode(s)',  
  1601. 'option label', 'nextgen-facebook' ), '', 'plugin_shortcodes' ). 
  1602. '<td>'.$form->get_checkbox( 'plugin_shortcodes' ).'</td>'. 
  1603. self::get_option_site_use( 'plugin_shortcodes', $form, $network, true ); 
  1604.  
  1605. if ( ! empty( $this->p->cf['*']['lib']['widget'] ) ) { 
  1606. $table_rows['plugin_widgets'] = '<tr class="hide_in_basic">'. 
  1607. $form->get_th_html( _x( 'Enable Plugin Widget(s)',  
  1608. 'option label', 'nextgen-facebook' ), '', 'plugin_widgets' ). 
  1609. '<td>'.$form->get_checkbox( 'plugin_widgets' ).'</td>'. 
  1610. self::get_option_site_use( 'plugin_widgets', $form, $network, true ); 
  1611.  
  1612. // deprecated on 2017/04/02 
  1613. public function get_site_use( $form, $network, $name, $enabled = false ) { 
  1614. return self::get_option_site_use( $name, $form, $network, $enabled ); // note the different arg order 
  1615.  
  1616. public static function get_option_site_use( $name, $form, $network = false, $enabled = false ) { 
  1617. if ( $network ) { 
  1618. return $form->get_th_html( _x( 'Site Use',  
  1619. 'option label (very short)', 'nextgen-facebook' ),  
  1620. 'site_use' ).( $enabled || self::$pkg['ngfb']['aop'] ? 
  1621. '<td class="site_use">'.$form->get_select( $name.':use',  
  1622. NgfbConfig::$cf['form']['site_option_use'], 'site_use' ).'</td>' : 
  1623. '<td class="blank site_use">'.$form->get_select( $name.':use',  
  1624. NgfbConfig::$cf['form']['site_option_use'], 'site_use', '', true, true ).'</td>' ); 
  1625. } else { 
  1626. return ''; 
  1627.  
  1628. public function get_readme_info( $ext, $use_cache = true ) { 
  1629.  
  1630. if ( $this->p->debug->enabled ) { 
  1631. $this->p->debug->log_args( array(  
  1632. 'ext' => $ext,  
  1633. 'use_cache' => $use_cache,  
  1634. ) ); 
  1635.  
  1636. $lca = $this->p->cf['lca']; 
  1637. $readme_info = array(); 
  1638. $readme_url = isset( $this->p->cf['plugin'][$ext]['url']['readme_txt'] ) ? 
  1639. $this->p->cf['plugin'][$ext]['url']['readme_txt'] : ''; 
  1640. $readme_file = defined( strtoupper( $ext ).'_PLUGINDIR' ) ? 
  1641. constant( strtoupper( $ext ).'_PLUGINDIR' ).'readme.txt' : ''; 
  1642. $use_remote = strpos( $readme_url, '://' ) ? true : false; 
  1643.  
  1644. $cache_salt = __METHOD__.'(url:'.$readme_url.'_file:'.$readme_file.')'; 
  1645. $cache_id = $ext.'_'.md5( $cache_salt ); 
  1646. $cache_exp = (int) apply_filters( $lca.'_cache_expire_readme_txt',  
  1647. $this->p->cf['readme_cache_exp'] ); 
  1648.  
  1649. if ( $this->p->debug->enabled ) { 
  1650. $this->p->debug->log( 'transient cache salt '.$cache_salt ); 
  1651.  
  1652. if ( $cache_exp > 0 ) { 
  1653. // check the transient cache, if reading the cache is allowed 
  1654. $readme_info = $use_cache ? get_transient( $cache_id ) : false; 
  1655.  
  1656. if ( is_array( $readme_info ) ) { 
  1657. if ( $this->p->debug->enabled ) { 
  1658. $this->p->debug->log( 'readme_info retrieved from transient '.$cache_id ); 
  1659. return $readme_info; // stop here 
  1660.  
  1661. // get the remote readme 
  1662. if ( $use_remote ) { 
  1663. // clear the cache first if reading the cache is disabled 
  1664. if ( ! $use_cache ) { 
  1665. $this->p->cache->clear( $readme_url ); 
  1666. // get the readme and save it to the disk cache 
  1667. $content = $this->p->cache->get( $readme_url, 'raw', 'file', $cache_exp ); 
  1668. if ( empty( $content ) ) { 
  1669. $use_remote = false; 
  1670. } else { 
  1671. $use_remote = false; 
  1672.  
  1673. // fallback to reading the local readme.txt file 
  1674. if ( $use_remote === false && ! empty( $readme_file ) && $fh = @fopen( $readme_file, 'rb' ) ) { 
  1675. $content = fread( $fh, filesize( $readme_file ) ); 
  1676. fclose( $fh ); 
  1677.  
  1678. if ( empty( $content ) ) { 
  1679. $readme_info = array(); // save an empty array 
  1680. } else { 
  1681. $parser = new SuextParseReadme( $this->p->debug ); 
  1682. $readme_info = $parser->parse_readme_contents( $content ); 
  1683.  
  1684. // remove possibly inaccurate information from local file 
  1685. if ( $use_remote === false && is_array( $readme_info ) ) { 
  1686. foreach ( array( 'stable_tag', 'upgrade_notice' ) as $key ) { 
  1687. unset ( $readme_info[$key] ); 
  1688.  
  1689. // save the parsed readme to the transient cache 
  1690. if ( $cache_exp > 0 ) { 
  1691. set_transient( $cache_id, $readme_info, $cache_exp ); 
  1692. if ( $this->p->debug->enabled ) { 
  1693. $this->p->debug->log( 'readme_info saved to transient '.$cache_id.' ('.$cache_exp.' seconds)'); 
  1694.  
  1695. return (array) $readme_info; // just in case 
  1696.  
  1697. public function get_setup_content( $ext, $read_cache = true ) { 
  1698.  
  1699. if ( $this->p->debug->enabled ) { 
  1700. $this->p->debug->log_args( array(  
  1701. 'ext' => $ext,  
  1702. 'read_cache' => $read_cache,  
  1703. ) ); 
  1704.  
  1705. if ( ! defined( strtoupper( $ext ).'_PLUGINDIR' ) ) { 
  1706. if ( $this->p->debug->enabled ) 
  1707. $this->p->debug->log( strtoupper( $ext ).'_PLUGINDIR is undefined and required' ); 
  1708. return false; 
  1709.  
  1710. $lca = $this->p->cf['lca']; 
  1711. $cache_exp = (int) apply_filters( $lca.'_cache_expire_setup_html',  
  1712. $this->p->cf['setup_cache_exp'] ); 
  1713. $file_url = isset( $this->p->cf['plugin'][$ext]['url']['setup_html'] ) ? 
  1714. $this->p->cf['plugin'][$ext]['url']['setup_html'] : ''; 
  1715. $file_path = constant( strtoupper( $ext ).'_PLUGINDIR' ).'setup.html'; 
  1716. $get_remote = strpos( $file_url, '://' ) ? true : false; 
  1717. $content = false; 
  1718.  
  1719. // get remote setup.html file 
  1720. if ( $cache_exp > 0 && $get_remote ) { 
  1721. if ( ! $read_cache ) { 
  1722. $this->p->cache->clear( $file_url ); // clear the wp object, transient, and file cache 
  1723. $content = $this->p->cache->get( $file_url, 'raw', 'file', $cache_exp ); 
  1724. if ( empty( $content ) ) { 
  1725. $get_remote = false; 
  1726. } else { 
  1727. $get_remote = false; 
  1728.  
  1729. // fallback to local setup.html file 
  1730. if ( $get_remote === false && ! empty( $file_path ) && $fh = @fopen( $file_path, 'rb' ) ) { 
  1731. $content = fread( $fh, filesize( $file_path ) ); 
  1732. fclose( $fh ); 
  1733.  
  1734. return $content; 
  1735.  
  1736. public function plugin_complete_actions( $actions ) { 
  1737. $lca = $this->p->cf['lca']; 
  1738.  
  1739. if ( ! empty( $this->pageref_url ) && ! empty( $this->pageref_title ) ) { 
  1740. foreach ( $actions as $action => &$html ) { 
  1741. switch ( $action ) { 
  1742. case 'plugins_page': 
  1743. $html = '<a href="'.$this->pageref_url.'" target="_parent">'. 
  1744. sprintf( __( 'Return to %s', 'nextgen-facebook' ), $this->pageref_title ).'</a>'; 
  1745. break; 
  1746. default: 
  1747. if ( preg_match( '/^(.*href=")([^"]+)(".*)$/', $html, $matches ) ) { 
  1748. $url = add_query_arg( array( 
  1749. $lca.'_pageref_url' => urlencode( $this->pageref_url ),  
  1750. $lca.'_pageref_title' => urlencode( $this->pageref_title ),  
  1751. ), $matches[2] ); 
  1752. $html = $matches[1].$url.$matches[3]; 
  1753. break; 
  1754. return $actions; 
  1755.  
  1756. public function plugin_complete_redirect( $url ) { 
  1757. $lca = $this->p->cf['lca']; 
  1758.  
  1759. if ( strpos( $url, '?activate=true' ) ) { 
  1760. if ( ! empty( $this->pageref_url ) ) { 
  1761. $this->p->notice->upd( __( 'Plugin <strong>activated</strong>.' ) ); // green status w check mark 
  1762. $url = $this->pageref_url; 
  1763.  
  1764. return $url; 
  1765.  
  1766. public function get_ext_img_icon( $ext, $fallback = true ) { 
  1767. $img_src = 'src="data:image/gif;base64, R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=="'; 
  1768.  
  1769. if ( ! empty( $this->p->cf['plugin'][$ext]['img']['icons'] ) ) { 
  1770. $icons = $this->p->cf['plugin'][$ext]['img']['icons']; 
  1771.  
  1772. if ( ! empty( $icons['low'] ) ) { 
  1773. $img_src = 'src="'.$icons['low'].'"'; 
  1774. if ( ! empty( $icons['high'] ) ) { 
  1775. $img_src .= ' srcset="'.$icons['high'].' 256w"'; 
  1776.  
  1777. return '<img '.$img_src.' width="128" height="128" />'; 
  1778.  
  1779. ?> 
.