Merge lp:~edb/quam-plures/three_image_hooks into lp:quam-plures

Proposed by EdB
Status: Merged
Merged at revision: 7574
Proposed branch: lp:~edb/quam-plures/three_image_hooks
Merge into: lp:quam-plures
Diff against target: 435 lines (+163/-98)
4 files modified
qp_inc/files/model/_file.class.php (+74/-64)
qp_inc/files/upload.ctrl.php (+38/-34)
qp_inc/plugins/_plugin.class.php (+47/-0)
qp_inc/plugins/model/_plugins_admin.class.php (+4/-0)
To merge this branch: bzr merge lp:~edb/quam-plures/three_image_hooks
Reviewer Review Type Date Requested Status
Yabs (community) Approve
Review via email: mp+44067@code.launchpad.net

Description of the change

This adds 3 hooks for working with images, but does not currently include any plugin that uses them. 2 came from that other app and seem useful for a watermarking plugin. The third I wanted so I could automatically resize an image after saving is successful.

'AfterFileUpload' => 'Called before an uploaded file gets saved on server.',
'AfterFileSave' => 'Called after an uploaded file gets saved on server.',
'BeforeThumbCreate' => 'This gets called before an image thumbnail gets created.',

To post a comment you must log in.
Revision history for this message
Yabs (yabs) wrote :

I'll try and get chance over the next couple of days to download and test this, but from a quick skim of the code it looks like it should work.

¥

Revision history for this message
Yabs (yabs) wrote :

Ok, seems to work well enough, not sure I like the image options but that's just a personal choice thing and I rarely, if ever, use the cores image stuff so it's not even remotely a deal killer ;)

¥

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'qp_inc/files/model/_file.class.php'
2--- qp_inc/files/model/_file.class.php 2010-08-17 10:18:27 +0000
3+++ qp_inc/files/model/_file.class.php 2010-12-17 16:57:56 +0000
4@@ -247,6 +247,69 @@
5
6
7 /**
8+ * Create the file/folder on disk, if it does not exist yet.
9+ *
10+ * Also sets file permissions.
11+ * Also inserts meta data into DB (if file/folder was successfully created).
12+ *
13+ * @param string type ('dir'|'file')
14+ * @param string optional permissions (octal format), otherwise the default from {@link $Settings} gets used
15+ * @return boolean true if file/folder was created, false on failure
16+ */
17+ function create( $type = 'file', $chmod = NULL )
18+ {
19+ if( $type == 'dir' )
20+ { // Create an empty directory:
21+ $success = @mkdir( $this->_adfp_full_path );
22+ $this->_is_dir = true; // used by chmod
23+ }
24+ else
25+ { // Create an empty file:
26+ $success = touch( $this->_adfp_full_path );
27+ $this->_is_dir = false; // used by chmod
28+ }
29+ $this->chmod( $chmod ); // uses $Settings for NULL
30+
31+ if( $success )
32+ { // The file/folder has been successfully created:
33+
34+ // Initializes file properties (type, size, perms...)
35+ $this->load_properties();
36+
37+ // If there was meta data for this file in the DB:
38+ // (maybe the file had existed before?)
39+ // Let's recycle it! :
40+ if( ! $this->load_meta() )
41+ { // No meta data could be loaded, let's make sure localization info gets recorded:
42+ $this->set( 'root_type', $this->_FileRoot->type );
43+ $this->set( 'root_ID', $this->_FileRoot->in_type_ID );
44+ $this->set( 'path', $this->_rdfp_rel_path );
45+ }
46+
47+ // Record to DB:
48+ $this->dbsave();
49+ }
50+
51+ return $success;
52+ }
53+
54+
55+ /**
56+ * Does the File/folder exist on disk?
57+ *
58+ * @return boolean true, if the file or dir exists; false if not
59+ */
60+ function exists()
61+ {
62+ if( ! isset($this->_exists) )
63+ {
64+ $this->_exists = file_exists( $this->_adfp_full_path );
65+ }
66+ return $this->_exists;
67+ }
68+
69+
70+ /**
71 * Attempt to load meta data.
72 *
73 * Will attempt only once and cache the result.
74@@ -302,54 +365,6 @@
75
76
77 /**
78- * Create the file/folder on disk, if it does not exist yet.
79- *
80- * Also sets file permissions.
81- * Also inserts meta data into DB (if file/folder was successfully created).
82- *
83- * @param string type ('dir'|'file')
84- * @param string optional permissions (octal format), otherwise the default from {@link $Settings} gets used
85- * @return boolean true if file/folder was created, false on failure
86- */
87- function create( $type = 'file', $chmod = NULL )
88- {
89- if( $type == 'dir' )
90- { // Create an empty directory:
91- $success = @mkdir( $this->_adfp_full_path );
92- $this->_is_dir = true; // used by chmod
93- }
94- else
95- { // Create an empty file:
96- $success = touch( $this->_adfp_full_path );
97- $this->_is_dir = false; // used by chmod
98- }
99- $this->chmod( $chmod ); // uses $Settings for NULL
100-
101- if( $success )
102- { // The file/folder has been successfully created:
103-
104- // Initializes file properties (type, size, perms...)
105- $this->load_properties();
106-
107- // If there was meta data for this file in the DB:
108- // (maybe the file had existed before?)
109- // Let's recycle it! :
110- if( ! $this->load_meta() )
111- { // No meta data could be loaded, let's make sure localization info gets recorded:
112- $this->set( 'root_type', $this->_FileRoot->type );
113- $this->set( 'root_ID', $this->_FileRoot->in_type_ID );
114- $this->set( 'path', $this->_rdfp_rel_path );
115- }
116-
117- // Record to DB:
118- $this->dbsave();
119- }
120-
121- return $success;
122- }
123-
124-
125- /**
126 * Initializes or refreshes file properties (type, size, perms...)
127 */
128 function load_properties()
129@@ -374,21 +389,6 @@
130
131
132 /**
133- * Does the File/folder exist on disk?
134- *
135- * @return boolean true, if the file or dir exists; false if not
136- */
137- function exists()
138- {
139- if( ! isset($this->_exists) )
140- {
141- $this->_exists = file_exists( $this->_adfp_full_path );
142- }
143- return $this->_exists;
144- }
145-
146-
147- /**
148 * Is the File a directory?
149 *
150 * @return boolean true if the object is a directory, false if not
151@@ -1789,10 +1789,20 @@
152 * @param resource
153 * @param string size name
154 * @param string mimetype of thumbnail
155- * @param string short error code
156+ * @param integer JPEG image quality
157 */
158 function save_thumb_to_cache( $thumb_imh, $size_name, $thumb_mimetype, $thumb_quality = 90 )
159 {
160+ global $Plugins;
161+
162+ $Plugins->trigger_event( 'BeforeThumbCreate', array(
163+ 'imh' => & $thumb_imh,
164+ 'size' => & $size_name,
165+ 'mimetype' => & $thumb_mimetype,
166+ 'quality' => & $thumb_quality,
167+ 'File' => & $this,
168+ ) );
169+
170 $af_thumb_path = $this->get_af_thumb_path( $size_name, $thumb_mimetype, true );
171 if( $af_thumb_path[0] != '!' )
172 { // We obtained a path for the thumbnail to be saved:
173
174=== modified file 'qp_inc/files/upload.ctrl.php'
175--- qp_inc/files/upload.ctrl.php 2010-08-13 16:13:00 +0000
176+++ qp_inc/files/upload.ctrl.php 2010-12-17 16:57:56 +0000
177@@ -56,7 +56,6 @@
178 // Check permission:
179 $current_User->check_perm( 'files', 'add', true );
180
181-
182 $AdminUI->set_path( 'files', 'upload' );
183
184 // Params that may need to be passed through:
185@@ -99,8 +98,8 @@
186 }
187 }
188
189-// I've no idea why I had this in my v247 package. I had a comment "fix the
190-// fucked up path ... maybe" but I've no idea what fucked up path needed
191+// EdB: I've no idea why I had this in my v247 package. I had a comment "fix
192+// the fucked up path ... maybe" but I've no idea what fucked up path needed
193 // fixing. If a path is missing a "/" one day this is probably it ;)
194 if( $path == '/' ) {
195 $path = '';
196@@ -175,7 +174,6 @@
197 }
198 }
199
200-
201 // If there were errors, display them and exit (especially in case there's no valid FileRoot ($fm_FileRoot)):
202 // TODO: dh> this prevents users from uploading if _any_ blog media directory is not writable.
203 // See http://forums.b2evolution.net/viewtopic.php?p=49001#49001
204@@ -193,19 +191,14 @@
205 exit(0);
206 }
207
208-
209 $Debuglog->add( 'FM root: '.var_export( $fm_FileRoot, true ), 'files' );
210 $Debuglog->add( 'FM _ads_list_path: '.var_export( $ads_list_path, true ), 'files' );
211
212-
213 if( empty($ads_list_path) )
214 { // We have no Root / list path, there was an error. Unset any action.
215 $action = '';
216 }
217
218-
219-
220-
221 // Check permissions:
222 if( ! $Settings->get('upload_enabled') )
223 { // Upload is globally disabled
224@@ -217,7 +210,6 @@
225 $Messages->add( T_('You have no permission to add/upload files.'), 'error' );
226 }
227
228-
229 // If there were errors, display them and exit (especially in case there's no valid FileRoot ($fm_FileRoot)):
230 if( $Messages->count('error') )
231 {
232@@ -228,7 +220,6 @@
233 exit(0);
234 }
235
236-
237 // Quick mode means "just upload and leave mode when successful"
238 param( 'upload_quickmode', 'integer', 0 );
239
240@@ -361,6 +352,19 @@
241 continue;
242 }
243
244+ // Trigger plugin event
245+ if( $Plugins->trigger_event_first_false( 'AfterFileUpload', array(
246+ 'File' => & $newFile,
247+ 'name' => & $_FILES['uploadfile']['name'][$lKey],
248+ 'type' => & $_FILES['uploadfile']['type'][$lKey],
249+ 'tmp_name' => & $_FILES['uploadfile']['tmp_name'][$lKey],
250+ 'size' => & $_FILES['uploadfile']['size'][$lKey],
251+ ) ) )
252+ {
253+ // Plugin returned 'false'. Abort file upload
254+ continue;
255+ }
256+
257 // Attempt to move the uploaded file to the requested target location:
258 if( ! @move_uploaded_file( $_FILES['uploadfile']['tmp_name'][$lKey], $newFile->get_full_path() ) )
259 {
260@@ -423,24 +427,26 @@
261 // get three links for img/link code or one link for files into any post
262 if( $mode == 'upload' )
263 {
264- // TODO: Add plugin hook to allow generating JS insert code(s)
265+ // @todo (legacy): Add plugin hook to allow generating JS insert code(s)
266 if( $newFile->is_image() )
267 {
268- // Gets image tag and stip out table and caption
269- $img_tag = format_to_output( $newFile->get_tag( '', NULL, '', '', 'original', '', 'leftmargin' ), 'formvalue' );
270- // style="width:40%;float:left;" could be class="uploaded_image" ??
271 $success_msg .= '<br />';
272 $success_msg .= '<fieldset class="uploaded_image"><legend>'.T_('Add this Image to your Post').'</legend><ul><li>';
273+ // image tag floated left
274+ $img_tag = format_to_output( $newFile->get_tag( '<span class="imgwrap floatleft center">', '<br /><span class="image_legend">', '</span>', '</span>', 'original', '', 'spanimage' ), 'formvalue' );
275 $success_msg .= '<a href="#" onclick="if( window.focus && window.opener ){ window.opener.focus(); textarea_wrap_selection( window.opener.document.getElementById(\'itemform_post_content\'), \''.$img_tag.'\', \'\', 1, window.opener.document ); } return false;">['.T_('float:left').']</a> or ';
276- $img_tag = format_to_output( $newFile->get_tag( '', NULL, '', '', 'original', '', 'center'), 'formvalue' );
277+ // image tag centered
278+ $img_tag = format_to_output( $newFile->get_tag( '<div class="image_block">', '<div class="image_legend">', '</div>', '</div>', 'original', '', 'center'), 'formvalue' );
279 $success_msg .= '<a href="#" onclick="if( window.focus && window.opener ){ window.opener.focus(); textarea_wrap_selection( window.opener.document.getElementById(\'itemform_post_content\'), \''.$img_tag.'\', \'\', 1, window.opener.document ); } return false;">['.T_('centered').']</a> or ';
280- $img_tag = format_to_output( $newFile->get_tag( '', NULL, '', '', 'original', '', 'rightmargin' ), 'formvalue' );
281+ // image tag floated right
282+ $img_tag = format_to_output( $newFile->get_tag( '<span class="imgwrap floatright center">', '<br /><span class="image_legend">', '</span>', '</span>', 'original', '', 'spanimage' ), 'formvalue' );
283 $success_msg .= '<a href="#" onclick="if( window.focus && window.opener ){ window.opener.focus(); textarea_wrap_selection( window.opener.document.getElementById(\'itemform_post_content\'), \''.$img_tag.'\', \'\', 1, window.opener.document ); } return false;">['.T_('float:right)').']</a>';
284 $success_msg .= '</li></ul></fieldset>';
285 $success_msg .= '<hr class="hidden" />';
286 }
287 else
288 {
289+ // not an image so it gets ... something
290 $img_tag = format_to_output( $newFile->get_tag(), 'formvalue' );
291 $success_msg .= '<ul>'
292 .'<li><a href="#" onclick="if( window.focus && window.opener ){ window.opener.focus(); textarea_wrap_selection( window.opener.document.getElementById(\'itemform_post_content\'), \''.$img_tag.'\', \'\', 1, window.opener.document ); } return false;">'.T_('Add a link to this file in your post').'</a></li>'
293@@ -482,6 +488,10 @@
294 // Store File object into DB:
295 $newFile->dbsave();
296
297+ $Plugins->trigger_event( 'AfterFileSave', array(
298+ 'newFile' => & $newFile,
299+ ) );
300+
301 }
302
303 if( $upload_quickmode && !empty($failedFiles) )
304@@ -494,40 +504,34 @@
305 // header_redirect( $dispatcher.'?ctrl=files&root='.$fm_FileRoot->ID.'&path='.rawurlencode($path) );
306 header_redirect( regenerate_url( 'ctrl', 'ctrl=files', '', '&' ) );
307 }
308+
309 }
310
311 // Update sub-menu:
312 if( $current_User->check_perm( 'files', 'add' ) )
313 { // Permission to upload: (no subtabs needed otherwise)
314 $AdminUI->add_menu_entries(
315- 'files',
316- array(
317- 'browse' => array(
318- 'text' => T_('Browse'),
319- 'href' => regenerate_url( 'ctrl', 'ctrl=files' ) ),
320- 'upload' => array(
321- 'text' => T_('Upload'),
322- 'href' => regenerate_url( 'ctrl', 'ctrl=upload' ) ),
323- )
324- );
325+ 'files', array(
326+ 'browse' => array(
327+ 'text' => T_('Browse'),
328+ 'href' => regenerate_url( 'ctrl', 'ctrl=files' ) ),
329+ 'upload' => array(
330+ 'text' => T_('Upload'),
331+ 'href' => regenerate_url( 'ctrl', 'ctrl=upload' ) ),
332+ )
333+ );
334 }
335
336-
337 // Display <html><head>...</head> section! (Note: should be done early if actions do not redirect)
338 $AdminUI->disp_html_head();
339
340 // Display title, menu, messages, etc. (Note: messages MUST be displayed AFTER the actions)
341 $AdminUI->disp_body_top();
342
343-
344-/*
345- * Display payload:
346- */
347+// Display payload:
348 $AdminUI->disp_view( 'files/views/_file_upload.view.php' );
349
350-
351 // Display body bottom, debug info and close </html>:
352 $AdminUI->disp_global_footer();
353
354-
355 ?>
356
357=== modified file 'qp_inc/plugins/_plugin.class.php'
358--- qp_inc/plugins/_plugin.class.php 2010-11-02 14:17:25 +0000
359+++ qp_inc/plugins/_plugin.class.php 2010-12-17 16:57:56 +0000
360@@ -1794,6 +1794,22 @@
361 {
362 }
363
364+ /**
365+ * This gets called before an image thumbnail gets created.
366+ *
367+ * This is useful to post-process the thumbnail image (add a watermark or change colors).
368+ *
369+ * @param array Associative array of parameters
370+ * - 'File': the related File (by reference)
371+ * - 'imh': image resource (by reference)
372+ * - 'size': size name (by reference)
373+ * - 'mimetype': mimetype of thumbnail (by reference)
374+ * - 'quality': JPEG image quality [0-100] (by reference)
375+ */
376+ function BeforeThumbCreate( & $params )
377+ {
378+ }
379+
380 // }}}
381
382
383@@ -2322,6 +2338,37 @@
384 return false; // Do nothing by default
385 }
386
387+
388+ /**
389+ * Event handler: Called before an uploaded file gets saved on server.
390+ *
391+ * @param array Associative array of parameters
392+ * - 'File': The "File" object (by reference).
393+ * - 'name': file name (by reference).
394+ * - 'type': file mimetype (by reference).
395+ * - 'tmp_name': file location (by reference).
396+ * - 'size': file size in bytes (by reference).
397+ *
398+ * @return boolean 'false' to abort file upload, otherwise return 'true'
399+ */
400+ function AfterFileUpload( & $params )
401+ {
402+ return array(); // Do nothing by default:
403+ }
404+
405+
406+ /**
407+ * Event handler: Called after an uploaded file gets saved on server.
408+ *
409+ * @param array Associative array of parameters
410+ * - 'newFile': The new "File" object (by reference).
411+ */
412+ function AfterFileSave( & $params )
413+ {
414+ return false; // Do nothing by default
415+ }
416+
417+
418 /*
419 * Event handlers }}}
420 */
421
422=== modified file 'qp_inc/plugins/model/_plugins_admin.class.php'
423--- qp_inc/plugins/model/_plugins_admin.class.php 2010-11-02 14:17:25 +0000
424+++ qp_inc/plugins/model/_plugins_admin.class.php 2010-12-17 16:57:56 +0000
425@@ -171,6 +171,10 @@
426
427 'AppendHitLog' => 'Called when a hit gets logged, but before it gets recorded.',
428
429+ 'AfterFileUpload' => 'Called before an uploaded file gets saved on server.',
430+ 'AfterFileSave' => 'Called after an uploaded file gets saved on server.',
431+ 'BeforeThumbCreate' => 'This gets called before an image thumbnail gets created.',
432+
433 'DisplayCommentToolbar' => 'Display a toolbar on the public feedback form',
434 'DisplayCommentFormButton' => 'Called in the submit button section of the frontend comment form.',
435 'DisplayCommentFormFieldset' => 'Called at the end of the frontend comment form.',

Subscribers

People subscribed via source and target branches