/products/photocrati_nextgen/modules/nextgen_gallery_display/package.module.nextgen_gallery_display.php

  1. <?php 
  2. /** 
  3. * Class A_Display_Settings_Controller 
  4. * @mixin C_NextGen_Admin_Page_Controller 
  5. * @adapts I_NextGen_Admin_Page using "ngg_display_settings" context 
  6. */ 
  7. class A_Display_Settings_Controller extends Mixin 
  8. /** 
  9. * Static resources required for the Display Settings page 
  10. */ 
  11. function enqueue_backend_resources() 
  12. $this->call_parent('enqueue_backend_resources'); 
  13. wp_enqueue_style('nextgen_gallery_display_settings'); 
  14. wp_enqueue_script('nextgen_gallery_display_settings'); 
  15. function get_page_title() 
  16. return __('Gallery Settings', 'nggallery'); 
  17. function get_required_permission() 
  18. return 'NextGEN Change options'; 
  19. /** 
  20. * Class A_Display_Settings_Page 
  21. * @mixin C_Page_Manager 
  22. * @adapts I_Page_Manager 
  23. */ 
  24. class A_Display_Settings_Page extends Mixin 
  25. function setup() 
  26. $this->object->add(NGG_DISPLAY_SETTINGS_SLUG, array('adapter' => 'A_Display_Settings_Controller', 'parent' => NGGFOLDER, 'before' => 'ngg_other_options')); 
  27. return $this->call_parent('setup'); 
  28. /** 
  29. * Class A_Displayed_Gallery_Trigger_Element 
  30. * @mixin C_MVC_View 
  31. * @adapts I_MVC_View 
  32. */ 
  33. class A_Displayed_Gallery_Trigger_Element extends Mixin 
  34. function render_object() 
  35. $root_element = $this->call_parent('render_object'); 
  36. if (($displayed_gallery = $this->object->get_param('displayed_gallery')) && $this->object->get_param('display_type_rendering')) { 
  37. $triggers = C_Displayed_Gallery_Trigger_Manager::get_instance(); 
  38. $triggers->render($root_element, $displayed_gallery); 
  39. return $root_element; 
  40. /** 
  41. * Class A_Displayed_Gallery_Trigger_Resources 
  42. * @mixin C_Display_Type_Controller 
  43. * @adapts I_Display_Type_Controller 
  44. */ 
  45. class A_Displayed_Gallery_Trigger_Resources extends Mixin 
  46. protected $run_once = FALSE; 
  47. function enqueue_frontend_resources($displayed_gallery) 
  48. $this->call_parent('enqueue_frontend_resources', $displayed_gallery); 
  49. return $this->enqueue_displayed_gallery_trigger_buttons_resources($displayed_gallery); 
  50. function enqueue_displayed_gallery_trigger_buttons_resources($displayed_gallery = FALSE) 
  51. $retval = FALSE; 
  52. M_Gallery_Display::enqueue_fontawesome(); 
  53. if (!$this->run_once && !empty($displayed_gallery) && !empty($displayed_gallery->display_settings['ngg_triggers_display']) && $displayed_gallery->display_settings['ngg_triggers_display'] !== 'never') { 
  54. $pro_active = FALSE; 
  55. if (defined('NGG_PRO_PLUGIN_VERSION')) { 
  56. $pro_active = 'NGG_PRO_PLUGIN_VERSION'; 
  57. if (defined('NEXTGEN_GALLERY_PRO_VERSION')) { 
  58. $pro_active = 'NEXTGEN_GALLERY_PRO_VERSION'; 
  59. if (!empty($pro_active)) { 
  60. $pro_active = constant($pro_active); 
  61. if (!is_admin() && (empty($pro_active) || version_compare($pro_active, '1.0.11') >= 0)) { 
  62. wp_enqueue_style('fontawesome'); 
  63. $retval = TRUE; 
  64. $this->run_once = TRUE; 
  65. return $retval; 
  66. /** 
  67. * Class A_Gallery_Display_Factory 
  68. * @mixin C_Component_Factory 
  69. * @adapts I_Component_Factory 
  70. */ 
  71. class A_Gallery_Display_Factory extends Mixin 
  72. /** 
  73. * Instantiates a Display Type 
  74. * @param C_DataMapper $mapper 
  75. * @param array|stdClass|C_DataMapper_Model $properties 
  76. * @param string|array|FALSE $context 
  77. */ 
  78. function display_type($properties = array(), $mapper = FALSE, $context = FALSE) 
  79. return new C_Display_Type($properties, $mapper, $context); 
  80. /** 
  81. * Instantiates a Displayed Gallery 
  82. * @param C_DataMapper $mapper 
  83. * @param array|stdClass|C_DataMapper_Model $properties 
  84. * @param string|array|FALSE $context 
  85. */ 
  86. function displayed_gallery($properties = array(), $mapper = FALSE, $context = FALSE) 
  87. return new C_Displayed_Gallery($properties, $mapper, $context); 
  88. /** 
  89. * Class A_Gallery_Display_View 
  90. * @mixin C_MVC_View 
  91. * @adapts I_MVC_View 
  92. */ 
  93. class A_Gallery_Display_View extends Mixin 
  94. /** 
  95. * Check whether to render certain kinds of extra additions to the view for a displayed gallery 
  96. * @param object $displayed_gallery 
  97. * @param string $template_id 
  98. * @param C_MVC_View_Element $root_element 
  99. * @param string $addition_type what kind of addition is being made 'layout', 'decoration', 'style', 'logic' etc. 
  100. * @return string|NULL 
  101. */ 
  102. function _check_addition_rendering($displayed_gallery, $template_id, $root_element, $addition_type) 
  103. $view = $root_element->get_object(); 
  104. $mode = $view->get_param('render_mode'); 
  105. $ret = true; 
  106. switch ($addition_type) { 
  107. case 'layout': 
  108. $ret = !in_array($mode, array('bare', 'basic')); 
  109. break; 
  110. case 'decoration': 
  111. break; 
  112. case 'style': 
  113. break; 
  114. case 'logic': 
  115. break; 
  116. return $ret; 
  117. /** 
  118. * A Display Type is a component which renders a collection of images 
  119. * in a "gallery". 
  120. * 
  121. * Properties: 
  122. * - entity_types (gallery, album) 
  123. * - name (nextgen_basic-thumbnails) 
  124. * - title (NextGEN Basic Thumbnails) 
  125. * - aliases [basic_thumbnail, basic_thumbnails] 
  126. * 
  127. * @mixin Mixin_Display_Type_Validation 
  128. * @mixin Mixin_Display_Type_Instance_Methods 
  129. * @implements I_Display_Type 
  130. */ 
  131. class C_Display_Type extends C_DataMapper_Model 
  132. var $_mapper_interface = 'I_Display_Type_Mapper'; 
  133. function define($properties = array(), $mapper = FALSE, $context = FALSE) 
  134. parent::define($mapper, $properties, $context); 
  135. $this->add_mixin('Mixin_Display_Type_Validation'); 
  136. $this->add_mixin('Mixin_Display_Type_Instance_Methods'); 
  137. $this->implement('I_Display_Type'); 
  138. /** 
  139. * Initializes a display type with properties 
  140. * @param FALSE|C_Display_Type_Mapper $mapper 
  141. * @param array|stdClass|C_Display_Type $properties 
  142. * @param FALSE|string|array $context 
  143. */ 
  144. function initialize($properties = array(), $mapper = FALSE, $context = FALSE) 
  145. // If no mapper was specified, then get the mapper 
  146. if (!$mapper) { 
  147. $mapper = $this->get_registry()->get_utility($this->_mapper_interface); 
  148. // Construct the model 
  149. parent::initialize($mapper, $properties); 
  150. /** 
  151. * Allows a setting to be retrieved directly, rather than through the 
  152. * settings property 
  153. * @param string $property 
  154. * @return mixed 
  155. */ 
  156. function &__get($property) 
  157. if (isset($this->settings) && isset($this->settings[$property])) { 
  158. $retval =& $this->settings[$property]; 
  159. return $retval; 
  160. } else { 
  161. return parent::__get($property); 
  162. class Mixin_Display_Type_Validation extends Mixin 
  163. function validation() 
  164. $this->object->validates_presence_of('entity_types'); 
  165. $this->object->validates_presence_of('name'); 
  166. $this->object->validates_presence_of('title'); 
  167. return $this->object->is_valid(); 
  168. /** 
  169. * Provides methods available for class instances 
  170. */ 
  171. class Mixin_Display_Type_Instance_Methods extends Mixin 
  172. /** 
  173. * Determines if this display type is compatible with a displayed gallery 
  174. * source 
  175. * @param stdClass 
  176. * @return bool 
  177. */ 
  178. function is_compatible_with_source($source) 
  179. return C_Displayed_Gallery_Source_Manager::get_instance()->is_compatible($source, $this); 
  180. function get_order() 
  181. return NGG_DISPLAY_PRIORITY_BASE; 
  182. /** 
  183. * A Controller which displays the settings form for the display type, as 
  184. * well as the front-end display 
  185. */ 
  186. /** 
  187. * Class C_Display_Type_Controller 
  188. * @mixin Mixin_Display_Type_Controller 
  189. * @implements I_Display_Type_Controller 
  190. */ 
  191. class C_Display_Type_Controller extends C_MVC_Controller 
  192. static $_instances = array(); 
  193. function define($context = FALSE) 
  194. parent::define($context); 
  195. $this->add_mixin('Mixin_Display_Type_Controller'); 
  196. $this->implement('I_Display_Type_Controller'); 
  197. /** 
  198. * Gets a singleton of the mapper 
  199. * @param string|array $context 
  200. * @return C_Display_Type_Controller 
  201. */ 
  202. public static function get_instance($context = FALSE) 
  203. if (!isset(self::$_instances[$context])) { 
  204. self::$_instances[$context] = new C_Display_Type_Controller($context); 
  205. return self::$_instances[$context]; 
  206. /** 
  207. * Provides instance methods for the C_Display_Type_Controller class 
  208. */ 
  209. class Mixin_Display_Type_Controller extends Mixin 
  210. var $_render_mode; 
  211. /** 
  212. * Enqueues static resources required for lightbox effects 
  213. * @param type $displayed_gallery 
  214. */ 
  215. function enqueue_lightbox_resources($displayed_gallery) 
  216. C_Lightbox_Library_Manager::get_instance()->enqueue(); 
  217. function is_cachable() 
  218. return TRUE; 
  219. /** 
  220. * This method should be overwritten by other adapters/mixins, and call 
  221. * wp_enqueue_script() / wp_enqueue_style() 
  222. */ 
  223. function enqueue_frontend_resources($displayed_gallery) 
  224. // This script provides common JavaScript among all display types 
  225. wp_enqueue_script('ngg_common'); 
  226. // Enqueue the display type library 
  227. wp_enqueue_script($displayed_gallery->display_type, $this->object->_get_js_lib_url($displayed_gallery), FALSE, NGG_SCRIPT_VERSION); 
  228. // Add "galleries = {};" 
  229. $this->object->_add_script_data('ngg_common', 'galleries', new stdClass(), TRUE, FALSE); 
  230. // Add "galleries.gallery_1 = {};" 
  231. $this->object->_add_script_data('ngg_common', 'galleries.gallery_' . $displayed_gallery->id(), (array) $displayed_gallery->get_entity(), FALSE); 
  232. $this->object->_add_script_data('ngg_common', 'galleries.gallery_' . $displayed_gallery->id() . '.wordpress_page_root', get_permalink(), FALSE); 
  233. // Enqueue trigger button resources 
  234. C_Displayed_Gallery_Trigger_Manager::get_instance()->enqueue_resources($displayed_gallery); 
  235. // Enqueue lightbox library 
  236. $this->object->enqueue_lightbox_resources($displayed_gallery); 
  237. function enqueue_ngg_styles() 
  238. $settings = C_NextGen_Settings::get_instance(); 
  239. if ((!is_multisite() || is_multisite() && $settings->wpmuStyle) && $settings->activateCSS) { 
  240. wp_enqueue_style('nggallery', C_NextGen_Style_Manager::get_instance()->get_selected_stylesheet_url(), FALSE, NGG_SCRIPT_VERSION); 
  241. function get_render_mode() 
  242. return $this->object->_render_mode; 
  243. function set_render_mode($mode) 
  244. $this->object->_render_mode = $mode; 
  245. /** 
  246. * Ensures that the minimum configuration of parameters are sent to a view 
  247. * @param $displayed_gallery 
  248. * @param null $params 
  249. * @return array|null 
  250. */ 
  251. function prepare_display_parameters($displayed_gallery, $params = null) 
  252. if ($params == null) { 
  253. $params = array(); 
  254. $params['display_type_rendering'] = true; 
  255. $params['displayed_gallery'] = $displayed_gallery; 
  256. $params['render_mode'] = $this->object->get_render_mode(); 
  257. return $params; 
  258. /** 
  259. * Renders the frontend display of the display type 
  260. */ 
  261. function index_action($displayed_gallery, $return = FALSE) 
  262. return $this->object->render_partial('photocrati-nextgen_gallery_display#index', array(), $return); 
  263. /** 
  264. * Returns the url for the JavaScript library required 
  265. * @return null|string 
  266. */ 
  267. function _get_js_lib_url() 
  268. return NULL; 
  269. function does_lightbox_support_displayed_gallery($displayed_gallery, $lightbox = NULL) 
  270. if (!$lightbox) { 
  271. $lightbox = C_Lightbox_Library_Manager::get_instance()->get_selected(); 
  272. $retval = FALSE; 
  273. if ($lightbox) { 
  274. // HANDLE COMPATIBILITY BREAK 
  275. // In NGG 2.1.48 and earlier, lightboxes were stdClass objects, and it was assumed 
  276. // that they only supported galleries that contained images, not albums that contained galleries. 
  277. // After NGG 2.1.48, lightboxes are now C_NGG_Lightbox instances which have a 'is_supported()' method 
  278. // to test if the lightbox can work with the displayed gallery settings 
  279. if (get_class($lightbox) == 'stdClass') { 
  280. $retval = !in_array($displayed_gallery->source, array('album', 'albums')); 
  281. } else { 
  282. $retval = $lightbox->is_supported($displayed_gallery); 
  283. return $retval; 
  284. /** 
  285. * Returns the effect HTML code for the displayed gallery 
  286. * @param type $displayed_gallery 
  287. */ 
  288. function get_effect_code($displayed_gallery) 
  289. $retval = ''; 
  290. if ($lightbox = C_Lightbox_Library_Manager::get_instance()->get_selected()) { 
  291. if ($this->does_lightbox_support_displayed_gallery($displayed_gallery, $lightbox)) { 
  292. $retval = $lightbox->code; 
  293. $retval = str_replace('%GALLERY_ID%', $displayed_gallery->id(), $retval); 
  294. $retval = str_replace('%GALLERY_NAME%', $displayed_gallery->id(), $retval); 
  295. global $post; 
  296. if ($post && isset($post->ID) && $post->ID) { 
  297. $retval = str_replace('%PAGE_ID%', $post->ID, $retval); 
  298. // allow for customization 
  299. $retval = apply_filters('ngg_effect_code', $retval, $displayed_gallery); 
  300. return $retval; 
  301. /** 
  302. * Adds data to the DOM which is then accessible by a script 
  303. * @param string $handle 
  304. * @param string $object_name 
  305. * @param mixed $object_value 
  306. * @param bool $define 
  307. */ 
  308. function _add_script_data($handle, $object_name, $object_value, $define = TRUE, $override = FALSE) 
  309. $retval = FALSE; 
  310. // wp_localize_script allows you to add data to the DOM, associated 
  311. // with a particular script. You can even call wp_localize_script 
  312. // multiple times to add multiple objects to the DOM. However, there 
  313. // are a few problems with wp_localize_script: 
  314. // 
  315. // - If you call it with the same object_name more than once, you're 
  316. // overwritting the first call. 
  317. // - You cannot namespace your objects due to the "var" keyword always 
  318. // - being used. 
  319. // 
  320. // To circumvent the above issues, we're going to use the WP_Scripts 
  321. // object to workaround the above issues 
  322. global $wp_scripts; 
  323. // Has the script been registered or enqueued yet? 
  324. if (isset($wp_scripts->registered[$handle])) { 
  325. // Get the associated data with this script 
  326. $script =& $wp_scripts->registered[$handle]; 
  327. $data = isset($script->extra['data']) ? $script->extra['data'] : ''; 
  328. // Construct the addition 
  329. $addition = $define ? "\nvar {$object_name} = " . json_encode($object_value) . ';' : "\n{$object_name} = " . json_encode($object_value) . ';'; 
  330. // Add the addition 
  331. if ($override) { 
  332. $data .= $addition; 
  333. $retval = TRUE; 
  334. } else { 
  335. if (strpos($data, $object_name) === FALSE) { 
  336. $data .= $addition; 
  337. $retval = TRUE; 
  338. $script->extra['data'] = $data; 
  339. unset($script); 
  340. return $retval; 
  341. // Returns the longest and widest dimensions from a list of entities 
  342. function get_entity_statistics($entities, $named_size, $style_images = FALSE) 
  343. $longest = $widest = 0; 
  344. $storage = C_Gallery_Storage::get_instance(); 
  345. $image_mapper = FALSE; 
  346. // we'll fetch this if needed 
  347. // Calculate longest and 
  348. foreach ($entities as $entity) { 
  349. // Get the image 
  350. $image = FALSE; 
  351. if (isset($entity->pid)) { 
  352. $image = $entity; 
  353. } elseif (isset($entity->previewpic)) { 
  354. if (!$image_mapper) { 
  355. $image_mapper = C_Image_Mapper::get_instance(); 
  356. $image = $image_mapper->find($entity->previewpic); 
  357. // Once we have the image, get it's dimensions 
  358. if ($image) { 
  359. $dimensions = $storage->get_image_dimensions($image, $named_size); 
  360. if ($dimensions['width'] > $widest) { 
  361. $widest = $dimensions['width']; 
  362. if ($dimensions['height'] > $longest) { 
  363. $longest = $dimensions['height']; 
  364. // Second loop to style images 
  365. if ($style_images) { 
  366. foreach ($entities as &$entity) { 
  367. // Get the image 
  368. $image = FALSE; 
  369. if (isset($entity->pid)) { 
  370. $image = $entity; 
  371. } elseif (isset($entity->previewpic)) { 
  372. if (!$image_mapper) { 
  373. $image_mapper = C_Image_Mapper::get_instance(); 
  374. $image = $image_mapper->find($entity->previewpic); 
  375. // Once we have the image, get it's dimension and calculate margins 
  376. if ($image) { 
  377. $dimensions = $storage->get_image_dimensions($image, $named_size); 
  378. return array('entities' => $entities, 'longest' => $longest, 'widest' => $widest); 
  379. /** 
  380. * Renders a view after checking for templates 
  381. */ 
  382. function create_view($template, $params = array(), $context = NULL) 
  383. if (isset($params['displayed_gallery'])) { 
  384. if (isset($params['displayed_gallery']->display_settings)) { 
  385. if (isset($params['displayed_gallery']->display_settings['display_type_view'])) { 
  386. if ('default' !== $params['displayed_gallery']->display_settings['display_type_view']) { 
  387. $template = $this->get_display_type_view_abspath($template, $params); 
  388. return $this->call_parent('create_view', $template, $params, $context); 
  389. /** 
  390. * Finds the abs path of template given file name and list of posssible directories 
  391. * @param string $template 
  392. * @param array $params 
  393. * @return string $template  
  394. */ 
  395. function get_display_type_view_abspath($template, $params) 
  396. /** Identify display type and display_type_view */ 
  397. $display_type_name = $params['displayed_gallery']->display_type; 
  398. $display_type_view = $params['displayed_gallery']->display_settings['display_type_view']; 
  399. /** Fetch array of template directories */ 
  400. $dirs = M_Gallery_Display::get_display_type_view_dirs($display_type_name); 
  401. /** Set abspath for template based on directory placeholder in display_type_view */ 
  402. $path = pathinfo($display_type_view); 
  403. if ($path['dirname'] == ".") { 
  404. $template = $dirs['default'] . DIRECTORY_SEPARATOR . $path['basename']; 
  405. } else { 
  406. foreach ($dirs as $dir_name => $dir) { 
  407. if ($path['dirname'] == $dir_name) { 
  408. $template = $dir . DIRECTORY_SEPARATOR . $path['basename']; 
  409. /** Return template. If no match is found, returns the original template */ 
  410. return $template; 
  411. /** 
  412. * Provides a datamapper to perform CRUD operations for Display Types 
  413. * 
  414. * @mixin Mixin_Display_Type_Mapper 
  415. * @implements I_Display_Type_Mapper 
  416. */ 
  417. class C_Display_Type_Mapper extends C_CustomPost_DataMapper_Driver 
  418. public static $_instances = array(); 
  419. function define($context = FALSE, $not_used = FALSE) 
  420. $object_name = 'display_type'; 
  421. // Add the object name to the context of the object as well 
  422. // This allows us to adapt the driver itself, if required 
  423. if (!is_array($context)) { 
  424. $context = array($context); 
  425. array_push($context, $object_name); 
  426. parent::define($object_name, $context); 
  427. $this->add_mixin('Mixin_Display_Type_Mapper'); 
  428. $this->implement('I_Display_Type_Mapper'); 
  429. $this->set_model_factory_method($object_name); 
  430. // Define columns 
  431. $this->define_column('ID', 'BIGINT', 0); 
  432. $this->define_column('name', 'VARCHAR(255)'); 
  433. $this->define_column('title', 'VARCHAR(255)'); 
  434. $this->define_column('preview_image_relpath', 'VARCHAR(255)'); 
  435. $this->define_column('default_source', 'VARCHAR(255)'); 
  436. $this->define_column('view_order', 'BIGINT', NGG_DISPLAY_PRIORITY_BASE); 
  437. $this->add_serialized_column('settings'); 
  438. $this->add_serialized_column('entity_types'); 
  439. function initialize($context = FALSE) 
  440. parent::initialize('display_type'); 
  441. /** 
  442. * Gets a singleton of the mapper 
  443. * @param string|array $context 
  444. * @return C_Display_Type_Mapper 
  445. */ 
  446. public static function get_instance($context = False) 
  447. if (!isset(self::$_instances[$context])) { 
  448. self::$_instances[$context] = new C_Display_Type_Mapper($context); 
  449. return self::$_instances[$context]; 
  450. /** 
  451. * Provides instance methods for the display type mapper 
  452. */ 
  453. class Mixin_Display_Type_Mapper extends Mixin 
  454. /** 
  455. * Locates a Display Type by names 
  456. * @param string $name 
  457. */ 
  458. function find_by_name($name, $model = FALSE) 
  459. $retval = NULL; 
  460. $this->object->select(); 
  461. $this->object->where(array('name = %s', $name)); 
  462. $results = $this->object->run_query(FALSE, $model); 
  463. if (!$results) { 
  464. foreach ($this->object->find_all(FALSE, $model) as $entity) { 
  465. if ($entity->name == $name || isset($entity->aliases) && is_array($entity->aliases) && in_array($name, $entity->aliases)) { 
  466. $retval = $entity; 
  467. break; 
  468. } else { 
  469. $retval = $results[0]; 
  470. return $retval; 
  471. /** 
  472. * Finds display types used to display specific types of entities 
  473. * @param string|array $entity_type e.g. image, gallery, album 
  474. * @return array 
  475. */ 
  476. function find_by_entity_type($entity_type, $model = FALSE) 
  477. $find_entity_types = is_array($entity_type) ? $entity_type : array($entity_type); 
  478. $retval = NULL; 
  479. foreach ($this->object->find_all(FALSE, $model) as $display_type) { 
  480. foreach ($find_entity_types as $entity_type) { 
  481. if (isset($display_type->entity_types) && in_array($entity_type, $display_type->entity_types)) { 
  482. $retval[] = $display_type; 
  483. break; 
  484. return $retval; 
  485. /** 
  486. * Uses the title attribute as the post title 
  487. * @param stdClass $entity 
  488. * @return string 
  489. */ 
  490. function get_post_title($entity) 
  491. return $entity->title; 
  492. /** 
  493. * Sets default values needed for display types 
  494. */ 
  495. function set_defaults($entity) 
  496. if (!isset($entity->settings)) { 
  497. $entity->settings = array(); 
  498. $this->_set_default_value($entity, 'preview_image_relpath', ''); 
  499. $this->_set_default_value($entity, 'default_source', ''); 
  500. $this->_set_default_value($entity, 'view_order', NGG_DISPLAY_PRIORITY_BASE); 
  501. $this->_set_default_value($entity, 'settings', 'use_lightbox_effect', TRUE); 
  502. $this->_set_default_value($entity, 'hidden_from_ui', FALSE); 
  503. // todo remove later 
  504. $this->_set_default_value($entity, 'hidden_from_igw', FALSE); 
  505. $this->_set_default_value($entity, 'aliases', array()); 
  506. return $this->call_parent('set_defaults', $entity); 
  507. /** 
  508. * Associates a Display Type with a collection of images 
  509. * 
  510. * * Properties: 
  511. * - source (gallery, album, recent_images, random_images, etc) 
  512. * - container_ids (gallery ids, album ids, tag ids, etc) 
  513. * - display_type (name of the display type being used) 
  514. * - display_settings (settings for the display type) 
  515. * - exclusions (excluded entity ids) 
  516. * - entity_ids (specific images/galleries to include, sorted) 
  517. * - order_by 
  518. * - order_direction 
  519. * 
  520. * @mixin Mixin_Displayed_Gallery_Validation 
  521. * @mixin Mixin_Displayed_Gallery_Instance_Methods 
  522. * @mixin Mixin_Displayed_Gallery_Queries 
  523. * @implements I_Displayed_Gallery 
  524. */ 
  525. class C_Displayed_Gallery extends C_DataMapper_Model 
  526. var $_mapper_interface = 'I_Displayed_Gallery_Mapper'; 
  527. function define($properties = array(), $mapper = FALSE, $context = FALSE) 
  528. parent::define($mapper, $properties, $context); 
  529. $this->add_mixin('Mixin_Displayed_Gallery_Validation'); 
  530. $this->add_mixin('Mixin_Displayed_Gallery_Instance_Methods'); 
  531. $this->add_mixin('Mixin_Displayed_Gallery_Queries'); 
  532. $this->implement('I_Displayed_Gallery'); 
  533. /** 
  534. * Initializes a display type with properties 
  535. * @param FALSE|C_Displayed_Gallery_Mapper $mapper 
  536. * @param array|stdClass|C_Displayed_Gallery $properties 
  537. * @param FALSE|string|array $context 
  538. */ 
  539. function initialize($properties = array(), $mapper = FALSE, $context = FALSE) 
  540. if (!$mapper) { 
  541. $mapper = $this->get_registry()->get_utility($this->_mapper_interface); 
  542. parent::initialize($mapper, $properties); 
  543. $this->select_random_variation(); 
  544. /** 
  545. * Provides validation 
  546. */ 
  547. class Mixin_Displayed_Gallery_Validation extends Mixin 
  548. function validation() 
  549. // Valid sources 
  550. $this->object->validates_presence_of('source'); 
  551. // Valid display type? 
  552. $this->object->validates_presence_of('display_type'); 
  553. if ($display_type = $this->object->get_display_type()) { 
  554. foreach ($this->object->display_settings as $key => $val) { 
  555. $display_type->settings[$key] = $val; 
  556. $this->object->display_settings = $display_type->settings; 
  557. if (!$display_type->validate()) { 
  558. foreach ($display_type->get_errors() as $property => $errors) { 
  559. foreach ($errors as $error) { 
  560. $this->object->add_error($error, $property); 
  561. $this->object->display_type = $display_type->name; 
  562. // Is the display type compatible with the source? E.g., if we're 
  563. // using a display type that expects images, we can't be feeding it 
  564. // galleries and albums 
  565. if ($source = $this->object->get_source()) { 
  566. if (!$display_type->is_compatible_with_source($source)) { 
  567. $this->object->add_error(__('Source not compatible with selected display type', 'nggallery'), 'display_type'); 
  568. // Allow ONLY recent & random galleries to have their own maximum_entity_count 
  569. if (!empty($this->object->display_settings['maximum_entity_count']) && in_array($this->object->source, array('random_images', 'recent_images', 'random', 'recent'))) { 
  570. $this->object->maximum_entity_count = $this->object->display_settings['maximum_entity_count']; 
  571. // If no maximum_entity_count has been given, then set a maximum 
  572. if (!isset($this->object->maximum_entity_count)) { 
  573. $settings = C_NextGen_Settings::get_instance(); 
  574. $this->object->maximum_entity_count = $settings->get('maximum_entity_count', 500); 
  575. } else { 
  576. $this->object->add_error('Invalid display type', 'display_type'); 
  577. return $this->object->is_valid(); 
  578. class Mixin_Displayed_Gallery_Queries extends Mixin 
  579. function select_random_variation() 
  580. $retval = FALSE; 
  581. $source_obj = $this->object->get_source(); 
  582. if ($source_obj && $source_obj->has_variations) { 
  583. $max = 0; 
  584. if (!defined('NGG_MAX_VARIATIONS')) { 
  585. $settings = C_Photocrati_Global_Settings_Manager::get_instance(); 
  586. $max = $settings->get('max_variations', 5); 
  587. define('NGG_MAX_VARIATIONS', $max); 
  588. } else { 
  589. $max = NGG_MAX_VARIATIONS; 
  590. $this->object->variation = floor(rand(1, $max)); 
  591. $retval = $this->object->variation; 
  592. return $retval; 
  593. function get_entities($limit = FALSE, $offset = FALSE, $id_only = FALSE, $returns = 'included') 
  594. $retval = array(); 
  595. $source_obj = $this->object->get_source(); 
  596. $max = $this->object->get_maximum_entity_count(); 
  597. if (!$limit || is_numeric($limit) && $limit > $max) { 
  598. $limit = $max; 
  599. // Ensure that all parameters have values that are expected 
  600. if ($this->object->_parse_parameters()) { 
  601. // Is this an image query? 
  602. if (in_array('image', $source_obj->returns)) { 
  603. $retval = $this->object->_get_image_entities($source_obj, $limit, $offset, $id_only, $returns); 
  604. } elseif (in_array('gallery', $source_obj->returns)) { 
  605. $retval = $this->object->_get_album_and_gallery_entities($source_obj, $limit, $offset, $id_only, $returns); 
  606. return $retval; 
  607. /** 
  608. * Gets all images in the displayed gallery 
  609. * @param stdClass $source_obj 
  610. * @param int $limit 
  611. * @param int $offset 
  612. * @param boolean $id_only 
  613. * @param string $returns 
  614. */ 
  615. function _get_image_entities($source_obj, $limit, $offset, $id_only, $returns) 
  616. // TODO: This method is very long, and therefore more difficult to read 
  617. // Find a way to minimalize or segment 
  618. $mapper = C_Image_Mapper::get_instance(); 
  619. $image_key = $mapper->get_primary_key_column(); 
  620. $select = $id_only ? $image_key : $mapper->get_table_name() . '.*'; 
  621. $sort_direction = $this->object->order_direction; 
  622. $sort_by = $this->object->order_by; 
  623. // Here's what this method is doing: 
  624. // 1) Determines what results need returned 
  625. // 2) Determines from what container ids the results should come from 
  626. // 3) Applies ORDER BY clause 
  627. // 4) Applies LIMIT/OFFSET clause 
  628. // 5) Executes the query and returns the result 
  629. // We start with the most difficult query. When returns is "both", we 
  630. // need to return a list of both included and excluded entity ids, and 
  631. // mark specifically which entities are excluded 
  632. if ($returns == 'both') { 
  633. // We need to add two dynamic columns, one called "sortorder" and 
  634. // the other called "exclude". 
  635. $if_true = 1; 
  636. $if_false = 0; 
  637. $excluded_set = $this->object->entity_ids; 
  638. if (!$excluded_set) { 
  639. $if_true = 0; 
  640. $if_false = 1; 
  641. $excluded_set = $this->object->exclusions; 
  642. $sortorder_set = $this->object->sortorder ? $this->object->sortorder : $excluded_set; 
  643. // Add sortorder column 
  644. if ($sortorder_set) { 
  645. $select = $this->object->_add_find_in_set_column($select, $image_key, $sortorder_set, 'new_sortorder', TRUE); 
  646. // A user might want to sort the results by the order of 
  647. // images that they specified to be included. For that,  
  648. // we need some trickery by reversing the order direction 
  649. $sort_direction = $this->object->order_direction == 'ASC' ? 'DESC' : 'ASC'; 
  650. $sort_by = 'new_sortorder'; 
  651. // Add exclude column 
  652. if ($excluded_set) { 
  653. $select = $this->object->_add_find_in_set_column($select, $image_key, $excluded_set, 'exclude'); 
  654. $select .= ", IF (exclude = 0 AND @exclude = 0, {$if_true}, {$if_false}) AS 'exclude'"; 
  655. // Select what we want 
  656. $mapper->select($select); 
  657. // When returns is "included", the query is relatively simple. We 
  658. // just provide a where clause to limit how many images we're returning 
  659. // based on the entity_ids, exclusions, and container_ids parameters 
  660. if ($returns == 'included') { 
  661. // If the sortorder propery is available, then we need to override 
  662. // the sortorder 
  663. if ($this->object->sortorder) { 
  664. $select = $this->object->_add_find_in_set_column($select, $image_key, $this->object->sortorder, 'new_sortorder', TRUE); 
  665. $sort_direction = $this->object->order_direction == 'ASC' ? 'DESC' : 'ASC'; 
  666. $sort_by = 'new_sortorder'; 
  667. $mapper->select($select); 
  668. // Filter based on entity_ids selection 
  669. if ($this->object->entity_ids) { 
  670. $mapper->where(array("{$image_key} IN %s", $this->object->entity_ids)); 
  671. // Filter based on exclusions selection 
  672. if ($this->object->exclusions) { 
  673. $mapper->where(array("{$image_key} NOT IN %s", $this->object->exclusions)); 
  674. // Ensure that no images marked as excluded at the gallery level are returned 
  675. if (empty($this->object->skip_excluding_globally_excluded_images)) { 
  676. $mapper->where(array("exclude = %d", 0)); 
  677. } elseif ($returns == 'excluded') { 
  678. // If the sortorder propery is available, then we need to override 
  679. // the sortorder 
  680. if ($this->object->sortorder) { 
  681. $select = $this->object->_add_find_in_set_column($select, $image_key, $this->object->sortorder, 'new_sortorder', TRUE); 
  682. $sort_direction = $this->object->order_direction == 'ASC' ? 'DESC' : 'ASC'; 
  683. $sort_by = 'new_sortorder'; 
  684. // Mark each result as excluded 
  685. $select .= ", 1 AS exclude"; 
  686. $mapper->select($select); 
  687. // Is this case, entity_ids become the exclusions 
  688. $exclusions = $this->object->entity_ids; 
  689. // Remove the exclusions always takes precedence over entity_ids, so 
  690. // we adjust the list of ids 
  691. if ($this->object->exclusions) { 
  692. foreach ($this->object->exclusions as $excluded_entity_id) { 
  693. if (($index = array_search($excluded_entity_id, $exclusions)) !== FALSE) { 
  694. unset($exclusions[$index]); 
  695. // Filter based on exclusions selection 
  696. if ($exclusions) { 
  697. $mapper->where(array("{$image_key} NOT IN %s", $exclusions)); 
  698. } else { 
  699. if ($this->object->exclusions) { 
  700. $mapper->where(array("{$image_key} IN %s", $this->object->exclusions)); 
  701. // Ensure that images marked as excluded are returned as well 
  702. $mapper->where(array("exclude = 1")); 
  703. // Filter based on containers_ids. Container ids is a little more 
  704. // complicated as it can contain gallery ids or tags 
  705. if ($this->object->container_ids) { 
  706. // Container ids are tags 
  707. if ($source_obj->name == 'tags') { 
  708. $term_ids = $this->object->get_term_ids_for_tags($this->object->container_ids); 
  709. $mapper->where(array("{$image_key} IN %s", get_objects_in_term($term_ids, 'ngg_tag'))); 
  710. } else { 
  711. $mapper->where(array("galleryid IN %s", $this->object->container_ids)); 
  712. // Filter based on excluded container ids 
  713. if ($this->object->excluded_container_ids) { 
  714. // Container ids are tags 
  715. if ($source_obj->name == 'tags') { 
  716. $term_ids = $this->object->get_term_ids_for_tags($this->object->excluded_container_ids); 
  717. $mapper->where(array("{$image_key} NOT IN %s", get_objects_in_term($term_ids, 'ngg_tag'))); 
  718. } else { 
  719. $mapper->where(array("galleryid NOT IN %s", $this->object->excluded_container_ids)); 
  720. // Adjust the query more based on what source was selected 
  721. if (in_array($this->object->source, array('recent', 'recent_images'))) { 
  722. $sort_direction = 'DESC'; 
  723. $sort_by = 'imagedate'; 
  724. } elseif ($this->object->source == 'random_images' && empty($this->object->entity_ids)) { 
  725. $table_name = $mapper->get_table_name(); 
  726. $where_clauses = array(); 
  727. $sub_where_sql = ''; 
  728. foreach ($mapper->_where_clauses as $where) { 
  729. $where_clauses[] = '(' . $where . ')'; 
  730. if ($where_clauses) { 
  731. $sub_where_sql = 'WHERE ' . implode(' AND ', $where_clauses); 
  732. $mapper->_where_clauses = array(" /*NGG_NO_EXTRAS_TABLE*/ `{$image_key}` IN (SELECT `{$image_key}` FROM (SELECT `{$image_key}` FROM `{$table_name}` i {$sub_where_sql} ORDER BY RAND() LIMIT {$this->object->maximum_entity_count}) o) /*NGG_NO_EXTRAS_TABLE*/"); 
  733. // Apply a sorting order 
  734. if ($sort_by) { 
  735. $mapper->order_by($sort_by, $sort_direction); 
  736. // Apply a limit 
  737. if ($limit) { 
  738. if ($offset) { 
  739. $mapper->limit($limit, $offset); 
  740. } else { 
  741. $mapper->limit($limit); 
  742. $results = $mapper->run_query(); 
  743. return $results; 
  744. /** 
  745. * Gets all gallery and album entities from albums specified, if any 
  746. * @param stdClass $source_obj 
  747. * @param int $limit 
  748. * @param int $offset 
  749. * @param boolean $id_only 
  750. * @param array $returns 
  751. */ 
  752. function _get_album_and_gallery_entities($source_obj, $limit = FALSE, $offset = FALSE, $id_only = FALSE, $returns = 'included') 
  753. // Albums queries and difficult and inefficient to perform due to the 
  754. // database schema. To complicate things, we're returning two different 
  755. // types of entities - galleries, and sub-albums. 
  756. // The user prefixes entity_id's with an 'a' to distinguish album ids 
  757. // from gallery ids. E.g. entity_ids=[1, "a2", 3] 
  758. $album_mapper = C_Album_Mapper::get_instance(); 
  759. $album_key = $album_mapper->get_primary_key_column(); 
  760. $gallery_mapper = C_Gallery_Mapper::get_instance(); 
  761. $gallery_key = $gallery_mapper->get_primary_key_column(); 
  762. $select = $id_only ? $album_key . ", sortorder" : $album_mapper->get_table_name() . '.*'; 
  763. $retval = array(); 
  764. // If no exclusions are specified, are entity_ids are specified,  
  765. // and we're to return is "included", then we have a relatively easy 
  766. // query to perform - we just fetch each entity listed in 
  767. // the entity_ids field 
  768. if ($returns == 'included' && $this->object->entity_ids && empty($this->object->exclusions)) { 
  769. $retval = $this->object->_entities_to_galleries_and_albums($this->object->entity_ids, $id_only, array(), $limit, $offset); 
  770. } else { 
  771. // Start the query 
  772. $album_mapper->select($select); 
  773. // Fetch the albums, and find the entity ids of the sub-albums and galleries 
  774. $entity_ids = array(); 
  775. $excluded_ids = array(); 
  776. // Filter by container ids. If container_ids === '0' we retrieve all existing gallery_ids and use 
  777. // them as the available entity_ids for comparability with 1.9x 
  778. $container_ids = $this->object->container_ids; 
  779. if ($container_ids) { 
  780. if ($container_ids !== array('0') && $container_ids !== array('')) { 
  781. $album_mapper->where(array("{$album_key} IN %s", $container_ids)); 
  782. foreach ($album_mapper->run_query() as $album) { 
  783. $entity_ids = array_merge($entity_ids, (array) $album->sortorder); 
  784. } else { 
  785. if ($container_ids === array('0') || $container_ids === array('')) { 
  786. foreach ($gallery_mapper->select($gallery_key)->run_query() as $gallery) { 
  787. $entity_ids[] = $gallery->{$gallery_key}; 
  788. // Break the list of entities into two groups, included entities 
  789. // and excluded entity ids 
  790. // -- 
  791. // If a specific list of entity ids have been specified, then 
  792. // we know what entity ids are meant to be included. We can compute 
  793. // the intersect and also determine what entity ids are to be 
  794. // excluded 
  795. if ($this->object->entity_ids) { 
  796. // Determine the real list of included entity ids. Exclusions 
  797. // always take precedence 
  798. $included_ids = $this->object->entity_ids; 
  799. foreach ($this->object->exclusions as $excluded_id) { 
  800. if (($index = array_search($excluded_id, $included_ids)) !== FALSE) { 
  801. unset($included_ids[$index]); 
  802. $excluded_ids = array_diff($entity_ids, $included_ids); 
  803. } elseif ($this->object->exclusions) { 
  804. $included_ids = array_diff($entity_ids, $this->object->exclusions); 
  805. $excluded_ids = array_diff($entity_ids, $included_ids); 
  806. } else { 
  807. $included_ids = $entity_ids; 
  808. // We've built our two groups. Let's determine how we'll focus on them 
  809. // -- 
  810. // We're interested in only the included ids 
  811. if ($returns == 'included') { 
  812. $retval = $this->object->_entities_to_galleries_and_albums($included_ids, $id_only, array(), $limit, $offset); 
  813. } elseif ($returns == 'excluded') { 
  814. $retval = $this->object->_entities_to_galleries_and_albums($excluded_ids, $id_only, $excluded_ids, $limit, $offset); 
  815. } else { 
  816. $retval = $this->object->_entities_to_galleries_and_albums($entity_ids, $id_only, $excluded_ids, $limit, $offset); 
  817. return $retval; 
  818. /** 
  819. * Takes a list of entities, and returns the mapped galleries and sub-albums 
  820. * 
  821. * @param array $entity_ids 
  822. * @param bool $id_only 
  823. * @param array $exclusions 
  824. * @param int $limit 
  825. * @param int $offset 
  826. * @return array 
  827. */ 
  828. function _entities_to_galleries_and_albums($entity_ids, $id_only = FALSE, $exclusions = array(), $limit = FALSE, $offset = FALSE) 
  829. $retval = array(); 
  830. $gallery_ids = array(); 
  831. $album_ids = array(); 
  832. $album_mapper = C_Album_Mapper::get_instance(); 
  833. $album_key = $album_mapper->get_primary_key_column(); 
  834. $gallery_mapper = C_Gallery_Mapper::get_instance(); 
  835. $image_mapper = C_Image_Mapper::get_instance(); 
  836. $gallery_key = $gallery_mapper->get_primary_key_column(); 
  837. $album_select = ($id_only ? $album_key : $album_mapper->get_table_name() . '.*') . ", 1 AS is_album, 0 AS is_gallery, name AS title, albumdesc AS galdesc"; 
  838. $gallery_select = ($id_only ? $gallery_key : $gallery_mapper->get_table_name() . '.*') . ", 1 AS is_gallery, 0 AS is_album"; 
  839. // Modify the sort order of the entities 
  840. if ($this->object->sortorder) { 
  841. $sortorder = array_intersect($this->object->sortorder, $entity_ids); 
  842. $entity_ids = array_merge($sortorder, array_diff($entity_ids, $sortorder)); 
  843. // Segment entity ids into two groups - galleries and albums 
  844. foreach ($entity_ids as $entity_id) { 
  845. if (substr($entity_id, 0, 1) == 'a') { 
  846. $album_ids[] = intval(substr($entity_id, 1)); 
  847. } else { 
  848. $gallery_ids[] = intval($entity_id); 
  849. // Adjust query to include an exclude property 
  850. if ($exclusions) { 
  851. $album_select = $this->object->_add_find_in_set_column($album_select, $album_key, $this->object->exclusions, 'exclude'); 
  852. $album_select = $this->object->_add_if_column($album_select, 'exclude', 0, 1); 
  853. $gallery_select = $this->object->_add_find_in_set_column($gallery_select, $gallery_key, $this->object->exclusions, 'exclude'); 
  854. $gallery_select = $this->object->_add_if_column($gallery_select, 'exclude', 0, 1); 
  855. // Add sorting parameter to the gallery and album queries 
  856. if ($gallery_ids) { 
  857. $gallery_select = $this->object->_add_find_in_set_column($gallery_select, $gallery_key, $gallery_ids, 'ordered_by', TRUE); 
  858. } else { 
  859. $gallery_select .= ", 0 AS ordered_by"; 
  860. if ($album_ids) { 
  861. $album_select = $this->object->_add_find_in_set_column($album_select, $album_key, $album_ids, 'ordered_by', TRUE); 
  862. } else { 
  863. $album_select .= ", 0 AS ordered_by"; 
  864. // Fetch entities 
  865. $galleries = $gallery_mapper->select($gallery_select)->where(array("{$gallery_key} IN %s", $gallery_ids))->order_by('ordered_by', 'DESC')->run_query(); 
  866. $counts = $image_mapper->select('galleryid, COUNT(*) as counter')->where(array(array("galleryid IN %s", $gallery_ids), array('exclude = %d', 0)))->group_by('galleryid')->run_query(FALSE, FALSE, TRUE); 
  867. $albums = $album_mapper->select($album_select)->where(array("{$album_key} IN %s", $album_ids))->order_by('ordered_by', 'DESC')->run_query(); 
  868. // Reorder entities according to order specified in entity_ids 
  869. foreach ($entity_ids as $entity_id) { 
  870. if (substr($entity_id, 0, 1) == 'a') { 
  871. $album = array_shift($albums); 
  872. if ($album) { 
  873. $retval[] = $album; 
  874. } else { 
  875. $gallery = array_shift($galleries); 
  876. if ($gallery) { 
  877. foreach ($counts as $id => $gal_count) { 
  878. if ($gal_count->galleryid == $gallery->gid) { 
  879. $gallery->counter = intval($gal_count->counter); 
  880. unset($counts[$id]); 
  881. $retval[] = $gallery; 
  882. // Sort the entities 
  883. if ($this->object->order_by && $this->object->order_by != 'sortorder') { 
  884. usort($retval, array(&$this, '_sort_album_result')); 
  885. if ($this->object->order_direction == 'DESC') { 
  886. $retval = array_reverse($retval); 
  887. // Limit the entities 
  888. if ($limit) { 
  889. $retval = array_slice($retval, $offset, $limit); 
  890. return $retval; 
  891. /** 
  892. * Returns the total number of entities in this displayed gallery 
  893. * @param string $returns 
  894. * @returns int 
  895. */ 
  896. function get_entity_count($returns = 'included') 
  897. $retval = 0; 
  898. // Is this an image query? 
  899. $source_obj = $this->object->get_source(); 
  900. if (in_array('image', $source_obj->returns)) { 
  901. $retval = count($this->object->_get_image_entities($source_obj, FALSE, FALSE, TRUE, $returns)); 
  902. } elseif (in_array('gallery', $source_obj->returns)) { 
  903. $retval = count($this->object->_get_album_and_gallery_entities($source_obj, FALSE, FALSE, TRUE, $returns)); 
  904. $max = $this->get_maximum_entity_count(); 
  905. if ($retval > $max) { 
  906. $retval = $max; 
  907. return $retval; 
  908. // Honor the gallery 'maximum_entity_count' setting ONLY when dealing with random & recent galleries. All 
  909. // others will always obey the *global* 'maximum_entity_count' setting. 
  910. function get_maximum_entity_count() 
  911. $max = intval(C_NextGen_Settings::get_instance()->get('maximum_entity_count', 500)); 
  912. $sources = C_Displayed_Gallery_Source_Manager::get_instance(); 
  913. $source_obj = $this->object->get_source(); 
  914. if (in_array($source_obj, array($sources->get('random'), $sources->get('random_images'), $sources->get('recent'), $sources->get('recent_images')))) { 
  915. $max = intval($this->object->maximum_entity_count); 
  916. return $max; 
  917. /** 
  918. * Returns all included entities for the displayed gallery 
  919. * @param int $limit 
  920. * @param int $offset 
  921. * @param boolean $id_only 
  922. * @return array 
  923. */ 
  924. function get_included_entities($limit = FALSE, $offset = FALSE, $id_only = FALSE) 
  925. return $this->object->get_entities($limit, $offset, $id_only, 'included'); 
  926. /** 
  927. * Adds a FIND_IN_SET call to the select portion of the query, and 
  928. * optionally defines a dynamic column 
  929. * @param string $select 
  930. * @param string $key 
  931. * @param array $array 
  932. * @param string $alias 
  933. * @param boolean $add_column 
  934. * @return string 
  935. */ 
  936. function _add_find_in_set_column($select, $key, $array, $alias, $add_column = FALSE) 
  937. $array = array_map('intval', $array); 
  938. $set = implode(", ", array_reverse($array)); 
  939. if (!$select) { 
  940. $select = "1"; 
  941. $select .= ", @{$alias} := FIND_IN_SET({$key}, '{$set}')"; 
  942. if ($add_column) { 
  943. $select .= " AS {$alias}"; 
  944. return $select; 
  945. function _add_if_column($select, $alias, $true = 1, $false = 0) 
  946. if (!$select) { 
  947. $select = "1"; 
  948. $select .= ", IF(@{$alias} = 0, {$true}, {$false}) AS {$alias}"; 
  949. return $select; 
  950. /** 
  951. * Parses the list of parameters provided in the displayed gallery, and 
  952. * ensures everything meets expectations 
  953. * @return boolean 
  954. */ 
  955. function _parse_parameters() 
  956. $valid = FALSE; 
  957. // Ensure that the source is valid 
  958. if (C_Displayed_Gallery_Source_Manager::get_instance()->get($this->object->source)) { 
  959. $valid = TRUE; 
  960. // Ensure that exclusions, entity_ids, and sortorder have valid elements. 
  961. // IE likes to send empty array as an array with a single element that 
  962. // has no value 
  963. if ($this->object->exclusions && !$this->object->exclusions[0]) { 
  964. $this->object->exclusions = array(); 
  965. if ($this->object->entity_ids && !$this->object->entity_ids[0]) { 
  966. $this->object->entity_ids = array(); 
  967. if ($this->object->sortorder && !$this->object->sortorder[0]) { 
  968. $this->object->sortorder = array(); 
  969. return $valid; 
  970. /** 
  971. * Returns a list of term ids for the list of tags 
  972. * @global wpdb $wpdb 
  973. * @param array $tags 
  974. * @return array 
  975. */ 
  976. function get_term_ids_for_tags($tags = FALSE) 
  977. global $wpdb; 
  978. // If no tags were provided, get them from the container_ids 
  979. if (!$tags || !is_array($tags)) { 
  980. $tags = $this->object->container_ids; 
  981. // Convert container ids to a string suitable for WHERE IN 
  982. $container_ids = array(); 
  983. if (is_array($tags) && !in_array('all', array_map('strtolower', $tags))) { 
  984. foreach ($tags as $ndx => $container) { 
  985. $container = esc_sql(str_replace('%', '%%', $container)); 
  986. $container_ids[] = "'{$container}'"; 
  987. $container_ids = implode(', ', $container_ids); 
  988. // Construct query 
  989. $query = "SELECT {$wpdb->term_taxonomy}.term_id FROM {$wpdb->term_taxonomy}\n INNER JOIN {$wpdb->terms} ON {$wpdb->term_taxonomy}.term_id = {$wpdb->terms}.term_id\n WHERE {$wpdb->term_taxonomy}.term_id = {$wpdb->terms}.term_id\n AND {$wpdb->term_taxonomy}.taxonomy = %s"; 
  990. if (!empty($container_ids)) { 
  991. $query .= " AND ({$wpdb->terms}.slug IN ({$container_ids}) OR {$wpdb->terms}.name IN ({$container_ids}))"; 
  992. $query .= " ORDER BY {$wpdb->terms}.term_id"; 
  993. $query = $wpdb->prepare($query, 'ngg_tag'); 
  994. // Get all term_ids for each image tag slug 
  995. $term_ids = array(); 
  996. $results = $wpdb->get_results($query); 
  997. if (is_array($results) && !empty($results)) { 
  998. foreach ($results as $row) { 
  999. $term_ids[] = $row->term_id; 
  1000. return $term_ids; 
  1001. /** 
  1002. * Sorts the results of an album query 
  1003. * @param stdClass $a 
  1004. * @param stdClass $b 
  1005. */ 
  1006. function _sort_album_result($a, $b) 
  1007. $key = $this->object->order_by; 
  1008. return strcmp($a->{$key}, $b->{$key}); 
  1009. /** 
  1010. * Provides instance methods useful for working with the C_Displayed_Gallery 
  1011. * model 
  1012. */ 
  1013. class Mixin_Displayed_Gallery_Instance_Methods extends Mixin 
  1014. function get_entity() 
  1015. $entity = $this->call_parent('get_entity'); 
  1016. unset($entity->post_author); 
  1017. unset($entity->post_date); 
  1018. unset($entity->post_date_gmt); 
  1019. unset($entity->post_title); 
  1020. unset($entity->post_excerpt); 
  1021. unset($entity->post_status); 
  1022. unset($entity->comment_status); 
  1023. unset($entity->ping_status); 
  1024. unset($entity->post_name); 
  1025. unset($entity->to_ping); 
  1026. unset($entity->pinged); 
  1027. unset($entity->post_modified); 
  1028. unset($entity->post_modified_gmt); 
  1029. unset($entity->post_parent); 
  1030. unset($entity->guid); 
  1031. unset($entity->post_type); 
  1032. unset($entity->post_mime_type); 
  1033. unset($entity->comment_count); 
  1034. unset($entity->filter); 
  1035. unset($entity->post_content_filtered); 
  1036. return $entity; 
  1037. /** 
  1038. * Gets the display type object used in this displayed gallery 
  1039. * @return C_Display_Type 
  1040. */ 
  1041. function get_display_type() 
  1042. return C_Display_Type_Mapper::get_instance()->find_by_name($this->object->display_type, TRUE); 
  1043. /** 
  1044. * Gets the corresponding source instance 
  1045. * @return stdClass 
  1046. */ 
  1047. function get_source() 
  1048. return C_Displayed_Gallery_Source_Manager::get_instance()->get($this->object->source); 
  1049. /** 
  1050. * Returns the galleries queries in this displayed gallery 
  1051. * @return array 
  1052. */ 
  1053. function get_galleries() 
  1054. $retval = array(); 
  1055. if ($source = $this->object->get_source()) { 
  1056. if (in_array('image', $source->returns)) { 
  1057. $mapper = C_Gallery_Mapper::get_instance(); 
  1058. $gallery_key = $mapper->get_primary_key_column(); 
  1059. $mapper->select(); 
  1060. if ($this->object->container_ids) { 
  1061. $mapper->where(array("{$gallery_key} IN %s", $this->object->container_ids)); 
  1062. $retval = $mapper->run_query(); 
  1063. return $retval; 
  1064. /** 
  1065. * Gets albums queried in this displayed gallery 
  1066. * @return array 
  1067. */ 
  1068. function get_albums() 
  1069. $retval = array(); 
  1070. if ($source = $this->object->get_source()) { 
  1071. if (in_array('album', $source->returns)) { 
  1072. $mapper = C_Album_Mapper::get_instance(); 
  1073. $album_key = $mapper->get_primary_key_column(); 
  1074. if ($this->object->container_ids) { 
  1075. $mapper->select()->where(array("{$album_key} IN %s", $this->object->container_ids)); 
  1076. $retval = $mapper->run_query(); 
  1077. return $retval; 
  1078. /** 
  1079. * Returns a transient for the displayed gallery 
  1080. * @return string 
  1081. */ 
  1082. function to_transient() 
  1083. $params = $this->object->get_entity(); 
  1084. unset($params->transient_id); 
  1085. $key = C_Photocrati_Transient_Manager::create_key('displayed_galleries', $params); 
  1086. if (is_null(C_Photocrati_Transient_Manager::fetch($key, NULL))) { 
  1087. C_Photocrati_Transient_Manager::update($key, $params, NGG_DISPLAYED_GALLERY_CACHE_TTL); 
  1088. $this->object->transient_id = $key; 
  1089. if (!$this->object->id()) { 
  1090. $this->object->id($key); 
  1091. return $key; 
  1092. /** 
  1093. * Applies the values of a transient to this object 
  1094. * @param string $transient_id 
  1095. */ 
  1096. function apply_transient($transient_id = NULL) 
  1097. $retval = FALSE; 
  1098. if (!$transient_id && isset($this->object->transient_id)) { 
  1099. $transient_id = $this->object->transient_id; 
  1100. if ($transient_id && ($transient = C_Photocrati_Transient_Manager::fetch($transient_id, FALSE))) { 
  1101. // Ensure that the transient is an object, not array 
  1102. if (is_array($transient)) { 
  1103. $obj = new stdClass(); 
  1104. foreach ($transient as $key => $value) { 
  1105. $obj->{$key} = $value; 
  1106. $transient = $obj; 
  1107. $this->object->_stdObject = $transient; 
  1108. // Ensure that the display settings are an array 
  1109. $this->object->display_settings = $this->_object_to_array($this->object->display_settings); 
  1110. // Ensure that we have the most accurate transient id 
  1111. $this->object->transient_id = $transient_id; 
  1112. if (!$this->object->id()) { 
  1113. $this->object->id($transient_id); 
  1114. $retval = TRUE; 
  1115. } else { 
  1116. unset($this->object->transient_id); 
  1117. unset($this->object->_stdObject->transient_id); 
  1118. $this->object->to_transient(); 
  1119. return $retval; 
  1120. public function _object_to_array($object) 
  1121. $retval = $object; 
  1122. if (is_object($retval)) { 
  1123. $retval = get_object_vars($object); 
  1124. if (is_array($retval)) { 
  1125. foreach ($retval as $key => $val) { 
  1126. if (is_object($val)) { 
  1127. $retval[$key] = $this->_object_to_array($val); 
  1128. return $retval; 
  1129. /** 
  1130. * Class C_Displayed_Gallery_Mapper 
  1131. * @mixin Mixin_Displayed_Gallery_Defaults 
  1132. * @implements I_Displayed_Gallery_Mapper 
  1133. */ 
  1134. class C_Displayed_Gallery_Mapper extends C_CustomPost_DataMapper_Driver 
  1135. static $_instances = array(); 
  1136. function define($context = FALSE, $not_used = FALSE) 
  1137. parent::define('displayed_gallery', array($context, 'displayed_gallery', 'display_gallery')); 
  1138. $this->add_mixin('Mixin_Displayed_Gallery_Defaults'); 
  1139. $this->implement('I_Displayed_Gallery_Mapper'); 
  1140. $this->set_model_factory_method('displayed_gallery'); 
  1141. // $this->add_post_hook( 
  1142. // 'save',  
  1143. // 'Propagate thumbnail dimensions',  
  1144. // 'Hook_Propagate_Thumbnail_Dimensions_To_Settings' 
  1145. // ); 
  1146. /** 
  1147. * Initializes the mapper 
  1148. * @param string|array|FALSE $context 
  1149. */ 
  1150. function initialize() 
  1151. parent::initialize('displayed_gallery'); 
  1152. /** 
  1153. * Gets a singleton of the mapper 
  1154. * @param string|array $context 
  1155. * @return C_Displayed_Gallery_Mapper 
  1156. */ 
  1157. public static function get_instance($context = False) 
  1158. if (!isset(self::$_instances[$context])) { 
  1159. self::$_instances[$context] = new C_Displayed_Gallery_Mapper($context); 
  1160. return self::$_instances[$context]; 
  1161. /** 
  1162. * Adds default values for the displayed gallery 
  1163. */ 
  1164. class Mixin_Displayed_Gallery_Defaults extends Mixin 
  1165. /** 
  1166. * Gets a display type object for a particular entity 
  1167. * @param stdClass|C_DataMapper_Model $entity 
  1168. * @return null|stdClass 
  1169. */ 
  1170. function get_display_type($entity) 
  1171. $mapper = C_Display_Type_Mapper::get_instance(); 
  1172. return $mapper->find_by_name($entity->display_type); 
  1173. /** 
  1174. * Sets defaults needed for the entity 
  1175. * @param type $entity 
  1176. */ 
  1177. function set_defaults($entity) 
  1178. // Ensure that we have a settings array 
  1179. if (!isset($entity->display_settings)) { 
  1180. $entity->display_settings = array(); 
  1181. // If the display type is set, then get it's settings and apply them as 
  1182. // defaults to the "display_settings" of the displayed gallery 
  1183. if (isset($entity->display_type)) { 
  1184. // Get display type mapper 
  1185. if ($display_type = $this->object->get_display_type($entity)) { 
  1186. $entity->display_settings = $this->array_merge_assoc($display_type->settings, $entity->display_settings, TRUE); 
  1187. // Default ordering 
  1188. $settings = C_NextGen_Settings::get_instance(); 
  1189. $this->object->_set_default_value($entity, 'order_by', $settings->galSort); 
  1190. $this->object->_set_default_value($entity, 'order_direction', $settings->galSortDir); 
  1191. // Ensure we have an exclusions array 
  1192. $this->object->_set_default_value($entity, 'exclusions', array()); 
  1193. // Ensure other properties exist 
  1194. $this->object->_set_default_value($entity, 'container_ids', array()); 
  1195. $this->object->_set_default_value($entity, 'excluded_container_ids', array()); 
  1196. $this->object->_set_default_value($entity, 'sortorder', array()); 
  1197. $this->object->_set_default_value($entity, 'entity_ids', array()); 
  1198. $this->object->_set_default_value($entity, 'returns', 'included'); 
  1199. // Set maximum_entity_count 
  1200. $this->object->_set_default_value($entity, 'maximum_entity_count', $settings->maximum_entity_count); 
  1201. /** 
  1202. * Class C_Displayed_Gallery_Renderer 
  1203. * @mixin Mixin_Displayed_Gallery_Renderer 
  1204. * @implements I_Displayed_Gallery_Renderer 
  1205. */ 
  1206. class C_Displayed_Gallery_Renderer extends C_Component 
  1207. static $_instances = array(); 
  1208. /** 
  1209. * Returns an instance of the class 
  1210. * @param mixed $context 
  1211. * @return C_Displayed_Gallery_Renderer 
  1212. */ 
  1213. static function get_instance($context = FALSE) 
  1214. if (!isset(self::$_instances[$context])) { 
  1215. $klass = __CLASS__; 
  1216. self::$_instances[$context] = new $klass($context); 
  1217. return self::$_instances[$context]; 
  1218. /** 
  1219. * Defines the object 
  1220. * @param bool $context 
  1221. */ 
  1222. function define($context = FALSE) 
  1223. parent::define($context); 
  1224. $this->add_mixin('Mixin_Displayed_Gallery_Renderer'); 
  1225. $this->implement('I_Displayed_Gallery_Renderer'); 
  1226. /** 
  1227. * Provides the ability to render a display type 
  1228. */ 
  1229. class Mixin_Displayed_Gallery_Renderer extends Mixin 
  1230. function params_to_displayed_gallery($params) 
  1231. $displayed_gallery = NULL; 
  1232. // Get the NextGEN settings to provide some defaults 
  1233. $settings = C_NextGen_Settings::get_instance(); 
  1234. // Configure the arguments 
  1235. $defaults = array('id' => NULL, 'source' => '', 'container_ids' => array(), 'gallery_ids' => array(), 'album_ids' => array(), 'tag_ids' => array(), 'display_type' => '', 'exclusions' => array(), 'order_by' => $settings->galSort, 'order_direction' => $settings->galSortOrder, 'image_ids' => array(), 'entity_ids' => array(), 'tagcloud' => FALSE, 'returns' => 'included', 'slug' => NULL, 'sortorder' => array()); 
  1236. $args = shortcode_atts($defaults, $params); 
  1237. // Are we loading a specific displayed gallery that's persisted? 
  1238. $mapper = C_Displayed_Gallery_Mapper::get_instance(); 
  1239. if (!is_null($args['id'])) { 
  1240. $displayed_gallery = $mapper->find($args['id'], TRUE); 
  1241. unset($mapper); 
  1242. // no longer needed 
  1243. } else { 
  1244. // Perform some conversions... 
  1245. // Galleries? 
  1246. if ($args['gallery_ids']) { 
  1247. if ($args['source'] != 'albums' and $args['source'] != 'album') { 
  1248. $args['source'] = 'galleries'; 
  1249. $args['container_ids'] = $args['gallery_ids']; 
  1250. if ($args['image_ids']) { 
  1251. $args['entity_ids'] = $args['image_ids']; 
  1252. } elseif ($args['source'] == 'albums') { 
  1253. $args['entity_ids'] = $args['gallery_ids']; 
  1254. unset($args['gallery_ids']); 
  1255. } elseif ($args['album_ids'] || $args['album_ids'] === '0') { 
  1256. $args['source'] = 'albums'; 
  1257. $args['container_ids'] = $args['album_ids']; 
  1258. unset($args['albums_ids']); 
  1259. } elseif ($args['tag_ids']) { 
  1260. $args['source'] = 'tags'; 
  1261. $args['container_ids'] = $args['tag_ids']; 
  1262. unset($args['tag_ids']); 
  1263. } elseif ($args['image_ids']) { 
  1264. $args['source'] = 'galleries'; 
  1265. $args['entity_ids'] = $args['image_ids']; 
  1266. unset($args['image_ids']); 
  1267. } elseif ($args['tagcloud']) { 
  1268. $args['source'] = 'tags'; 
  1269. // Convert strings to arrays 
  1270. if (!is_array($args['container_ids'])) { 
  1271. $args['container_ids'] = preg_split("/, |\\|/", $args['container_ids']); 
  1272. if (!is_array($args['exclusions'])) { 
  1273. $args['exclusions'] = preg_split("/, |\\|/", $args['exclusions']); 
  1274. if (!is_array($args['entity_ids'])) { 
  1275. $args['entity_ids'] = preg_split("/, |\\|/", $args['entity_ids']); 
  1276. if (!is_array($args['sortorder'])) { 
  1277. $args['sortorder'] = preg_split("/, |\\|/", $args['sortorder']); 
  1278. // Get the display settings 
  1279. foreach (array_keys($defaults) as $key) { 
  1280. unset($params[$key]); 
  1281. $args['display_settings'] = $params; 
  1282. // Create the displayed gallery 
  1283. $factory = C_Component_Factory::get_instance(); 
  1284. $displayed_gallery = $factory->create('displayed_gallery', $args, $mapper); 
  1285. unset($factory); 
  1286. // Validate the displayed gallery 
  1287. if ($displayed_gallery) { 
  1288. $displayed_gallery->validate(); 
  1289. return $displayed_gallery; 
  1290. /** 
  1291. * Displays a "displayed gallery" instance 
  1292. * 
  1293. * Alias Properties: 
  1294. * gallery_ids/album_ids/tag_ids == container_ids 
  1295. * image_ids/gallery_ids == entity_ids 
  1296. * 
  1297. * Default Behavior: 
  1298. * - if order_by and order_direction are missing, the default settings 
  1299. * are used from the "Other Options" page. The exception to this is 
  1300. * when entity_ids are selected, in which the order is custom unless 
  1301. * specified. 
  1302. * 
  1303. * How to use: 
  1304. * 
  1305. * To retrieve images from gallery 1 & 3, but exclude images 4 & 6: 
  1306. * [ngg_images gallery_ids="1, 3" exclusions="4, 6" display_type="photocrati-nextgen_basic_thumbnails"] 
  1307. * 
  1308. * To retrieve images 1 & 2 from gallery 1: 
  1309. * [ngg_images gallery_ids="1" image_ids="1, 2" display_type="photocrati-nextgen_basic_thumbnails"] 
  1310. * 
  1311. * To retrieve images matching tags "landscapes" and "wedding shoots": 
  1312. * [ngg_images tag_ids="landscapes, wedding shoots" display_type="photocrati-nextgen_basic_thumbnails"] 
  1313. * 
  1314. * To retrieve galleries from albums 1 & #, but exclude sub-album 1: 
  1315. * [ngg_images album_ids="1, 2" exclusions="a1" display_type="photocrati-nextgen_basic_compact_album"] 
  1316. * 
  1317. * To retrieve galleries from albums 1 & 2, but exclude gallery 1: 
  1318. * [ngg_images album_ids="1, 2" exclusions="1" display_type="photocrati-nextgen_basic_compact_album"] 
  1319. * 
  1320. * To retrieve image 2, 3, and 5 - independent of what container is used 
  1321. * [ngg_images image_ids="2, 3, 5" display_type="photocrati-nextgen_basic_thumbnails"] 
  1322. * 
  1323. * To retrieve galleries 3 & 5, custom sorted, in album view 
  1324. * [ngg_images source="albums" gallery_ids="3, 5" display_type="photocrati-nextgen_basic_compact_album"] 
  1325. * 
  1326. * To retrieve recent images, sorted by alt/title text 
  1327. * [ngg_images source="recent" order_by="alttext" display_type="photocrati-nextgen_basic_thumbnails"] 
  1328. * 
  1329. * To retrieve random image 
  1330. * [ngg_images source="random" display_type="photocrati-nextgen_basic_thumbnails"] 
  1331. * 
  1332. * To retrieve a single image 
  1333. * [ngg_images image_ids='8' display_type='photocrati-nextgen_basic_singlepic'] 
  1334. * 
  1335. * To retrieve a tag cloud 
  1336. * [ngg_images tagcloud=yes display_type='photocrati-nextgen_basic_tagcloud'] 
  1337. */ 
  1338. function display_images($params, $inner_content = NULL, $mode = NULL) 
  1339. $retval = ''; 
  1340. // Validate the displayed gallery 
  1341. if ($displayed_gallery = $this->object->params_to_displayed_gallery($params)) { 
  1342. if ($displayed_gallery->validate()) { 
  1343. // Display! 
  1344. $retval = $this->object->render($displayed_gallery, TRUE, $mode); 
  1345. } else { 
  1346. if (C_NextGEN_Bootstrap::$debug) { 
  1347. $retval = __('We cannot display this gallery', 'nggallery') . $this->debug_msg($displayed_gallery->get_errors()) . $this->debug_msg($displayed_gallery->get_entity()); 
  1348. } else { 
  1349. $retval = __('We cannot display this gallery', 'nggallery'); 
  1350. } else { 
  1351. $retval = __('We cannot display this gallery', 'nggallery'); 
  1352. return $retval; 
  1353. function debug_msg($msg, $print_r = FALSE) 
  1354. $retval = ''; 
  1355. if (C_NextGEN_Bootstrap::$debug) { 
  1356. ob_start(); 
  1357. if ($print_r) { 
  1358. echo '<pre>'; 
  1359. print_r($msg); 
  1360. echo '</pre>'; 
  1361. } else { 
  1362. var_dump($msg); 
  1363. $retval = ob_get_clean(); 
  1364. return $retval; 
  1365. /** 
  1366. * Renders a displayed gallery on the frontend 
  1367. * @param C_Displayed_Gallery|stdClass $displayed_gallery 
  1368. */ 
  1369. function render($displayed_gallery, $return = FALSE, $mode = null) 
  1370. $retval = ''; 
  1371. $lookup = TRUE; 
  1372. // Simply throwing our rendered gallery into a feed will most likely not work correctly. 
  1373. // The MediaRSS option in NextGEN is available as an alternative. 
  1374. if (!C_NextGen_Settings::get_instance()->galleries_in_feeds && is_feed()) { 
  1375. return sprintf(__(' [<a href="%s">See image gallery at %s</a>] ', 'nggallery'), esc_url(apply_filters('the_permalink_rss', get_permalink())), $_SERVER['SERVER_NAME']); 
  1376. if ($mode == null) { 
  1377. $mode = 'normal'; 
  1378. if (apply_filters('ngg_cache_displayed_galleries', FALSE)) { 
  1379. // Save the displayed gallery as a transient if it hasn't already. Allows for ajax operations 
  1380. // to add or modify the gallery without losing a retrievable ID 
  1381. if (!$displayed_gallery->apply_transient()) { 
  1382. $displayed_gallery->to_transient(); 
  1383. } else { 
  1384. if (is_null($displayed_gallery->id())) { 
  1385. $displayed_gallery->id(md5(json_encode($displayed_gallery->get_entity()))); 
  1386. // Get the display type controller 
  1387. $controller = $this->get_registry()->get_utility('I_Display_Type_Controller', $displayed_gallery->display_type); 
  1388. // Get routing info 
  1389. $router = C_Router::get_instance(); 
  1390. $url = $router->get_url($router->get_request_uri(), TRUE); 
  1391. // Should we lookup in cache? 
  1392. if (is_array($displayed_gallery->container_ids) && in_array('All', $displayed_gallery->container_ids)) { 
  1393. $lookup = FALSE; 
  1394. } elseif ($displayed_gallery->source == 'albums' && $controller->param('gallery') or $controller->param('album')) { 
  1395. $lookup = FALSE; 
  1396. } elseif ($controller->param('show')) { 
  1397. $lookup = FALSE; 
  1398. } elseif ($controller->is_cachable() === FALSE) { 
  1399. $lookup = FALSE; 
  1400. } elseif (!NGG_RENDERING_CACHE_ENABLED) { 
  1401. $lookup = FALSE; 
  1402. // Enqueue any necessary static resources 
  1403. if (!defined('NGG_SKIP_LOAD_SCRIPTS') || !NGG_SKIP_LOAD_SCRIPTS) { 
  1404. $controller->enqueue_frontend_resources($displayed_gallery); 
  1405. // Try cache lookup, if we're to do so 
  1406. $key = NULL; 
  1407. $html = FALSE; 
  1408. if ($lookup) { 
  1409. // The display type may need to output some things 
  1410. // even when serving from the cache 
  1411. if ($controller->has_method('cache_action')) { 
  1412. $retval = $controller->cache_action($displayed_gallery); 
  1413. // Output debug message 
  1414. $retval .= $this->debug_msg("Lookup!"); 
  1415. // Some settings affect display types 
  1416. $settings = C_NextGen_Settings::get_instance(); 
  1417. $key_params = apply_filters('ngg_displayed_gallery_cache_params', array($displayed_gallery->get_entity(), $url, $mode, $settings->activateTags, $settings->appendType, $settings->maxImages, $settings->thumbEffect, $settings->thumbCode, $settings->galSort, $settings->galSortDir)); 
  1418. // Any displayed gallery links on the home page will need to be regenerated if the permalink structure 
  1419. // changes 
  1420. if (is_home() or is_front_page()) { 
  1421. $key_params[] = get_option('permalink_structure'); 
  1422. // Try getting the rendered HTML from the cache 
  1423. $key = C_Photocrati_Transient_Manager::create_key('displayed_gallery_rendering', $key_params); 
  1424. $html = C_Photocrati_Transient_Manager::fetch($key, FALSE); 
  1425. // Output debug message
  1426. if ($html) { 
  1427. $retval .= $this->debug_msg("HIT!"); 
  1428. } else { 
  1429. $retval .= $this->debug_msg("MISS!"); 
  1430. // TODO: This is hack. We need to figure out a more uniform way of detecting dynamic image urls 
  1431. if (strpos($html, C_Photocrati_Settings_Manager::get_instance()->dynamic_thumbnail_slug . '/') !== FALSE) { 
  1432. $html = FALSE; 
  1433. // forces the cache to be re-generated 
  1434. } else { 
  1435. $retval .= $this->debug_msg("Not looking up in cache as per rules"); 
  1436. // If we're displaying a variant, I want to know it 
  1437. if (isset($displayed_gallery->variation) && is_numeric($displayed_gallery->variation) && $displayed_gallery->variation > 0) { 
  1438. $retval .= $this->debug_msg("Using variation #{$displayed_gallery->variation}!"); 
  1439. // If a cached version doesn't exist, then create the cache 
  1440. if (!$html) { 
  1441. $retval .= $this->debug_msg("Rendering displayed gallery"); 
  1442. $current_mode = $controller->get_render_mode(); 
  1443. $controller->set_render_mode($mode); 
  1444. $html = apply_filters('ngg_displayed_gallery_rendering', $controller->index_action($displayed_gallery, TRUE), $displayed_gallery); 
  1445. if ($key != null) { 
  1446. C_Photocrati_Transient_Manager::update($key, $html, NGG_RENDERING_CACHE_TTL); 
  1447. $retval .= $html; 
  1448. if (!$return) { 
  1449. echo $retval; 
  1450. return $retval; 
  1451. class C_Displayed_Gallery_Source_Manager 
  1452. private $_sources = array(); 
  1453. private $_entity_types = array(); 
  1454. private $_registered_defaults = array(); 
  1455. /** @var C_Displayed_Gallery_Source_Manager */ 
  1456. static $_instance = NULL; 
  1457. static function get_instance() 
  1458. if (!isset(self::$_instance)) { 
  1459. $klass = get_class(); 
  1460. self::$_instance = new $klass(); 
  1461. return self::$_instance; 
  1462. function register_defaults() 
  1463. // Entity types must be registered first!!! 
  1464. // ---------------------------------------- 
  1465. $this->register_entity_type('gallery', 'galleries'); 
  1466. $this->register_entity_type('image', 'images'); 
  1467. $this->register_entity_type('album', 'albums'); 
  1468. // Galleries 
  1469. $galleries = new stdClass(); 
  1470. $galleries->name = 'galleries'; 
  1471. $galleries->title = __('Galleries', 'nggallery'); 
  1472. $galleries->aliases = array('gallery', 'images', 'image'); 
  1473. $galleries->returns = array('image'); 
  1474. $this->register($galleries->name, $galleries); 
  1475. // Albums 
  1476. $albums = new stdClass(); 
  1477. $albums->name = 'albums'; 
  1478. $albums->title = __('Albums', 'nggallery'); 
  1479. $albums->aliases = array('album'); 
  1480. $albums->returns = array('album', 'gallery'); 
  1481. $this->register($albums->name, $albums); 
  1482. // Tags 
  1483. $tags = new stdClass(); 
  1484. $tags->name = 'tags'; 
  1485. $tags->title = __('Tags', 'nggallery'); 
  1486. $tags->aliases = array('tag', 'image_tags', 'image_tag'); 
  1487. $tags->returns = array('image'); 
  1488. $this->register($tags->name, $tags); 
  1489. // Random Images; 
  1490. $random = new stdClass(); 
  1491. $random->name = 'random_images'; 
  1492. $random->title = __('Random Images', 'nggallery'); 
  1493. $random->aliases = array('random', 'random_image'); 
  1494. $random->returns = array('image'); 
  1495. $random->has_variations = TRUE; 
  1496. $this->register($random->name, $random); 
  1497. // Recent Images 
  1498. $recent = new stdClass(); 
  1499. $recent->name = 'recent_images'; 
  1500. $recent->title = __('Recent Images', 'nggallery'); 
  1501. $recent->aliases = array('recent', 'recent_image'); 
  1502. $recent->returns = array('image'); 
  1503. $this->register($recent->name, $recent); 
  1504. $this->_registered_defaults = TRUE; 
  1505. function register($name, $properties) 
  1506. // We'll use an object to represent the source 
  1507. $object = $properties; 
  1508. if (!is_object($properties)) { 
  1509. $object = new stdClass(); 
  1510. foreach ($properties as $k => $v) { 
  1511. $object->{$k} = $v; 
  1512. // Set default properties 
  1513. $object->name = $name; 
  1514. if (!isset($object->title)) { 
  1515. $object->title = $name; 
  1516. if (!isset($object->returns)) { 
  1517. $object->returns = array(); 
  1518. if (!isset($object->aliases)) { 
  1519. $object->aliases = array(); 
  1520. if (!isset($object->has_variations)) { 
  1521. $object->has_variations = FALSE; 
  1522. // Add internal reference 
  1523. $this->_sources[$name] = $object; 
  1524. foreach ($object->aliases as $name) { 
  1525. $this->_sources[$name] = $object; 
  1526. function register_entity_type() 
  1527. $aliases = func_get_args(); 
  1528. $name = array_shift($aliases); 
  1529. $this->_entity_types[] = $name; 
  1530. foreach ($aliases as $alias) { 
  1531. $this->_entity_types[$alias] = $name; 
  1532. function deregister($name) 
  1533. if ($source = $this->get($name)) { 
  1534. unset($this->_sources[$name]); 
  1535. foreach ($source->aliases as $alias) { 
  1536. unset($this->_sources[$alias]); 
  1537. function deregister_entity_type($name) 
  1538. unset($this->_entity_types[$name]); 
  1539. function get($name_or_alias) 
  1540. if (!$this->_registered_defaults) { 
  1541. $this->register_defaults(); 
  1542. $retval = NULL; 
  1543. if (isset($this->_sources[$name_or_alias])) { 
  1544. $retval = $this->_sources[$name_or_alias]; 
  1545. return $retval; 
  1546. function get_entity_type($name) 
  1547. if (!$this->_registered_defaults) { 
  1548. $this->register_defaults(); 
  1549. $found = array_search($name, $this->_entity_types); 
  1550. if ($found) { 
  1551. return $this->_entity_types[$found]; 
  1552. } else { 
  1553. return NULL; 
  1554. function get_all() 
  1555. if (!$this->_registered_defaults) { 
  1556. $this->register_defaults(); 
  1557. $retval = array(); 
  1558. foreach (array_values($this->_sources) as $source_obj) { 
  1559. if (!in_array($source_obj, $retval)) { 
  1560. $retval[] = $source_obj; 
  1561. usort($retval, array(&$this, '__sort_by_name')); 
  1562. return $retval; 
  1563. function __sort_by_name($a, $b) 
  1564. return strcmp($a->name, $b->name); 
  1565. function get_all_entity_types() 
  1566. if (!$this->_registered_defaults) { 
  1567. $this->register_defaults(); 
  1568. return array_unique(array_values($this->_entity_types)); 
  1569. function is_registered($name) 
  1570. return !is_null($this->get($name)); 
  1571. function is_valid_entity_type($name) 
  1572. return !is_null($this->get_entity_type($name)); 
  1573. function deregister_all() 
  1574. $this->_sources = array(); 
  1575. $this->_entity_types = array(); 
  1576. $this->_registered_defaults = FALSE; 
  1577. function is_compatible($source, $display_type) 
  1578. $retval = FALSE; 
  1579. if ($source = $this->get($source->name)) { 
  1580. // Get the real entity type names for the display type 
  1581. $display_type_entity_types = array(); 
  1582. foreach ($display_type->entity_types as $type) { 
  1583. $result = $this->get_entity_type($type); 
  1584. if ($result) { 
  1585. $display_type_entity_types[] = $result; 
  1586. foreach ($source->returns as $entity_type) { 
  1587. if (in_array($entity_type, $display_type_entity_types, TRUE)) { 
  1588. $retval = TRUE; 
  1589. break; 
  1590. return $retval; 
  1591. abstract class C_Displayed_Gallery_Trigger 
  1592. static function is_renderable($name, $displayed_gallery) 
  1593. return TRUE; 
  1594. function get_css_class() 
  1595. return 'fa fa-circle'; 
  1596. function get_attributes() 
  1597. return array('class' => $this->get_css_class()); 
  1598. function render() 
  1599. $attributes = array(); 
  1600. foreach ($this->get_attributes() as $k => $v) { 
  1601. $k = esc_attr($k); 
  1602. $v = esc_attr($v); 
  1603. $attributes[] = "{$k}='{$v}'"; 
  1604. $attributes = implode(" ", $attributes); 
  1605. return "<i {$attributes}></i>"; 
  1606. /** 
  1607. * The Trigger Manager displays "trigger buttons" for a displayed gallery. 
  1608. * 
  1609. * Each display type can register a "handler", which is a class with a render method, which is used 
  1610. * to render the display of the trigger buttons. 
  1611. * 
  1612. * Each trigger button is registered with a handler, which is also a class with a render() method. 
  1613. * Class C_Displayed_Gallery_Trigger_Manager 
  1614. */ 
  1615. class C_Displayed_Gallery_Trigger_Manager 
  1616. static $_instance = NULL; 
  1617. private $_triggers = array(); 
  1618. private $_trigger_order = array(); 
  1619. private $_display_type_handlers = array(); 
  1620. private $_default_display_type_handler = NULL; 
  1621. private $css_class = 'ngg-trigger-buttons'; 
  1622. private $_default_image_types = array('photocrati-nextgen_basic_thumbnails', 'photocrati-nextgen_basic_singlepic', 'photocrati-nextgen_pro_thumbnail_grid', 'photocrati-nextgen_pro_blog_gallery', 'photocrati-nextgen_pro_film'); 
  1623. /** 
  1624. * @return C_Displayed_Gallery_Trigger_Manager 
  1625. */ 
  1626. static function get_instance() 
  1627. if (!self::$_instance) { 
  1628. $klass = get_class(); 
  1629. self::$_instance = new $klass(); 
  1630. return self::$_instance; 
  1631. function __construct() 
  1632. $this->_default_display_type_handler = 'C_Displayed_Gallery_Trigger_Handler'; 
  1633. foreach ($this->_default_image_types as $display_type) { 
  1634. $this->register_display_type_handler($display_type, 'C_Displayed_Gallery_Image_Trigger_Handler'); 
  1635. function register_display_type_handler($display_type, $klass) 
  1636. $this->_display_type_handlers[$display_type] = $klass; 
  1637. function deregister_display_type_handler($display_type) 
  1638. unset($this->_display_type_handlers[$display_type]); 
  1639. function add($name, $handler) 
  1640. $this->_triggers[$name] = $handler; 
  1641. $this->_trigger_order[] = $name; 
  1642. return $this; 
  1643. function remove($name) 
  1644. $order = array(); 
  1645. unset($this->_triggers[$name]); 
  1646. foreach ($this->_trigger_order as $trigger) { 
  1647. if ($trigger != $name) { 
  1648. $order[] = $trigger; 
  1649. $this->_trigger_order = $order; 
  1650. return $this; 
  1651. function _rebuild_index() 
  1652. $order = array(); 
  1653. foreach ($this->_trigger_order as $name) { 
  1654. $order[] = $name; 
  1655. $this->_trigger_order = $order; 
  1656. return $this; 
  1657. function increment_position($name) 
  1658. if (($current_index = array_search($name, $this->_trigger_order)) !== FALSE) { 
  1659. $next_index = $current_index += 1; 
  1660. // 1, 2, 3, 4, 5 => 1, 2, 4, 3, 5 
  1661. if (isset($this->_trigger_order[$next_index])) { 
  1662. $next = $this->_trigger_order[$next_index]; 
  1663. $this->_trigger_order[$next_index] = $name; 
  1664. $this->_trigger_order[$current_index] = $next; 
  1665. return $this->position_of($name); 
  1666. function decrement_position($name) 
  1667. if (($current_index = array_search($name, $this->_trigger_order)) !== FALSE) { 
  1668. $previous_index = $current_index -= 1; 
  1669. if (isset($this->_trigger_order[$previous_index])) { 
  1670. $previous = $this->_trigger_order[$previous_index]; 
  1671. $this->_trigger_order[$previous_index] = $name; 
  1672. $this->_trigger_order[$current_index] = $previous; 
  1673. return $this->position_of($name); 
  1674. function position_of($name) 
  1675. return array_search($name, $this->_trigger_order); 
  1676. function move_to_position($name, $position_index) 
  1677. if (($current_index = $this->position_of($name)) !== FALSE) { 
  1678. $func = 'increment_position'; 
  1679. if ($current_index < $position_index) { 
  1680. $func = 'decrement_position'; 
  1681. while ($this->position_of($name) != $position_index) { 
  1682. $this->{$func}($name); 
  1683. return $this->position_of($name); 
  1684. function move_to_start($name) 
  1685. if ($index = $this->position_of($name)) { 
  1686. unset($this->_trigger_order[$index]); 
  1687. array_unshift($this->_trigger_order, $name); 
  1688. $this->_rebuild_index(); 
  1689. return $this->position_of($name); 
  1690. function count() 
  1691. return count($this->_trigger_order); 
  1692. function move_to_end($name) 
  1693. $index = $this->position_of($name); 
  1694. if ($index !== FALSE or $index != $this->count() - 1) { 
  1695. unset($this->_trigger_order[$index]); 
  1696. $this->_trigger_order[] = $name; 
  1697. $this->_rebuild_index(); 
  1698. return $this->position_of($name); 
  1699. function get_handler_for_displayed_gallery($displayed_gallery) 
  1700. // Find the trigger handler for the current display type. 
  1701. // First, check the display settings for the displayed gallery. Some third-party 
  1702. // display types might specify their own handler 
  1703. $klass = NULL; 
  1704. if (isset($displayed_gallery->display_settings['trigger_handler'])) { 
  1705. $klass = $displayed_gallery->display_settings['trigger_handler']; 
  1706. } else { 
  1707. $klass = $this->_default_display_type_handler; 
  1708. if (isset($this->_display_type_handlers[$displayed_gallery->display_type])) { 
  1709. $klass = $this->_display_type_handlers[$displayed_gallery->display_type]; 
  1710. return $klass; 
  1711. function render($view, $displayed_gallery) 
  1712. if ($klass = $this->get_handler_for_displayed_gallery($displayed_gallery)) { 
  1713. $handler = new $klass(); 
  1714. $handler->view = $view; 
  1715. $handler->displayed_gallery = $displayed_gallery; 
  1716. $handler->manager = $this; 
  1717. if (method_exists($handler, 'render')) { 
  1718. $handler->render(); 
  1719. return $view; 
  1720. function render_trigger($name, $view, $displayed_gallery) 
  1721. $retval = ''; 
  1722. if (isset($this->_triggers[$name])) { 
  1723. $klass = $this->_triggers[$name]; 
  1724. if (call_user_func(array($klass, 'is_renderable'), $name, $displayed_gallery)) { 
  1725. $handler = new $klass(); 
  1726. $handler->name = $name; 
  1727. $handler->view = $this->view = $view; 
  1728. $handler->displayed_gallery = $displayed_gallery; 
  1729. $retval = $handler->render(); 
  1730. return $retval; 
  1731. function render_triggers($view, $displayed_gallery) 
  1732. $output = FALSE; 
  1733. $css_class = esc_attr($this->css_class); 
  1734. $retval = array("<div class='{$css_class}'>"); 
  1735. foreach ($this->_trigger_order as $name) { 
  1736. if ($markup = $this->render_trigger($name, $view, $displayed_gallery)) { 
  1737. $output = TRUE; 
  1738. $retval[] = $markup; 
  1739. if ($output) { 
  1740. $retval[] = "</div>"; 
  1741. $retval = implode("\n", $retval); 
  1742. } else { 
  1743. $retval = ''; 
  1744. return $retval; 
  1745. function enqueue_resources($displayed_gallery) 
  1746. if ($handler = $this->get_handler_for_displayed_gallery($displayed_gallery)) { 
  1747. wp_enqueue_style('fontawesome'); 
  1748. wp_enqueue_style('ngg_trigger_buttons'); 
  1749. if (method_exists($handler, 'enqueue_resources')) { 
  1750. call_user_func(array($handler, 'enqueue_resources'), $displayed_gallery); 
  1751. foreach ($this->_trigger_order as $name) { 
  1752. $handler = $this->_triggers[$name]; 
  1753. $renderable = TRUE; 
  1754. if (method_exists($handler, 'is_renderable')) { 
  1755. $renderable = call_user_func($handler, 'is_renderable', $name, $displayed_gallery); 
  1756. if ($renderable && method_exists($handler, 'enqueue_resources')) { 
  1757. call_user_func(array($handler, 'enqueue_resources', $name, $displayed_gallery)); 
  1758. class C_Displayed_Gallery_Image_Trigger_Handler 
  1759. function render() 
  1760. foreach ($this->view->find('nextgen_gallery.image', true) as $image_element) { 
  1761. $image_element->append($this->manager->render_triggers($image_element, $this->displayed_gallery)); 
  1762. class C_Displayed_Gallery_Trigger_Handler 
  1763. function render() 
  1764. $this->view->append($this->manager->render_triggers($this->view, $this->displayed_gallery)); 
  1765. /** 
  1766. * Class Mixin_Display_Type_Form 
  1767. * @mixin C_Form 
  1768. */ 
  1769. class Mixin_Display_Type_Form extends Mixin 
  1770. var $_model = null; 
  1771. function initialize() 
  1772. $this->object->implement('I_Display_Type_Form'); 
  1773. /** 
  1774. * Returns the name of the display type. Sub-class should override 
  1775. * @throws Exception 
  1776. * @returns string 
  1777. */ 
  1778. function get_display_type_name() 
  1779. throw new Exception(__METHOD__ . " not implemented"); 
  1780. /** 
  1781. * Returns the model (display type) used in the form 
  1782. * @return stdClass 
  1783. */ 
  1784. function get_model() 
  1785. if ($this->_model == null) { 
  1786. $mapper = C_Display_Type_Mapper::get_instance(); 
  1787. $this->_model = $mapper->find_by_name($this->object->get_display_type_name(), TRUE); 
  1788. return $this->_model; 
  1789. /** 
  1790. * Returns the title of the form, which is the title of the display type 
  1791. * @returns string 
  1792. */ 
  1793. function get_title() 
  1794. return __($this->object->get_model()->title, 'nggallery'); 
  1795. /** 
  1796. * Saves the settings for the display type 
  1797. * @param array $attributes 
  1798. * @return boolean 
  1799. */ 
  1800. function save_action($attributes = array()) 
  1801. return $this->object->get_model()->save(array('settings' => $attributes)); 
  1802. /** 
  1803. * Renders the AJAX pagination settings field 
  1804. * 
  1805. * @param C_Display_Type $display_type 
  1806. * @return string 
  1807. */ 
  1808. function _render_ajax_pagination_field($display_type) 
  1809. return $this->object->_render_radio_field($display_type, 'ajax_pagination', __('Enable AJAX pagination', 'nggallery'), isset($display_type->settings['ajax_pagination']) ? $display_type->settings['ajax_pagination'] : FALSE, __('Browse images without reloading the page.', 'nggallery')); 
  1810. function _render_thumbnail_override_settings_field($display_type) 
  1811. $hidden = !(isset($display_type->settings['override_thumbnail_settings']) ? $display_type->settings['override_thumbnail_settings'] : FALSE); 
  1812. $override_field = $this->_render_radio_field($display_type, 'override_thumbnail_settings', __('Override thumbnail settings', 'nggallery'), isset($display_type->settings['override_thumbnail_settings']) ? $display_type->settings['override_thumbnail_settings'] : FALSE, __("This does not affect existing thumbnails; overriding the thumbnail settings will create an additional set of thumbnails. To change the size of existing thumbnails please visit 'Manage Galleries' and choose 'Create new thumbnails' for all images in the gallery.", 'nggallery')); 
  1813. $dimensions_field = $this->object->render_partial('photocrati-nextgen_gallery_display#thumbnail_settings', array('display_type_name' => $display_type->name, 'name' => 'thumbnail_dimensions', 'label' => __('Thumbnail dimensions', 'nggallery'), 'thumbnail_width' => isset($display_type->settings['thumbnail_width']) ? intval($display_type->settings['thumbnail_width']) : 0, 'thumbnail_height' => isset($display_type->settings['thumbnail_height']) ? intval($display_type->settings['thumbnail_height']) : 0, 'hidden' => $hidden ? 'hidden' : '', 'text' => ''), TRUE); 
  1814. /** 
  1815. $qualities = array(); 
  1816. for ($i = 100; $i > 40; $i -= 5) { $qualities[$i] = "{$i}%"; } 
  1817. $quality_field = $this->_render_select_field( 
  1818. $display_type,  
  1819. 'thumbnail_quality',  
  1820. __('Thumbnail quality', 'nggallery'),  
  1821. $qualities,  
  1822. isset($display_type->settings['thumbnail_quality']) ? $display_type->settings['thumbnail_quality'] : 100,  
  1823. '',  
  1824. $hidden 
  1825. ); 
  1826. */ 
  1827. $crop_field = $this->_render_radio_field($display_type, 'thumbnail_crop', __('Thumbnail crop', 'nggallery'), isset($display_type->settings['thumbnail_crop']) ? $display_type->settings['thumbnail_crop'] : FALSE, '', $hidden); 
  1828. /** 
  1829. $watermark_field = $this->_render_radio_field( 
  1830. $display_type,  
  1831. 'thumbnail_watermark',  
  1832. __('Thumbnail watermark', 'nggallery'),  
  1833. isset($display_type->settings['thumbnail_watermark']) ? $display_type->settings['thumbnail_watermark'] : FALSE,  
  1834. '',  
  1835. $hidden 
  1836. ); 
  1837. */ 
  1838. $everything = $override_field . $dimensions_field . $crop_field; 
  1839. return $everything; 
  1840. /** 
  1841. * Renders the thumbnail override settings field(s) 
  1842. * 
  1843. * @param C_Display_Type $display_type 
  1844. * @return string 
  1845. */ 
  1846. function _render_image_override_settings_field($display_type) 
  1847. $hidden = !(isset($display_type->settings['override_image_settings']) ? $display_type->settings['override_image_settings'] : FALSE); 
  1848. $override_field = $this->_render_radio_field($display_type, 'override_image_settings', __('Override image settings', 'nggallery'), isset($display_type->settings['override_image_settings']) ? $display_type->settings['override_image_settings'] : 0, __('Overriding the image settings will create an additional set of images', 'nggallery')); 
  1849. $qualities = array(); 
  1850. for ($i = 100; $i > 40; $i -= 5) { 
  1851. $qualities[$i] = "{$i}%"; 
  1852. $quality_field = $this->_render_select_field($display_type, 'image_quality', __('Image quality', 'nggallery'), $qualities, $display_type->settings['image_quality'], '', $hidden); 
  1853. $crop_field = $this->_render_radio_field($display_type, 'image_crop', __('Image crop', 'nggallery'), $display_type->settings['image_crop'], '', $hidden); 
  1854. $watermark_field = $this->_render_radio_field($display_type, 'image_watermark', __('Image watermark', 'nggallery'), $display_type->settings['image_watermark'], '', $hidden); 
  1855. $everything = $override_field . $quality_field . $crop_field . $watermark_field; 
  1856. return $everything; 
  1857. /** 
  1858. * Renders a field for selecting a template 
  1859. * 
  1860. * @param C_Display_Type $display_type 
  1861. * @return string 
  1862. */ 
  1863. function _render_display_type_view_field($display_type) 
  1864. $display_type_views = $this->get_available_display_type_views($display_type); 
  1865. return $this->object->_render_select_field($display_type, 'display_type_view', __('Select Template', 'nggallery'), $display_type_views, $display_type->settings['display_type_view'], '', FALSE); 
  1866. /** 
  1867. * Gets available templates 
  1868. * 
  1869. * @param C_Display_Type $display_type 
  1870. * @return array 
  1871. */ 
  1872. function get_available_display_type_views($display_type) 
  1873. /** Set up templates array */ 
  1874. $views = array('default' => __('Default Template', 'nggallery')); 
  1875. /** Fetch array of directories to scan */ 
  1876. $dirs = M_Gallery_Display::get_display_type_view_dirs($display_type); 
  1877. /** Populate the views array by scanning each directory for relevant templates */ 
  1878. foreach ($dirs as $dir_name => $dir) { 
  1879. /** Confirm directory exists */ 
  1880. if (!file_exists($dir) || !is_dir($dir)) { 
  1881. continue; 
  1882. /** Scan for template files and create array */ 
  1883. $files = scandir($dir); 
  1884. $template_files = preg_grep('/^.+\\-template.php$/i', $files); 
  1885. $template_files = $template_files ? array_combine($template_files, $template_files) : array(); 
  1886. /** For custom templates only, append directory name placeholder */ 
  1887. foreach ($template_files as $key => $value) { 
  1888. if ($dir_name !== 'default') { 
  1889. $template_files[$dir_name . DIRECTORY_SEPARATOR . $key] = $dir_name . DIRECTORY_SEPARATOR . $value; 
  1890. unset($template_files[$key]); 
  1891. $views = array_merge($views, $template_files); 
  1892. return $views; 
.