fa6df74435f6de861f60575576b29a05a8a5a10b
[web/PetoskeyRobotics.git] /
1 <?php
2 /**
3  {
4         Module:         photocrati-attach_to_post,
5         Depends:        { photocrati-nextgen_gallery_display }
6  }
7  */
8
9 define('NGG_ATTACH_TO_POST_SLUG', 'nextgen-attach_to_post');
10
11 class M_Attach_To_Post extends C_Base_Module
12 {
13         var $attach_to_post_tinymce_plugin  = 'NextGEN_AttachToPost';
14     var $_event_publisher               = NULL;
15
16         /**
17          * Defines the module
18          * @param string|bool $context
19          */
20     function define($context=FALSE)
21     {
22         parent::define(
23                         'photocrati-attach_to_post',
24                         'Attach To Post',
25                         'Provides the "Attach to Post" interface for displaying galleries and albums',
26                         '0.10',
27                         'http://www.nextgen-gallery.com',
28                         'Photocrati Media',
29                         'http://www.photocrati.com',
30                     $context
31                 );
32
33                 include_once('class.attach_to_post_option_handler.php');
34                 C_NextGen_Settings::get_instance()->add_option_handler('C_Attach_To_Post_Option_Handler', array(
35                         'attach_to_post_url',
36                         'gallery_preview_url',
37                         'attach_to_post_display_tab_js_url'
38                 ));
39         if (is_multisite()) C_NextGen_Global_Settings::get_instance()->add_option_handler('C_Attach_To_Post_Option_Handler', array(
40             'attach_to_post_url',
41             'gallery_preview_url',
42             'attach_to_post_display_tab_js_url'
43         ));
44
45                 include_once('class.attach_to_post_installer.php');
46                 C_Photocrati_Installer::add_handler($this->module_id, 'C_Attach_To_Post_Installer');
47                 
48         // Set WP_ADMIN=true for better compatibility with certain themes & plugins.
49         // Unfortunately as of 3.9 in a multisite environment this causes problems.
50         if (self::is_atp_url() && (!defined('MULTISITE') || (defined('MULTISITE') && !MULTISITE)))
51             define('WP_ADMIN', true);
52     }
53
54     // We only register our display-type settings forms when IS_ADMIN, but Wordpress 3.9 introduced a problem
55     // with doing this on multisite sub-sites. Now we register our forms when is_atp_url() is true OR is_admin()
56     static function is_atp_url()
57     {
58         return (strpos(strtolower($_SERVER['REQUEST_URI']), '/nextgen-attach_to_post') !== false) ? TRUE : FALSE;
59     }
60
61     /**
62      * Gets the Frame Event Publisher
63      * @return C_Component
64      */
65     function _get_frame_event_publisher()
66     {
67         if (is_null($this->_event_publisher)) {
68             $this->_event_publisher = $this->get_registry()->get_utility('I_Frame_Event_Publisher', 'attach_to_post');
69         }
70
71         return $this->_event_publisher;
72     }
73
74
75         /**
76          * Registers requires the utilites that this module provides
77          */
78         function _register_utilities()
79         {
80                 // This utility provides a controller that renders the
81                 // Attach to Post interface, used to manage Displayed Galleries
82                 $this->get_registry()->add_utility(
83                         'I_Attach_To_Post_Controller',
84                         'C_Attach_Controller'
85 //                      'C_Attach_To_Post_Proxy_Controller'
86                 );
87         }
88
89         /**
90          * Registers the adapters that this module provides
91          */
92         function _register_adapters()
93         {
94                 // Installs the Attach to Post module
95                 $this->get_registry()->add_adapter(
96                         'I_Installer', 'A_Attach_To_Post_Installer'
97                 );
98
99                 // Provides routing for the Attach To Post interface
100                 $this->get_registry()->add_adapter(
101                         'I_Router', 'A_Attach_To_Post_Routes'
102                 );
103
104                 // Provides AJAX actions for the Attach To Post interface
105                 $this->get_registry()->add_adapter(
106                         'I_Ajax_Controller',   'A_Attach_To_Post_Ajax'
107                 );
108
109                 // Applies a post hook to the generate_thumbnail method of the
110                 // gallery storage component
111                 $this->get_registry()->add_adapter(
112                         'I_Gallery_Storage', 'A_Gallery_Storage_Frame_Event'
113                 );
114         }
115
116
117         function _register_hooks()
118         {
119                 if (is_admin()) {
120                         add_action(
121                                 'admin_enqueue_scripts',
122                                 array(&$this, 'enqueue_static_resources'),
123                                 1
124                         );
125                 }
126
127                 // Add hook to delete displayed galleries when removed from a post
128                 add_action('pre_post_update', array(&$this, 'locate_stale_displayed_galleries'));
129                 add_action('before_delete_post', array(&$this, 'locate_stale_displayed_galleries'));
130                 add_action('post_updated',      array(&$this, 'cleanup_displayed_galleries'));
131                 add_action('after_delete_post', array(&$this, 'cleanup_displayed_galleries'));
132
133                 // Add hook to subsitute displayed gallery placeholders
134                 add_filter('the_content', array(&$this, 'substitute_placeholder_imgs'), PHP_INT_MAX, 1);
135
136                 // Emit frame communication events
137                 add_action('ngg_created_new_gallery',   array(&$this, 'new_gallery_event'));
138                 add_action('ngg_after_new_images_added',array(&$this, 'images_added_event'));
139                 add_action('ngg_page_event',                    array(&$this, 'nextgen_page_event'));
140         add_action('ngg_manage_tags',           array(&$this, 'manage_tags_event'));
141
142         // We use two hooks here because we need it to execute for both the post-new.php
143         // page and ATP interface
144         add_action('plugins_loaded',            array(&$this, 'fix_ie11'), 1);
145         add_action('admin_init',                array(&$this, 'fix_ie11'), PHP_INT_MAX-1);
146         add_action('admin_enqueue_scripts',     array(&$this, 'fix_ie11'), 1);
147         add_action('admin_enqueue_scripts',     array(&$this, 'fix_ie11'), PHP_INT_MAX-1);
148         }
149
150     /**
151      * WordPress sets the X-UA-Compatible header to IE=edge. Unfortunately, this causes problems with Plupload,
152      * so we have the send this header
153      */
154     function fix_ie11()
155     {
156         if ((array_search('attach_to_post', array_keys($_REQUEST)) !== FALSE OR strpos($_SERVER['REQUEST_URI'], NGG_ATTACH_TO_POST_SLUG) !== FALSE OR strpos($_SERVER['REQUEST_URI'], 'wp-admin/post.php') !== FALSE OR strpos($_SERVER['REQUEST_URI'], 'wp-admin/post-new.php') !== FALSE)) {
157             if (!headers_sent()) {
158                 header('X-UA-Compatible: IE=EmulateIE10');
159             }
160         }
161     }
162
163         /**
164      * Substitutes the gallery placeholder content with the gallery type frontend
165      * view, returns a list of static resources that need to be loaded
166      * @param string $content
167      */
168     function substitute_placeholder_imgs($content)
169     {
170                 // Get some utilities
171                 $mapper = $this->get_registry()->get_utility('I_Displayed_Gallery_Mapper');
172                 $router = $this->get_registry()->get_utility('I_Router');
173
174                 // To match ATP entries we compare the stored url against a generic path
175                 // We must check HTTP and HTTPS as well as permalink and non-permalink forms
176                 $preview_url = parse_url($router->join_paths(
177                         $router->remove_url_segment('index.php', $router->get_base_url('root')),
178                         '/nextgen-attach_to_post/preview'
179                 ));
180         $router->debug = TRUE;
181                 $preview_url = preg_quote($preview_url['host'] . $preview_url['path'], '#');
182
183                 $alt_preview_url = parse_url($router->join_paths(
184                         $router->remove_url_segment('index.php', $router->get_base_url('root')),
185                         'index.php/nextgen-attach_to_post/preview'
186                 ));
187                 $alt_preview_url = preg_quote($alt_preview_url['host'] . $alt_preview_url['path'], '#');
188
189                 // The placeholder MUST have a gallery instance id
190                 if (preg_match_all("#<img.*http(s)?://({$preview_url}|{$alt_preview_url})/id--(\\d+).*\\/>#mi", $content, $matches, PREG_SET_ORDER)) {
191                         foreach ($matches as $match) {
192                                 // Find the displayed gallery
193                                 $displayed_gallery_id = $match[3];
194                                 $displayed_gallery = $mapper->find($displayed_gallery_id, TRUE);
195
196                                 // Get the content for the displayed gallery
197                                 $retval = '<p>'._('Invalid Displayed Gallery').'</p>';
198                                 if ($displayed_gallery) {
199                                         $renderer = $this->get_registry()->get_utility('I_Displayed_Gallery_Renderer');
200                                         $retval = $renderer->render($displayed_gallery, TRUE);
201                                 }
202                                 $content = str_replace($match[0], $retval, $content);
203                         }
204                 }
205
206                 return $content;
207     }
208
209         /**
210          * Enqueues static resources required by the Attach to Post interface
211          */
212         function enqueue_static_resources()
213         {
214                 $router = $this->get_registry()->get_utility('I_Router');
215
216                 // Enqueue resources needed at post/page level
217                 if (preg_match("/\/wp-admin\/(post|post-new)\.php$/", $_SERVER['SCRIPT_NAME'])) {
218                         $this->_enqueue_tinymce_resources();
219                         wp_enqueue_style(
220                                 'ngg_attach_to_post_dialog', $router->get_static_url('photocrati-attach_to_post#attach_to_post_dialog.css')
221                         );
222                 }
223
224                 elseif (isset($_REQUEST['attach_to_post']) OR
225                   (isset($_REQUEST['page']) && strpos($_REQUEST['page'], 'nggallery') !== FALSE)) {
226                         wp_enqueue_script('iframely', $router->get_static_url('photocrati-attach_to_post#iframely.js'));
227                         wp_enqueue_style('iframely',  $router->get_static_url('photocrati-attach_to_post#iframely.css'));
228                 }
229         }
230
231
232         /**
233          * Enqueues resources needed by the TinyMCE editor
234          */
235         function _enqueue_tinymce_resources()
236         {
237         wp_localize_script(
238                         'media-editor',
239                         'nextgen_gallery_attach_to_post_url',
240                         C_NextGen_Settings::get_instance()->attach_to_post_url
241                 );
242
243                 // Registers our tinymce button and plugin for attaching galleries
244         $security   = $this->get_registry()->get_utility('I_Security_Manager');
245         $sec_actor  = $security->get_current_actor();
246         $checks = array(
247             $sec_actor->is_allowed('NextGEN Attach Interface'),
248             $sec_actor->is_allowed('NextGEN Use TinyMCE')
249         );
250         if (!in_array(FALSE, $checks)) {
251             if (get_user_option('rich_editing') == 'true') {
252                 add_filter('mce_buttons', array(&$this, 'add_attach_to_post_button'));
253                 add_filter('mce_external_plugins', array(&$this, 'add_attach_to_post_tinymce_plugin'));
254                 add_filter('wp_mce_translation', array($this, 'add_attach_to_post_tinymce_i18n'));
255             }
256         }
257         }
258
259
260         /**
261          * Adds a TinyMCE button for the Attach To Post plugin
262          * @param array $buttons
263          * @returns array
264          */
265         function add_attach_to_post_button($buttons)
266         {
267                 array_push(
268             $buttons,
269             'separator',
270             $this->attach_to_post_tinymce_plugin
271         );
272         return $buttons;
273         }
274
275
276         /**
277          * Adds the Attach To Post TinyMCE plugin
278          * @param array $plugins
279          * @return array
280          * @uses mce_external_plugins filter
281          */
282         function add_attach_to_post_tinymce_plugin($plugins)
283         {
284         global $wp_version;
285         $router = $this->get_registry()->get_utility('I_Router');
286
287         if ($wp_version >= 3.9)
288             $file = $router->get_static_url('photocrati-attach_to_post#ngg_attach_to_post_tinymce_plugin.js');
289         else
290             $file = $router->get_static_url('photocrati-attach_to_post#ngg_attach_to_post_tinymce_plugin_wp38_compat.js');
291
292                 $plugins[$this->attach_to_post_tinymce_plugin] = $file;
293                 return $plugins;
294         }
295
296
297     /**
298      * Adds the Attach To Post TinyMCE i18n strings
299      * @param $mce_translation
300      * @return mixed
301      */
302     function add_attach_to_post_tinymce_i18n($mce_translation)
303     {
304         $mce_translation['ngg_attach_to_post.title'] = __('Attach NextGEN Gallery to Post', 'nggallery');
305         return $mce_translation;
306     }
307
308
309         /**
310          * Locates the ids of displayed galleries that have been
311          * removed from the post, and flags then for cleanup (deletion)
312          * @global array $displayed_galleries_to_cleanup
313          * @param int $post_id
314          */
315         function locate_stale_displayed_galleries($post_id)
316         {
317                 global $displayed_galleries_to_cleanup;
318                 $displayed_galleries_to_cleanup = array();
319                 $post                                                   = get_post($post_id);
320                 $gallery_preview_url                    = C_NextGen_Settings::get_instance()->get('gallery_preview_url');
321                 $preview_url = preg_quote($gallery_preview_url, '#');
322                 if (preg_match_all("#{$preview_url}/id--(\d+)#", html_entity_decode($post->post_content), $matches, PREG_SET_ORDER)) {
323                         foreach ($matches as $match) {
324                                 $preview_url = preg_quote($match[0], '/');
325                                 // The post was edited, and the displayed gallery placeholder was removed
326                                 if (isset($_REQUEST['post_content']) && (!preg_match("/{$preview_url}/", $_POST['post_content']))) {
327                                         $displayed_galleries_to_cleanup[] = intval($match[1]);
328                                 }
329                                 // The post was deleted
330                                 elseif (!isset($_REQUEST['action'])) {
331                                         $displayed_galleries_to_cleanup[] = intval($match[1]);
332                                 }
333                         }
334                 }
335         }
336
337         /**
338          * Deletes any displayed galleries that are no longer associated with
339          * a post/page
340          * @global array $displayed_galleries_to_cleanup
341          * @param int $post_id
342          */
343         function cleanup_displayed_galleries($post_id)
344         {
345                 global $displayed_galleries_to_cleanup;
346                 $mapper = $this->get_registry()->get_utility('I_Displayed_Gallery_Mapper');
347                 foreach ($displayed_galleries_to_cleanup as $id) $mapper->destroy($id);
348         }
349
350
351         /**
352          * Notify frames that a new gallery has been created
353          * @param int $gallery_id
354          */
355         function new_gallery_event($gallery_id)
356         {
357         $gallery = $this->get_registry()->get_utility('I_Gallery_Mapper')->find($gallery_id);
358                 if ($gallery) {
359                         $this->_get_frame_event_publisher()->add_event(array(
360                                 'event'         =>      'new_gallery',
361                                 'gallery_id'=>  intval($gallery_id),
362                                 'gallery_title'   =>  $gallery->title
363                         ));
364                 }
365         }
366
367         /**
368          * Notifies a frame that images have been added to a gallery
369          * @param int $gallery_id
370          * @param array $image_ids
371          */
372         function images_added_event($gallery_id, $image_ids=array())
373         {
374         $this->_get_frame_event_publisher()->add_event(array(
375                         'event'                 =>      'images_added',
376                         'gallery_id'            =>      intval($gallery_id)
377                 ));
378         }
379
380     /**
381      * Notifies a frame that the tags have changed
382      *
383      * @param array $tags
384      */
385     function manage_tags_event($tags = array())
386     {
387         $this->_get_frame_event_publisher()->add_event(array(
388             'event' => 'manage_tags',
389             'tags' => $tags
390         ));
391     }
392
393         /**
394          * Notifies a frame that an action has been performed on a particular
395          * NextGEN page
396          * @param array $event
397          */
398         function nextgen_page_event($event)
399         {
400         $this->_get_frame_event_publisher()->add_event($event);
401         }
402
403     function get_type_list()
404     {
405         return array(
406             'A_Attach_To_Post_Ajax' => 'adapter.attach_to_post_ajax.php',
407             'C_Attach_To_Post_Installer' => 'class.attach_to_post_installer.php',
408             'A_Attach_To_Post_Routes' => 'adapter.attach_to_post_routes.php',
409             'A_Gallery_Storage_Frame_Event' => 'adapter.gallery_storage_frame_event.php',
410             'C_Attach_Controller' => 'class.attach_controller.php',
411                         'C_Attach_To_Post_Proxy_Controller' => 'class.attach_to_post_proxy_controller.php',
412             'I_Attach_To_Post_Controller' => 'interface.attach_to_post_controller.php',
413             'Mixin_Attach_To_Post_Display_Tab' => 'mixin.attach_to_post_display_tab.php'
414         );
415     }
416 }
417
418 new M_Attach_To_Post();