/nggallery.php

  1. <?php 
  2. if(preg_match('#' . basename(__FILE__) . '#', $_SERVER['PHP_SELF'])) { die('You are not allowed to call this page directly.'); } 
  3.  
  4. /** 
  5. * Plugin Name: NextGEN Gallery 
  6. * Description: The most popular gallery plugin for WordPress and one of the most popular plugins of all time with over 17 million downloads. 
  7. * Version: 2.2.3 
  8. * Author: Imagely 
  9. * Plugin URI: https://www.imagely.com/wordpress-gallery-plugin/nextgen-gallery/ 
  10. * Author URI: https://www.imagely.com 
  11. * License: GPLv2 
  12. * Text Domain: nggallery 
  13. * Domain Path: /products/photocrati_nextgen/modules/i18n/lang 
  14. */ 
  15.  
  16. if (!class_exists('E_Clean_Exit')) { class E_Clean_Exit extends RuntimeException {} } 
  17. if (!class_exists('E_NggErrorException')) { class E_NggErrorException extends RuntimeException {} } 
  18.  
  19. // This is a temporary function to replace the use of WP's esc_url which strips spaces away from URLs 
  20. // TODO: Move this to a better place 
  21. if (!function_exists('nextgen_esc_url')) { 
  22. function nextgen_esc_url( $url, $protocols = null, $_context = 'display' ) { 
  23. $original_url = $url; 
  24.  
  25. if ( '' == $url ) 
  26. return $url; 
  27. $url = preg_replace('|[^a-z0-9 \\-~+_.?#=!&;, /:%@$\|*\'()\\x80-\\xff]|i', '', $url); 
  28. $strip = array('%0d', '%0a', '%0D', '%0A'); 
  29. $url = _deep_replace($strip, $url); 
  30. $url = str_replace(';//', '://', $url); 
  31. /** If the URL doesn't appear to contain a scheme, we 
  32. * presume it needs http:// appended (unless a relative 
  33. * link starting with /, # or ? or a php file). 
  34. */ 
  35.  
  36. if ( strpos($url, ':') === false && ! in_array( $url[0], array( '/', '#', '?' ) ) && 
  37. ! preg_match('/^[a-z0-9-]+?\.php/i', $url) ) 
  38. $url = 'http://' . $url; 
  39.  
  40. // Replace ampersands and single quotes only when displaying. 
  41. if ( 'display' == $_context ) { 
  42. $url = wp_kses_normalize_entities( $url ); 
  43. $url = str_replace( '&', '&', $url ); 
  44. $url = str_replace( "'", ''', $url ); 
  45. $url = str_replace( ' ', '%20', $url ); 
  46.  
  47. if ( '/' === $url[0] ) { 
  48. $good_protocol_url = $url; 
  49. } else { 
  50. if ( ! is_array( $protocols ) ) 
  51. $protocols = wp_allowed_protocols(); 
  52. $good_protocol_url = wp_kses_bad_protocol( $url, $protocols ); 
  53. if ( strtolower( $good_protocol_url ) != strtolower( $url ) ) 
  54. return ''; 
  55.  
  56. return apply_filters('clean_url', $good_protocol_url, $original_url, $_context); 
  57.  
  58. /** 
  59. * NextGEN Gallery is built on top of the Pope Framework: 
  60. * https://bitbucket.org/photocrati/pope-framework 
  61. * 
  62. * Pope constructs applications by assembling modules. 
  63. * 
  64. * The Bootstrapper. This class performs the following: 
  65. * 1) Loads the Pope Framework 
  66. * 2) Adds a path to the C_Component_Registry instance to search for products 
  67. * 3) Loads all found Products. A Product is a collection of modules with some 
  68. * additional meta data. A Product is responsible for loading any modules it 
  69. * requires. 
  70. * 4) Once all Products (and their associated modules) have been loaded (or in 
  71. * otherwords, "included"), the modules are initialized. 
  72. */ 
  73. class C_NextGEN_Bootstrap 
  74. var $_registry = NULL; 
  75. var $_settings_option_name = 'ngg_options'; 
  76. var $_pope_loaded = FALSE; 
  77. static $debug = FALSE; 
  78. var $minimum_ngg_pro_version = '2.0.5'; 
  79. var $minimum_ngg_plus_version = '1.0.1'; 
  80.  
  81. static function shutdown($exception=NULL) 
  82. if (is_null($exception)) { 
  83. throw new E_Clean_Exit; 
  84. elseif (!($exception instanceof E_Clean_Exit)) { 
  85. ob_end_clean(); 
  86. self::print_exception($exception); 
  87.  
  88.  
  89. static function print_exception($exception) 
  90. $klass = get_class($exception); 
  91. echo "<h1>{$klass} thrown</h1>"; 
  92. echo "<p>{$exception->getMessage()}</p>"; 
  93. if (self::$debug OR (defined('NGG_DEBUG') AND NGG_DEBUG == TRUE)) { 
  94. echo "<h3>Where:</h3>"; 
  95. echo "<p>On line <strong>{$exception->getLine()}</strong> of <strong>{$exception->getFile()}</strong></p>"; 
  96. echo "<h3>Trace:</h3>"; 
  97. echo "<pre>{$exception->getTraceAsString()}</pre>"; 
  98. if (method_exists($exception, 'getPrevious')) { 
  99. if (($previous = $exception->getPrevious())) { 
  100. self::print_exception($previous); 
  101.  
  102. static function get_backtrace($objects=FALSE, $remove_dynamic_calls=TRUE) 
  103. $trace = debug_backtrace($objects); 
  104. if ($remove_dynamic_calls) { 
  105. $skip_methods = array( 
  106. '_exec_cached_method',  
  107. '__call',  
  108. 'get_method_property',  
  109. 'set_method_property',  
  110. 'call_method' 
  111. ); 
  112. foreach ($trace as $key => &$value) { 
  113. if (isset($value['class']) && isset($value['function'])) { 
  114. if ($value['class'] == 'ReflectionMethod' && $value['function'] == 'invokeArgs') 
  115. unset($trace[$key]); 
  116.  
  117. else if ($value['class'] == 'ExtensibleObject' && in_array($value['function'], $skip_methods)) 
  118. unset($trace[$key]); 
  119.  
  120. return $trace; 
  121.  
  122. function __construct() 
  123. set_exception_handler(__CLASS__.'::shutdown'); 
  124.  
  125. // We only load the plugin if we're outside of the activation request, loaded in an iframe 
  126. // by WordPress. Reason being, if WP_DEBUG is enabled, and another Pope-based plugin (such as 
  127. // the photocrati theme or NextGEN Pro/Plus), then PHP will output strict warnings 
  128. if ($this->is_not_activating()) { 
  129. $this->_define_constants(); 
  130. $this->_load_non_pope(); 
  131. $this->_register_hooks(); 
  132. $this->_load_pope(); 
  133.  
  134. function is_not_activating() 
  135. return !$this->is_activating(); 
  136.  
  137. function is_activating() 
  138. $retval = strpos($_SERVER['REQUEST_URI'], 'plugins.php') !== FALSE && isset($_REQUEST['action']) && in_array($_REQUEST['action'], array('activate-selected')); 
  139.  
  140. if (!$retval && strpos($_SERVER['REQUEST_URI'], 'update.php') !== FALSE && isset($_REQUEST['action']) && $_REQUEST['action'] == 'install-plugin' && isset($_REQUEST['plugin']) && strpos($_REQUEST['plugin'], 'nextgen-gallery') === 0) { 
  141. $retval = TRUE; 
  142.  
  143. if (!$retval && strpos($_SERVER['REQUEST_URI'], 'update.php') !== FALSE && isset($_REQUEST['action']) && $_REQUEST['action'] == 'activate-plugin' && isset($_REQUEST['plugin']) && strpos($_REQUEST['plugin'], 'nextgen-gallery') === 0) { 
  144. $retval = TRUE; 
  145.  
  146. return $retval; 
  147.  
  148. function _load_non_pope() 
  149. // Load caching component 
  150. include_once('non_pope/class.photocrati_transient_manager.php'); 
  151.  
  152. if (isset($_REQUEST['ngg_flush']) OR isset($_REQUEST['ngg_flush_expired'])) { 
  153. C_Photocrati_Transient_Manager::flush(); 
  154. die("Flushed all caches"); 
  155.  
  156. // Load Settings Manager 
  157. include_once('non_pope/class.photocrati_settings_manager.php'); 
  158. include_once('non_pope/class.nextgen_settings.php'); 
  159. C_Photocrati_Global_Settings_Manager::$option_name = $this->_settings_option_name; 
  160. C_Photocrati_Settings_Manager::$option_name = $this->_settings_option_name; 
  161.  
  162. // Load the installer 
  163. include_once('non_pope/class.photocrati_installer.php'); 
  164.  
  165. // Load the resource manager 
  166. include_once('non_pope/class.photocrati_resource_manager.php'); 
  167. C_Photocrati_Resource_Manager::init(); 
  168.  
  169. // Load the style manager 
  170. include_once('non_pope/class.nextgen_style_manager.php'); 
  171.  
  172. // Load the shortcode manager 
  173. include_once('non_pope/class.nextgen_shortcode_manager.php'); 
  174. C_NextGen_Shortcode_Manager::get_instance(); 
  175.  
  176. function fix_loading_order() 
  177. // If a plugin wasn't activated/deactivated siliently, we can listen for these things 
  178. if (did_action('activate_plugin') || did_action('deactivate_plugin')) return; 
  179. else if (strpos($_SERVER['REQUEST_URI'], 'plugins') !== FALSE) return; 
  180. else if (!$this->is_page_request()) return; 
  181.  
  182. $plugins = get_option('active_plugins'); 
  183.  
  184. // Remove NGG from the list 
  185. $ngg = basename(dirname(__FILE__)).'/'.basename(__FILE__); 
  186. $order = array(); 
  187. foreach ($plugins as $plugin) { 
  188. if ($plugin != $ngg) $order[] = $plugin; 
  189.  
  190.  
  191. // Get the position of either NGG Pro or NGG Plus 
  192. $insert_at = FALSE; 
  193. for($i=0; $i<count($order); $i++) { 
  194. $plugin = $order[$i]; 
  195. if (strpos($plugin, 'nggallery-pro') !== FALSE) $insert_at = $i+1; 
  196. else if (strpos($plugin, 'ngg-plus') !== FALSE) $insert_at = $i+1; 
  197.  
  198. // Re-insert NGG after Pro or Plus 
  199. if ($insert_at === FALSE || $insert_at === count($order)) $order[] = $ngg; 
  200. elseif ($insert_at === 0) array_unshift($order, $ngg); 
  201. else array_splice($order, $insert_at, 0, array($ngg)); 
  202.  
  203. if ($order != $plugins) { 
  204. $order = array_filter($order); 
  205. update_option('active_plugins', $order); 
  206.  
  207. /** 
  208. * Loads the Pope Framework 
  209. */ 
  210. function _load_pope() 
  211. // No need to initialize pope again 
  212. if ($this->_pope_loaded) return; 
  213.  
  214. // Pope requires a a higher limit 
  215. $tmp = ini_get('xdebug.max_nesting_level'); 
  216. if ($tmp && (int)$tmp <= 300) @ini_set('xdebug.max_nesting_level', 300); 
  217.  
  218. // Include pope framework 
  219. require_once(implode( 
  220. DIRECTORY_SEPARATOR, array(NGG_PLUGIN_DIR, 'pope', 'lib', 'autoload.php') 
  221. )); 
  222.  
  223. // Enable/disable pope caching. For now, the pope cache will not be used in multisite environments 
  224. if (class_exists('C_Pope_Cache')) { 
  225. if ((C_Pope_Cache::$enabled = NGG_POPE_CACHE)) { 
  226. $blogid = (is_multisite() ? get_current_blog_id() : NULL); 
  227. if (isset($_SERVER['SERVER_ADDR'])) 
  228. $cache_key_prefix = abs(crc32((implode('|', array($blogid, site_url(), AUTH_KEY, $_SERVER['SERVER_ADDR']))))); 
  229. else 
  230. $cache_key_prefix = abs(crc32(implode('|', array($blogid, site_url(), AUTH_KEY)))); 
  231.  
  232. C_Pope_Cache::set_driver('C_Pope_Cache_SingleFile'); 
  233. C_Pope_Cache::add_key_prefix($cache_key_prefix); 
  234.  
  235. // Enforce interfaces 
  236. if (property_exists('ExtensibleObject', 'enforce_interfaces')) ExtensibleObject::$enforce_interfaces = EXTENSIBLE_OBJECT_ENFORCE_INTERFACES; 
  237.  
  238. // Get the component registry 
  239. $this->_registry = C_Component_Registry::get_instance(); 
  240.  
  241. // Add the default Pope factory utility, C_Component_Factory 
  242. $this->_registry->add_utility('I_Component_Factory', 'C_Component_Factory'); 
  243.  
  244. // Blacklist any modules which are known NOT to work with this version of NextGEN Gallery 
  245. // We need to check if we have this ability as it's only available with Pope 0.9 
  246. if (method_exists($this->_registry, 'blacklist_module_file')) { 
  247. $this->_registry->blacklist_module_file('module.nextgen_pro_lightbox_legacy.php'); 
  248. $this->_registry->blacklist_module_file('module.protect_image.php'); 
  249. // TODO: Add module id for protect image 
  250.  
  251. // If Pro is incompatible, then we need to blacklist all of Pro's modules 
  252. // TODO: Pope needs a better way of introspecting into a product's list of provided modules 
  253. if ($this->is_pro_incompatible()) { 
  254. $pro_modules = array( 
  255. 'photocrati-comments',  
  256. 'photocrati-galleria',  
  257. 'photocrati-nextgen_pro_slideshow',  
  258. 'photocrati-nextgen_pro_horizontal_filmstrip',  
  259. 'photocrati-nextgen_pro_thumbnail_grid',  
  260. 'photocrati-nextgen_pro_blog_gallery',  
  261. 'photocrati-nextgen_pro_film',  
  262. 'photocrati-nextgen_pro_masonry',  
  263. 'photocrati-nextgen_pro_albums',  
  264. 'photocrati-nextgen_pro_lightbox',  
  265. 'photocrati-nextgen_pro_lightbox_legacy',  
  266. 'photocrati-nextgen_pro_ecommerce',  
  267. 'photocrati-paypal_express_checkout',  
  268. 'photocrati-paypal_standard',  
  269. 'photocrati-stripe' 
  270. ); 
  271. foreach ($pro_modules as $mod) $this->_registry->blacklist_module_file($mod); 
  272.  
  273. // Load embedded products. Each product is expected to load any 
  274. // modules required 
  275. $this->_registry->add_module_path(NGG_PRODUCT_DIR, 2, false); 
  276. $this->_registry->load_all_products(); 
  277.  
  278. // Give third-party plugins that opportunity to include their own products 
  279. // and modules 
  280. do_action('load_nextgen_gallery_modules', $this->_registry); 
  281.  
  282. // Initializes all loaded modules 
  283. $this->_registry->initialize_all_modules(); 
  284.  
  285. $this->_pope_loaded = TRUE; 
  286.  
  287. function is_pro_compatible() 
  288. $retval = TRUE; 
  289.  
  290. if (defined('NEXTGEN_GALLERY_PRO_VERSION')) $retval = FALSE; 
  291. if (defined('NEXTGEN_GALLERY_PRO_PLUGIN_BASENAME') && !defined('NGG_PRO_PLUGIN_VERSION')) $retval = FALSE; // 1.0 - 1.0.6 
  292. if (defined('NGG_PRO_PLUGIN_VERSION') && version_compare(NGG_PRO_PLUGIN_VERSION, $this->minimum_ngg_pro_version) < 0) $retval = FALSE; 
  293. if (defined('NGG_PLUS_PLUGIN_VERSION') && version_compare(NGG_PLUS_PLUGIN_VERSION, $this->minimum_ngg_plus_version) < 0) $retval = FALSE; 
  294.  
  295. return $retval; 
  296.  
  297. function is_pro_incompatible() 
  298. return !$this->is_pro_compatible(); 
  299.  
  300. function render_incompatibility_warning() 
  301. echo '<div class="updated error"><p>'; 
  302. echo esc_html( 
  303. sprintf( 
  304. __("NextGEN Gallery %s is incompatible with this version of NextGEN Pro. Please update NextGEN Pro to version %s or higher to restore NextGEN Pro functionality.",  
  305. 'nggallery' 
  306. ),  
  307. NGG_PLUGIN_VERSION, $this->minimum_ngg_pro_version 
  308. )); 
  309. echo '</p></div>'; 
  310.  
  311.  
  312. /** 
  313. * Registers hooks for the WordPress framework necessary for instantiating 
  314. * the plugin 
  315. */ 
  316. function _register_hooks() 
  317. // Register the deactivation routines 
  318. add_action('deactivate_'.NGG_PLUGIN_BASENAME, array(get_class(), 'deactivate')); 
  319.  
  320. // Register our test suite 
  321. add_filter('simpletest_suites', array(&$this, 'add_testsuite')); 
  322.  
  323. // Ensure that settings manager is saved as an array 
  324. add_filter('pre_update_option_'.$this->_settings_option_name, array(&$this, 'persist_settings')); 
  325. add_filter('pre_update_site_option_'.$this->_settings_option_name, array(&$this, 'persist_settings')); 
  326.  
  327. // This plugin uses jQuery extensively 
  328. if (NGG_FIX_JQUERY) { 
  329. add_action('wp_enqueue_scripts', array(&$this, 'fix_jquery')); 
  330. add_action('wp_print_scripts', array(&$this, 'fix_jquery')); 
  331.  
  332. // If the selected stylesheet is using an unsafe path, then notify the user 
  333. add_action('all_admin_notices', array(&$this, 'display_stylesheet_notice')); 
  334.  
  335. // Delete displayed gallery transients periodically 
  336. if (NGG_CRON_ENABLED) { 
  337. add_filter('cron_schedules', array(&$this, 'add_ngg_schedule')); 
  338. add_action('ngg_delete_expired_transients', array(&$this, 'delete_expired_transients')); 
  339. add_action('wp', array(&$this, 'schedule_cron_jobs')); 
  340.  
  341. // Update modules 
  342. add_action('init', array(&$this, 'update'), PHP_INT_MAX-2); 
  343.  
  344. // Start the plugin! 
  345. add_action('init', array(&$this, 'route'), 11); 
  346.  
  347. // Flush pope cache 
  348. add_action('init', array(&$this, 'flush_pope_cache')); 
  349.  
  350. // NGG extension plugins should be loaded in a specific order 
  351. add_action('shutdown', array(&$this, 'fix_loading_order')); 
  352.  
  353. // Display a warning if an compatible version of NextGEN Pro is installed alongside this 
  354. // version of NextGEN Gallery 
  355. if ($this->is_pro_incompatible()) { 
  356. add_filter('http_request_args', array(&$this, 'fix_autoupdate_api_requests'), 10, 2); 
  357. add_action('all_admin_notices', array(&$this, 'render_incompatibility_warning')); 
  358.  
  359. add_filter('ngg_load_frontend_logic', array($this, 'disable_frontend_logic'), -10, 2); 
  360.  
  361. function disable_frontend_logic($enabled, $module_id) 
  362. if (is_admin()) 
  363. $settings = C_NextGen_Settings::get_instance(); 
  364. if (!$settings->get('always_enable_frontend_logic')) 
  365. $enabled = FALSE; 
  366. return $enabled; 
  367.  
  368. function fix_autoupdate_api_requests($args, $url) 
  369. // Is this an HTTP request to the licensing server? 
  370. if (preg_match("/api_act=/", $url)) { 
  371. $args['autoupdate'] = TRUE; 
  372.  
  373. // If we're supposed to pass all Pro modules, then include them here 
  374. if (preg_match("/api_act=(ckups|cklic)/", $url) && isset($args['body']) && is_array($args['body']) && isset($args['body']['module-list'])) { 
  375. $pro_modules = array( 
  376. 'photocrati-comments',  
  377. 'photocrati-galleria',  
  378. 'photocrati-nextgen_pro_slideshow',  
  379. 'photocrati-nextgen_pro_horizontal_filmstrip',  
  380. 'photocrati-nextgen_pro_thumbnail_grid',  
  381. 'photocrati-nextgen_pro_blog_gallery',  
  382. 'photocrati-nextgen_pro_film',  
  383. 'photocrati-nextgen_pro_masonry',  
  384. 'photocrati-nextgen_pro_albums',  
  385. 'photocrati-auto_update',  
  386. 'photocrati-auto_update-admin',  
  387. 'photocrati-nextgen_pro_lightbox',  
  388. 'photocrati-nextgen_pro_lightbox_legacy',  
  389. 'photocrati-nextgen_pro_ecommerce',  
  390. 'photocrati-paypal_express_checkout',  
  391. 'photocrati-paypal_standard',  
  392. 'photocrati-stripe' 
  393. ); 
  394. foreach ($pro_modules as $mod) { 
  395. if (!isset($args['body']['module-list'][$mod])) $args['body']['module-list'][$mod] = '0.1'; 
  396. return $args; 
  397.  
  398. function flush_pope_cache() 
  399. if (is_user_logged_in() && current_user_can('manage_options') && isset($_REQUEST['ngg_flush_pope_cache'])) { 
  400. C_Pope_Cache::get_instance()->flush(); 
  401. print "Flushed pope cache"; 
  402. exit; 
  403.  
  404. function schedule_cron_jobs() 
  405. if (!wp_next_scheduled('ngg_delete_expired_transients')) { 
  406. wp_schedule_event(time(), 'ngg_custom', 'ngg_delete_expired_transients'); 
  407.  
  408. /** 
  409. * Defines a new cron schedule 
  410. * @param $schedules 
  411. * @return mixed 
  412. */ 
  413. function add_ngg_schedule($schedules) 
  414. $schedules['ngg_custom'] = array( 
  415. 'interval' => NGG_CRON_SCHEDULE,  
  416. 'display' => sprintf(__('Every %d seconds', 'nggallery'), NGG_CRON_SCHEDULE) 
  417. ); 
  418.  
  419. return $schedules; 
  420.  
  421.  
  422. /** 
  423. * Flush all expires transients created by the plugin 
  424. */ 
  425. function delete_expired_transients() 
  426. C_Photocrati_Transient_Manager::flush(); 
  427.  
  428. /** 
  429. * Ensure that C_Photocrati_Settings_Manager gets persisted as an array 
  430. * @param $settings 
  431. * @return array 
  432. */ 
  433. function persist_settings($settings) 
  434. if (is_object($settings) && $settings instanceof C_Photocrati_Settings_Manager_Base) { 
  435. $settings = $settings->to_array(); 
  436. return $settings; 
  437.  
  438. /** 
  439. * Ensures that the version of JQuery used is expected for NextGEN Gallery 
  440. */ 
  441. function fix_jquery() 
  442. global $wp_scripts; 
  443.  
  444. // Determine which version of jQuery to include 
  445. $src = '/wp-includes/js/jquery/jquery.js'; 
  446.  
  447. // Ensure that jQuery is always set to the default 
  448. if (isset($wp_scripts->registered['jquery'])) { 
  449. $jquery = $wp_scripts->registered['jquery']; 
  450.  
  451. // There's an exception to the rule. We'll allow the same 
  452. // version of jQuery as included with WP to be fetched from 
  453. // Google AJAX libraries, as we have a systematic means of verifying 
  454. // that won't cause any troubles 
  455. $version = preg_quote($jquery->ver, '#'); 
  456. if (!preg_match("#ajax\\.googleapis\\.com/ajax/libs/jquery/{$version}/jquery\\.min\\.js#", $jquery->src)) { 
  457. $jquery->src = FALSE; 
  458. if (array_search('jquery-core', $jquery->deps) === FALSE) { 
  459. $jquery->deps[] = 'jquery-core'; 
  460. if (array_search('jquery-migrate', $jquery->deps) === FALSE) { 
  461. $jquery->deps[] = 'jquery-migrate'; 
  462.  
  463. // Ensure that jquery-core is used, as WP intended 
  464. if (isset($wp_scripts->registered['jquery-core'])) { 
  465. $wp_scripts->registered['jquery-core']->src = $src; 
  466.  
  467. wp_enqueue_script('jquery'); 
  468.  
  469. /** 
  470. * Displays a notice to the user that the current stylesheet location is unsafe 
  471. */ 
  472. function display_stylesheet_notice() 
  473. if (C_NextGen_Style_Manager::get_instance()->is_directory_unsafe()) { 
  474. $styles = C_NextGen_Style_Manager::get_instance(); 
  475. $filename = $styles->get_selected_stylesheet(); 
  476. $abspath = $styles->find_selected_stylesheet_abspath(); 
  477. $newpath = $styles->new_dir; 
  478.  
  479. echo "<div class='updated error'> 
  480. <h3>WARNING: NextGEN Gallery Stylesheet NOT Upgrade-safe</h3> 
  481. <p> 
  482. <strong>{$filename}</strong> is currently stored in <strong>{$abspath}</strong>, which isn't upgrade-safe. Please move the stylesheet to 
  483. <strong>{$newpath}</strong> to ensure that your customizations persist after updates. 
  484. </p></div>"; 
  485.  
  486. /** 
  487. * Updates all modules 
  488. */ 
  489. function update() 
  490. if ((!(defined('DOING_AJAX') && DOING_AJAX)) && !isset($_REQUEST['doing_wp_cron'])) { 
  491.  
  492. $this->_load_pope(); 
  493.  
  494. // Try updating all modules 
  495. C_Photocrati_Installer::update(); 
  496.  
  497. /** 
  498. * Routes access points using the Pope Router 
  499. * @return boolean 
  500. */ 
  501. function route() 
  502. $this->_load_pope(); 
  503. $router = C_Router::get_instance(); 
  504.  
  505. // Set context to path if subdirectory install 
  506. $parts = parse_url($router->get_base_url(FALSE)); 
  507. if (isset($parts['path'])) { 
  508. $parts = explode('/index.php', $parts['path']); 
  509. $router->context = array_shift($parts); 
  510.  
  511. // Provide a means for modules/third-parties to configure routes 
  512. do_action_ref_array('ngg_routes', array(&$router)); 
  513.  
  514. // Serve the routes 
  515. if (!$router->serve_request() && $router->has_parameter_segments()) { 
  516. return $router->passthru(); 
  517.  
  518. function is_page_request() 
  519. return !(defined('DOING_AJAX') && DOING_AJAX) && !(defined('DOING_CRON') && DOING_CRON) && !(defined('NGG_AJAX_SLUG') && strpos($_SERVER['REQUEST_URI'], NGG_AJAX_SLUG) !== FALSE); 
  520.  
  521. /** 
  522. * Run the uninstaller 
  523. */ 
  524. static function deactivate() 
  525. include_once('products/photocrati_nextgen/class.nextgen_product_installer.php'); 
  526. C_Photocrati_Installer::add_handler(NGG_PLUGIN_BASENAME, 'C_NextGen_Product_Installer'); 
  527. C_Photocrati_Installer::uninstall(NGG_PLUGIN_BASENAME); 
  528.  
  529. /** 
  530. * Defines necessary plugins for the plugin to load correctly 
  531. */ 
  532. function _define_constants() 
  533. define('NGG_PLUGIN', basename($this->directory_path())); 
  534. define('NGG_PLUGIN_BASENAME', plugin_basename(__FILE__)); 
  535. define('NGG_PLUGIN_DIR', $this->directory_path()); 
  536. define('NGG_PLUGIN_URL', $this->path_uri()); 
  537. define('NGG_TESTS_DIR', implode(DIRECTORY_SEPARATOR, array(rtrim(NGG_PLUGIN_DIR, "/\\"), 'tests'))); 
  538. define('NGG_PRODUCT_DIR', implode(DIRECTORY_SEPARATOR, array(rtrim(NGG_PLUGIN_DIR, "/\\"), 'products'))); 
  539. define('NGG_MODULE_DIR', implode(DIRECTORY_SEPARATOR, array(rtrim(NGG_PRODUCT_DIR, "/\\"), 'photocrati_nextgen', 'modules'))); 
  540. define('NGG_PRODUCT_URL', path_join(str_replace("\\", '/', NGG_PLUGIN_URL), 'products')); 
  541. define('NGG_MODULE_URL', path_join(str_replace("\\", '/', NGG_PRODUCT_URL), 'photocrati_nextgen/modules')); 
  542. define('NGG_PLUGIN_STARTED_AT', microtime()); 
  543. define('NGG_PLUGIN_VERSION', '2.2.3'); 
  544.  
  545. if (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) 
  546. define('NGG_SCRIPT_VERSION', (string)mt_rand(0, mt_getrandmax())); 
  547. else 
  548. define('NGG_SCRIPT_VERSION', NGG_PLUGIN_VERSION); 
  549.  
  550. if (!defined('NGG_HIDE_STRICT_ERRORS')) { 
  551. define('NGG_HIDE_STRICT_ERRORS', TRUE); 
  552.  
  553. // Should we display E_STRICT errors? 
  554. if (NGG_HIDE_STRICT_ERRORS) { 
  555. $level = error_reporting(); 
  556. if ($level != 0) error_reporting($level & ~E_STRICT); 
  557.  
  558. // Should we display NGG debugging information? 
  559. if (!defined('NGG_DEBUG')) { 
  560. define('NGG_DEBUG', FALSE); 
  561. self::$debug = NGG_DEBUG; 
  562.  
  563. // User definable constants 
  564. if (!defined('NGG_IMPORT_ROOT')) { 
  565. $path = WP_CONTENT_DIR; 
  566. if (defined('NEXTGEN_GALLERY_IMPORT_ROOT')) { 
  567. $path = NEXTGEN_GALLERY_IMPORT_ROOT; 
  568. define('NGG_IMPORT_ROOT', $path); 
  569.  
  570. // Should the Photocrati cache be enabled 
  571. if (!defined('PHOTOCRATI_CACHE')) { 
  572. define('PHOTOCRATI_CACHE', TRUE); 
  573. if (!defined('PHOTOCRATI_CACHE_TTL')) { 
  574. define('PHOTOCRATI_CACHE_TTL', 1800); 
  575.  
  576. // Cron job 
  577. if (!defined('NGG_CRON_SCHEDULE')) { 
  578. define('NGG_CRON_SCHEDULE', 900); 
  579.  
  580. if (!defined('NGG_CRON_ENABLED')) { 
  581. define('NGG_CRON_ENABLED', TRUE); 
  582.  
  583. // Don't enforce interfaces 
  584. if (!defined('EXTENSIBLE_OBJECT_ENFORCE_INTERFACES')) { 
  585. define('EXTENSIBLE_OBJECT_ENFORCE_INTERFACES', FALSE); 
  586.  
  587. // Fix jquery 
  588. if (!defined('NGG_FIX_JQUERY')) { 
  589. define('NGG_FIX_JQUERY', TRUE); 
  590.  
  591. // Use Pope's new caching mechanism? 
  592. if (!defined('NGG_POPE_CACHE')) { 
  593. define('NGG_POPE_CACHE', FALSE); 
  594.  
  595. /** 
  596. * Defines the NextGEN Test Suite 
  597. * @param array $suites 
  598. * @return array 
  599. */ 
  600. function add_testsuite($suites=array()) 
  601. $tests_dir = NGG_TESTS_DIR; 
  602.  
  603. if (file_exists($tests_dir)) { 
  604.  
  605. // Include mock objects 
  606. // TODO: These mock objects should be moved to the appropriate 
  607. // test folder 
  608. require_once(path_join($tests_dir, 'mocks.php')); 
  609.  
  610. // Define the NextGEN Test Suite 
  611. $suites['nextgen'] = array( 
  612. // path_join($tests_dir, 'mvc'),  
  613. path_join($tests_dir, 'datamapper'),  
  614. path_join($tests_dir, 'nextgen_data'),  
  615. path_join($tests_dir, 'gallery_display') 
  616. ); 
  617.  
  618. return $suites; 
  619.  
  620.  
  621. /** 
  622. * Returns the path to a file within the plugin root folder 
  623. * @param type $file_name 
  624. * @return type 
  625. */ 
  626. function file_path($file_name=NULL) 
  627. $path = dirname(__FILE__); 
  628.  
  629. if ($file_name != null) 
  630. $path .= '/' . $file_name; 
  631.  
  632. return str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path); 
  633.  
  634.  
  635. /** 
  636. * Gets the directory path used by the plugin 
  637. * @return string 
  638. */ 
  639. function directory_path($dir=NULL) 
  640. return $this->file_path($dir); 
  641.  
  642.  
  643. /** 
  644. * Determines the location of the plugin - within a theme or plugin 
  645. * @return string 
  646. */ 
  647. function get_plugin_location() 
  648. $path = dirname(__FILE__); 
  649. $gallery_dir = strtolower($path); 
  650. $gallery_dir = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $gallery_dir); 
  651.  
  652. $theme_dir = strtolower(get_stylesheet_directory()); 
  653. $theme_dir = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $theme_dir); 
  654.  
  655. $plugin_dir = strtolower(WP_PLUGIN_DIR); 
  656. $plugin_dir = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $plugin_dir); 
  657.  
  658. $common_dir_theme = substr($gallery_dir, 0, strlen($theme_dir)); 
  659. $common_dir_plugin = substr($gallery_dir, 0, strlen($plugin_dir)); 
  660.  
  661. if ($common_dir_theme == $theme_dir) 
  662. return 'theme'; 
  663.  
  664. if ($common_dir_plugin == $plugin_dir) 
  665. return 'plugin'; 
  666.  
  667. $parent_dir = dirname($path); 
  668.  
  669. if (file_exists($parent_dir . DIRECTORY_SEPARATOR . 'style.css')) 
  670. return 'theme'; 
  671.  
  672. return 'plugin'; 
  673.  
  674.  
  675. /** 
  676. * Gets the URI for a particular path 
  677. * @param string $path 
  678. * @param boolean $url_encode 
  679. * @return string 
  680. */ 
  681. function path_uri($path = null, $url_encode = false) 
  682. $location = $this->get_plugin_location(); 
  683. $uri = null; 
  684.  
  685. $path = str_replace(array('/', '\\'), '/', $path); 
  686.  
  687. if ($url_encode) 
  688. $path_list = explode('/', $path); 
  689.  
  690. foreach ($path_list as $index => $path_item) 
  691. $path_list[$index] = urlencode($path_item); 
  692.  
  693. $path = implode('/', $path_list); 
  694.  
  695. if ($location == 'theme') 
  696. $theme_uri = get_stylesheet_directory_uri(); 
  697.  
  698. $uri = $theme_uri . 'nextgen-gallery'; 
  699.  
  700. if ($path != null) 
  701. $uri .= '/' . $path; 
  702. else 
  703. // XXX Note, paths could not match but STILL being contained in the theme (i.e. WordPress returns the wrong path for the theme directory, either with wrong formatting or wrong encoding) 
  704. $base = basename(dirname(__FILE__)); 
  705.  
  706. if ($base != 'nextgen-gallery') 
  707. // XXX this is needed when using symlinks, if the user renames the plugin folder everything will break though 
  708. $base = 'nextgen-gallery'; 
  709.  
  710. if ($path != null) 
  711. $base .= '/' . $path; 
  712.  
  713. $uri = plugins_url($base); 
  714.  
  715. return $uri; 
  716.  
  717. /** 
  718. * Returns the URI for a particular file 
  719. * @param string $file_name 
  720. * @return string 
  721. */ 
  722. function file_uri($file_name = NULL) 
  723. return $this->path($file_name); 
  724.  
  725. #region Freemius 
  726.  
  727. /** 
  728. * Customize the opt-in message. 
  729. * 
  730. * @author Vova Feldman (@svovaf) 
  731. * @since 2.1.32 
  732. * 
  733. * @param string $message 
  734. * @param string $user_first_name 
  735. * @param string $plugin_title 
  736. * @param string $user_login 
  737. * @param string $site_link 
  738. * @param string $freemius_link 
  739. * 
  740. * @return string 
  741. */ 
  742. function ngg_fs_custom_connect_message( 
  743. $message,  
  744. $user_first_name,  
  745. $plugin_title,  
  746. $user_login,  
  747. $site_link,  
  748. $freemius_link 
  749. ) { 
  750. return sprintf( 
  751. __fs( 'hey-x' ) . '<br>' . 
  752. __( 'Allow %6$s to collect some usage data with %5$s to make the plugin even more awesome. If you skip this, that\'s okay! %2$s will still work just fine.', 'nggallery' ),  
  753. $user_first_name,  
  754. '<b>' . __('NextGEN Gallery', 'nggallery') . '</b>',  
  755. '<b>' . $user_login . '</b>',  
  756. $site_link,  
  757. $freemius_link,  
  758. '<b>' . __('Imagely', 'nggallery') . '</b>' 
  759. ); 
  760.  
  761. /** 
  762. * Uninstall cleanup script. 
  763. */ 
  764. function ngg_fs_uninstall() { 
  765. // Your cleanup script. 
  766.  
  767. /** 
  768. * Send custom event about 1st gallery creation. 
  769. * 
  770. * @author Vova Feldman (@svovaf) 
  771. */ 
  772. function fs_track_new_gallery() { 
  773. global $ngg_fs; 
  774.  
  775. $galleries = C_Gallery_Mapper::get_instance()->count(); 
  776. if (1 == $galleries) { 
  777. // Only track event on 1st gallery creation. 
  778. $ngg_fs->track_event_once( 'new_gallery' ); 
  779.  
  780. /** 
  781. * Create a helper function for easy SDK access. 
  782. * 
  783. * @author Vova Feldman (@svovaf) 
  784. * @since 2.1.32 
  785. * 
  786. * @param bool $activate_for_all If true, activate Freemius for all users. Was added for testing. 
  787. * 
  788. * @return \Freemius 
  789. */ 
  790. function ngg_fs( $activate_for_all = false ) { 
  791. global $ngg_fs; 
  792.  
  793. if ( ! $activate_for_all ) { 
  794. $ngg_options = get_option( 'ngg_options' ); 
  795. $ngg_run_freemius = get_option( 'ngg_run_freemius', null ); 
  796.  
  797. if ( false === $ngg_options ) { 
  798. // New plugin installation. 
  799.  
  800. if ( defined( 'WP_FS__DEV_MODE' ) && WP_FS__DEV_MODE ) { 
  801. // Always run Freemius in development mode for new plugin installs. 
  802. $run_freemius = true; 
  803. } else { 
  804. // Run Freemius code on 20% of the new installations. 
  805. // $random = rand( 1, 10 ); 
  806. // $run_freemius = ( 1 <= $random && $random <= 2 ); 
  807. // Update 2016-08: run on all new instances 
  808. $run_freemius = TRUE; 
  809.  
  810. update_option( 'ngg_run_freemius', $run_freemius ); 
  811.  
  812. // Compare both bool or string 0/1 because get_option() may give us either 
  813. } else if ( ( is_bool( $ngg_run_freemius ) && $ngg_run_freemius ) || '1' === $ngg_run_freemius ) { 
  814. // If runFreemius was set, use the value. 
  815. $run_freemius = $ngg_run_freemius; 
  816. } else { 
  817. // Don't run Freemius for plugin updates. 
  818. $run_freemius = false; 
  819. if (is_null($ngg_run_freemius)) 
  820. update_option('ngg_run_freemius', FALSE); 
  821.  
  822. if ( ! $run_freemius ) { 
  823. return false; 
  824.  
  825. if ( ! isset( $ngg_fs ) ) { 
  826. // Include Freemius SDK. 
  827. require_once dirname( __FILE__ ) . '/freemius/start.php'; 
  828.  
  829. $ngg_fs = fs_dynamic_init( array( 
  830. 'id' => '266',  
  831. 'slug' => 'nextgen-gallery',  
  832. 'public_key' => 'pk_009356711cd548837f074e1ef60a4',  
  833. 'is_premium' => false,  
  834. 'has_addons' => false,  
  835. 'has_paid_plans' => false,  
  836. 'menu' => array( 
  837. 'slug' => 'nextgen-gallery',  
  838. 'account' => false,  
  839. 'contact' => false,  
  840. 'support' => false,  
  841. ),  
  842. 'permissions' => array( 
  843. 'newsletter' => true,  
  844. ),  
  845. ) ); 
  846.  
  847. /** 
  848. // Optional button override. 
  849. if ( function_exists( 'fs_override_i18n' ) ) { 
  850. fs_override_i18n( array( 
  851. 'opt-in-connect' => __('OK - I\'m in!', 'nggallery'),  
  852. ), 'nextgen-gallery' ); 
  853. } 
  854. */ 
  855.  
  856. // Hook to the custom message filter. 
  857. $ngg_fs->add_filter( 'connect_message', 'ngg_fs_custom_connect_message', 10, 6 ); 
  858. $ngg_fs->add_action( 'after_uninstall', 'ngg_fs_uninstall' ); 
  859.  
  860. // Hook to new gallery creation event. 
  861. add_action( 'ngg_created_new_gallery', 'fs_track_new_gallery' ); 
  862.  
  863. return $ngg_fs; 
  864.  
  865. // Init Freemius. 
  866. ngg_fs(); 
  867.  
  868. #endregion Freemius 
  869.  
  870. new C_NextGEN_Bootstrap(); 
.