3
* This file implements the UI controller for managing widgets inside of a blog.
5
* Quam Plures - {@link http://quamplures.net/}
6
* Released under GNU GPL License - {@link http://quamplures.net/license.html}
7
* @copyright (c) 2009 - 2011 by the Quam Plures developers - {@link http://quamplures.net/}
8
* @copyright (c)2003-2009 by Francois PLANQUE - {@link http://fplanque.net/}
10
* {@internal Open Source relicensing agreement:
13
* {@internal Below is a list of authors who have contributed to design/coding of this file: }}
14
* @author fplanque: Francois PLANQUE.
3
* $ctrl_mappings: 'widgets' || Blog settings -> {{blog}} -> Widgets
5
* This is a (partial?) list of authors who have contributed to this file:
6
* @author {@link http://wonderwinds.com/ Ed Bennett}
7
* @author {@link http://fplanque.net/ Francois PLANQUE}
8
* @copyright (c) 2009 by {@link http://quamplures.net/ the Quam Plures project}
9
* @copyright (c) 2003 by Francois PLANQUE - {@link http://fplanque.net/}
10
* @license {@link http://www.gnu.org/licenses/gpl.txt GNU General Public License v3}
18
if( !defined('QP_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
13
if(!defined('QP_MAIN_INIT')) die('fail');
29
load_class( 'widgets/model/_widget.class.php' );
31
18
param( 'action', 'string', 'list' );
32
19
param( 'display_mode', 'string', 'normal' );
33
20
$display_mode = ( in_array( $display_mode, array( 'js', 'normal' ) ) ? $display_mode : 'normal' );
34
21
if( $display_mode == 'js' )
35
{ // Javascript in debug mode conflicts/fails.
23
// Javascript in debug mode conflicts/fails.
36
24
// fp> TODO: either fix the debug javascript or have an easy way to disable JS in the debug output.
39
// This should probably be handled with teh existing $mode var
27
// This should probably be handled with the existing $mode var
42
* Init the objects we want to work on.
29
// Init the objects we want to work on
52
param( 'type', 'string', true );
53
param( 'code', 'string', true );
38
param( 'type', 'string', true );
39
param( 'code', 'string', true );
55
param( 'container', 'string', true, true ); // memorize
41
param( 'container', 'string', true, true ); // memorize
58
case 're-order' : // js request
59
param( 'container_list', 'string', true );
60
$containers_list = explode( ',', $container_list );
61
$containers = array();
62
foreach( $containers_list as $a_container )
63
{ // add each container and grab its widgets:
64
if( $container_name = trim( str_replace( array( 'container_', '_' ), array( '', ' ' ), $a_container ), ',' ) )
66
$containers[ $container_name ] = explode( ',', param( trim( $a_container, ',' ), 'string', true ) );
44
case 're-order': // js request
45
param( 'container_list', 'string', true );
46
$containers_list = explode( ',', $container_list );
47
$containers = array();
48
foreach( $containers_list as $a_container )
50
// add each container and grab its widgets
51
if( $container_name = trim( str_replace( array( 'container_', '_' ), array( '', ' ' ), $a_container ), ',' ) )
53
$containers[$container_name] = explode( ',', param( trim( $a_container, ',' ), 'string', true ) );
96
82
switch( $display_mode )
98
case 'js' : // js response needed
99
// fp> when does this happen -- should be documented
100
if( !$current_User->check_perm( 'blog_properties', 'edit', false, $blog ) )
101
{ // user doesn't have permissions
102
$Messages->add( T_('You do not have permission to perform this action' ) );
103
// fp>does this only happen when we try to edit settings. The hardcoded 'closeWidgetSettings' response looks bad.
104
send_javascript_message( array( 'closeWidgetSettings' => array() ) );
86
if( !$current_User->check_perm( 'blog_properties', 'edit', false, $blog ) )
88
// user doesn't have permissions
89
$Messages->add( T_('You do not have permission to perform this action' ) );
90
// fp> does this only happen when we try to edit settings? The hardcoded 'closeWidgetSettings' response looks bad.
91
send_javascript_message( array( 'closeWidgetSettings' => array() ) );
95
// take usual approach
109
default : // take usual approach
110
$current_User->check_perm( 'blog_properties', 'edit', true, $blog );
98
$current_User->check_perm( 'blog_properties', 'edit', true, $blog );
113
// Get Template used by current Blog:
101
// get template used by current blog
114
102
$TemplateCache = & get_Cache( 'TemplateCache' );
115
103
$Template = & $TemplateCache->get_by_ID( $Blog->template_ID );
116
// Make sure containers are loaded for that template:
104
// make sure containers are loaded for that template
117
105
$container_list = $Template->get_containers();
123
108
switch( $action )
132
// Add a Widget to container:
133
if( !in_array( $container, $container_list ) )
135
$Messages->add( T_('WARNING: you are adding to a container that does not seem to be part of the current template.'), 'error' );
141
// Check the requested core widget is valid:
142
$WidgetCache = & get_Cache( 'WidgetCache' );
143
if( $WidgetCache->load_widget( $code ) )
145
$objtype = $code.'_Widget';
146
$edited_ComponentWidget = new $objtype();
150
debug_die( 'Requested widget not found' );
155
if( ! $Plugin = & $Plugins->get_by_code( $code ) )
157
debug_die( 'Requested plugin not found' );
159
if( ! $Plugins->has_event( $Plugin->ID, 'TemplateTag' ) )
161
debug_die( 'Requested plugin does not support TemplateTag' );
163
$edited_ComponentWidget = new ComponentWidget( NULL, 'plugin', $code, array() );
167
debug_die( 'Unhandled widget type' );
170
$edited_ComponentWidget->set( 'coll_ID', $Blog->ID );
171
$edited_ComponentWidget->set( 'sco_name', $container );
172
$edited_ComponentWidget->set( 'enabled', 1 );
175
$edited_ComponentWidget->dbinsert();
177
$Messages->add( sprintf( T_('Widget «%s» has been added to container «%s».'),
178
$edited_ComponentWidget->get_name(), T_($container) ), 'success' );
180
switch( $display_mode )
183
send_javascript_message( array(
184
'addNewWidgetCallback' => array(
185
$edited_ComponentWidget->ID,
187
$edited_ComponentWidget->get( 'order' ),
188
$edited_ComponentWidget->get_name(),
190
// Open widget settings:
191
'editWidget' => array(
192
'wi_ID_'.$edited_ComponentWidget->ID,
198
default : // take usual action
199
header_redirect( '?ctrl=widgets&action=edit&wi_ID='.$edited_ComponentWidget->ID );
207
$edited_ComponentWidget->load_from_Request();
209
if( ! param_errors_detected() )
210
{ // Update settings:
211
$edited_ComponentWidget->dbupdate();
212
$Messages->add( T_('Widget settings have been updated'), 'success' );
213
switch( $display_mode )
215
case 'js' : // js reply
216
$edited_ComponentWidget->init_display( array() );
217
send_javascript_message(array( 'widgetSettingsCallback' => array( $edited_ComponentWidget->ID, $edited_ComponentWidget->get_desc_for_list() ), 'closeWidgetSettings' => array() ), true );
222
elseif( $display_mode == 'js' )
223
{ // send errors back as js
224
send_javascript_message( array(), true );
230
// Move the widget up:
232
$order = $edited_ComponentWidget->order;
235
// Get the previous element
236
$row = $DB->get_row( 'SELECT *
238
WHERE wi_coll_ID = '.$Blog->ID.'
239
AND wi_sco_name = '.$DB->quote($edited_ComponentWidget->sco_name).'
240
AND wi_order < '.$order.'
241
ORDER BY wi_order DESC
245
$prev_ComponentWidget = new ComponentWidget( $row );
246
$prev_order = $prev_ComponentWidget->order;
248
$edited_ComponentWidget->set( 'order', 0 ); // Temporary
249
$edited_ComponentWidget->dbupdate();
251
$prev_ComponentWidget->set( 'order', $order );
252
$prev_ComponentWidget->dbupdate();
254
$edited_ComponentWidget->set( 'order', $prev_order );
255
$edited_ComponentWidget->dbupdate();
262
// Move the widget down:
264
$order = $edited_ComponentWidget->order;
267
// Get the next element
268
$row = $DB->get_row( 'SELECT *
270
WHERE wi_coll_ID = '.$Blog->ID.'
271
AND wi_sco_name = '.$DB->quote($edited_ComponentWidget->sco_name).'
272
AND wi_order > '.$order.'
273
ORDER BY wi_order ASC
277
$next_ComponentWidget = new ComponentWidget( $row );
278
$next_order = $next_ComponentWidget->order;
280
$edited_ComponentWidget->set( 'order', 0 ); // Temporary
281
$edited_ComponentWidget->dbupdate();
283
$next_ComponentWidget->set( 'order', $order );
284
$next_ComponentWidget->dbupdate();
286
$edited_ComponentWidget->set( 'order', $next_order );
287
$edited_ComponentWidget->dbupdate();
294
// Enable or disable the widget:
295
$enabled = $edited_ComponentWidget->get( 'enabled' );
296
$edited_ComponentWidget->set( 'enabled', (int)! $enabled );
297
$edited_ComponentWidget->dbupdate();
301
$msg = T_( 'Widget has been disabled.' );
117
// add a widget to a container
118
if( !in_array( $container, $container_list ) )
120
$Messages->add( T_('WARNING: you are adding to a container that does not seem to be part of the current template.'), 'error' );
126
// Check the requested core widget is valid
127
$WidgetCache = & get_Cache( 'WidgetCache' );
128
if( $WidgetCache->load_widget( $code ) )
130
$objtype = $code.'_Widget';
131
$edited_ComponentWidget = new $objtype();
305
$msg = T_( 'Widget has been enabled.' );
307
$Messages->add( $msg, 'success' );
309
if ( $display_mode == 'js' )
312
send_javascript_message( array( 'doToggle' => array( $edited_ComponentWidget->ID, (int)! $enabled ) ) );
135
debug_die( 'Requested widget not found' );
140
if( ! $Plugin = & $Plugins->get_by_code( $code ) )
142
debug_die( 'Requested plugin not found' );
144
if( ! $Plugins->has_event( $Plugin->ID, 'TemplateTag' ) )
146
debug_die( 'Requested plugin does not support TemplateTag' );
148
$edited_ComponentWidget = new ComponentWidget( NULL, 'plugin', $code, array() );
152
debug_die( 'Unhandled widget type' );
155
$edited_ComponentWidget->set( 'coll_ID', $Blog->ID );
156
$edited_ComponentWidget->set( 'sco_name', $container );
157
$edited_ComponentWidget->set( 'enabled', 1 );
159
// insert into database
160
$edited_ComponentWidget->dbinsert();
162
$Messages->add( sprintf( T_('Widget «%s» has been added to container «%s».'),
163
$edited_ComponentWidget->get_name(), T_($container) ), 'success' );
165
switch( $display_mode )
168
send_javascript_message(
170
'addNewWidgetCallback' => array(
171
$edited_ComponentWidget->ID,
173
$edited_ComponentWidget->get( 'order' ),
174
$edited_ComponentWidget->get_name(),
176
// open widget settings
177
'editWidget' => array(
178
'wi_ID_'.$edited_ComponentWidget->ID,
187
header_redirect( '?ctrl=widgets&action=edit&wi_ID='.$edited_ComponentWidget->ID );
194
$edited_ComponentWidget->load_from_Request();
196
if( ! param_errors_detected() )
199
$edited_ComponentWidget->dbupdate();
200
$Messages->add( T_('Widget settings have been updated'), 'success' );
201
switch( $display_mode )
205
$edited_ComponentWidget->init_display( array() );
206
send_javascript_message( array( 'widgetSettingsCallback' => array( $edited_ComponentWidget->ID, $edited_ComponentWidget->get_desc_for_list() ), 'closeWidgetSettings' => array() ), true );
211
elseif( $display_mode == 'js' )
213
// send errors back as js
214
send_javascript_message( array(), true );
218
// Move the widget up
220
$order = $edited_ComponentWidget->order;
222
// Get the previous element
223
$row = $DB->get_row( 'SELECT * FROM T_widget WHERE wi_coll_ID = '.$Blog->ID.'
224
AND wi_sco_name = '.$DB->quote( $edited_ComponentWidget->sco_name ).'
225
AND wi_order < '.$order.' ORDER BY wi_order DESC LIMIT 0, 1' );
226
if( ! empty( $row ) )
228
$prev_ComponentWidget = new ComponentWidget( $row );
229
$prev_order = $prev_ComponentWidget->order;
230
$edited_ComponentWidget->set( 'order', 0 ); // Temporary
231
$edited_ComponentWidget->dbupdate();
232
$prev_ComponentWidget->set( 'order', $order );
233
$prev_ComponentWidget->dbupdate();
234
$edited_ComponentWidget->set( 'order', $prev_order );
235
$edited_ComponentWidget->dbupdate();
240
// Move the widget down
242
$order = $edited_ComponentWidget->order;
244
// Get the next element
245
$row = $DB->get_row( 'SELECT * FROM T_widget WHERE wi_coll_ID = '.$Blog->ID.'
246
AND wi_sco_name = '.$DB->quote( $edited_ComponentWidget->sco_name ).'
247
AND wi_order > '.$order.' ORDER BY wi_order ASC LIMIT 0, 1' );
248
if( ! empty( $row ) )
250
$next_ComponentWidget = new ComponentWidget( $row );
251
$next_order = $next_ComponentWidget->order;
252
$edited_ComponentWidget->set( 'order', 0 ); // Temporary
253
$edited_ComponentWidget->dbupdate();
254
$next_ComponentWidget->set( 'order', $order );
255
$next_ComponentWidget->dbupdate();
256
$edited_ComponentWidget->set( 'order', $next_order );
257
$edited_ComponentWidget->dbupdate();
262
// Enable or disable the widget
264
$enabled = $edited_ComponentWidget->get( 'enabled' );
265
$edited_ComponentWidget->set( 'enabled', (int)! $enabled );
266
$edited_ComponentWidget->dbupdate();
270
$msg = T_('Widget has been disabled.');
274
$msg = T_('Widget has been enabled.');
276
$Messages->add( $msg, 'success' );
278
if( $display_mode == 'js' )
281
send_javascript_message( array( 'doToggle' => array( $edited_ComponentWidget->ID, (int)! $enabled ) ) );
285
// Remove a widget from container
317
// Remove a widget from container:
318
$msg = sprintf( T_('Widget «%s» removed.'), $edited_ComponentWidget->get_name() );
319
$edited_widget_ID = $edited_ComponentWidget->ID;
320
$edited_ComponentWidget->dbdelete( true );
321
unset( $edited_ComponentWidget );
322
forget_param( 'wi_ID' );
323
$Messages->add( $msg, 'success' );
325
switch( $display_mode )
287
$msg = sprintf( T_('Widget «%s» removed.'), $edited_ComponentWidget->get_name() );
288
$edited_widget_ID = $edited_ComponentWidget->ID;
289
$edited_ComponentWidget->dbdelete( true );
290
unset( $edited_ComponentWidget );
291
forget_param( 'wi_ID' );
292
$Messages->add( $msg, 'success' );
294
switch( $display_mode )
296
// js call, return success message
298
send_javascript_message( array( 'doDelete' => $edited_widget_ID ) );
304
// PREVENT RELOAD & Switch to list mode
305
header_redirect( '?ctrl=widgets&blog='.$blog );
317
// Reset the current orders and make container names temp to avoid duplicate entry errors
318
$DB->query( 'UPDATE T_widget SET wi_order = wi_order * -1,
319
wi_sco_name = CONCAT( \'temp_\', wi_sco_name ) WHERE wi_coll_ID = '.$Blog->ID );
321
foreach( $containers as $container => $widgets )
323
// loop through each container and set new order
325
foreach( $widgets as $widget )
327
case 'js' : // js call : return success message
328
send_javascript_message( array( 'doDelete' => $edited_widget_ID ) );
332
default : // take usual action
333
// PREVENT RELOAD & Switch to list mode:
334
header_redirect( '?ctrl=widgets&blog='.$blog );
342
case 're-order' : // js request
345
// Reset the current orders and make container names temp to avoid duplicate entry errors
346
$DB->query( 'UPDATE T_widget
347
SET wi_order = wi_order * -1,
348
wi_sco_name = CONCAT( \'temp_\', wi_sco_name )
349
WHERE wi_coll_ID = '.$Blog->ID );
351
foreach( $containers as $container => $widgets )
352
{ // loop through each container and set new order
353
$order = 0; // reset counter for this container
354
foreach( $widgets as $widget )
355
{ // loop through each widget
356
if( $widget = preg_replace( '~[^0-9]~', '', $widget ) )
359
$DB->query( 'UPDATE T_widget
360
SET wi_order = '.$order.',
361
wi_sco_name = '.$DB->quote( $container ).'
362
WHERE wi_ID = '.$widget.'
363
AND wi_coll_ID = '.$Blog->ID ); // Doh! Don't trust the client request!!
327
// loop through each widget
328
if( $widget = preg_replace( '~[^0-9]~', '', $widget ) )
332
$DB->query( 'UPDATE T_widget SET wi_order = '.$order.', wi_sco_name = '.$DB->quote( $container ).'
333
WHERE wi_ID = '.$widget.' AND wi_coll_ID = '.$Blog->ID ); // Don't trust the client request!!
368
// Cleanup deleted widgets and empty temp containers
369
$DB->query( 'DELETE FROM T_widget
371
AND wi_coll_ID = '.$Blog->ID ); // Doh! Don't touch other blogs!
375
$Messages->add( T_( 'Widgets updated' ), 'success' );
376
send_javascript_message( array( 'sendWidgetOrderCallback' => array( 'blog='.$Blog->ID ) ) ); // exits() automatically
338
// Cleanup deleted widgets and empty temp containers
339
$DB->query( 'DELETE FROM T_widget WHERE wi_order < 1 AND wi_coll_ID = '.$Blog->ID );
341
$Messages->add( T_('Widgets updated'), 'success' );
342
// exits() automatically
343
send_javascript_message( array( 'sendWidgetOrderCallback' => array( 'blog='.$Blog->ID ) ) );
380
debug_die( 'Action: unhandled action' );
347
debug_die( 'Action: unhandled action' );
383
350
if( $display_mode == 'normal' )
384
{ // this is a normal (not a JS) request
352
// this is a normal (not a JS) request
385
353
// fp> This probably shouldn't be handled like this but with $mode
387
* Display page header, menus & messages:
354
// Display page header, menus & messages
389
355
$AdminUI->set_coll_list_params( 'blog_properties', 'edit', array( 'ctrl' => 'widgets' ),
390
T_('List'), '?ctrl=collections&blog=0' );
356
T_('List'), '?ctrl=collections&blog=0' );
392
357
$AdminUI->set_path( 'blogs', 'widgets' );
394
359
// load the js and css required to make the magic work
395
360
add_js_headline( '
397
* @internal T_ array of translation strings required by the UI
361
// array of translation strings required by the UI
399
362
var T_arr = new Array();
400
363
T_arr["Changes pending"] = \''.TS_( 'Changes pending' ).'\';
401
364
T_arr["Saving changes"] = \''.TS_( 'Saving changes' ).'\';
403
366
T_arr["Update cancelled"] = \''.TS_( 'Update cancelled' ).'\';
404
367
T_arr["Update Paused"] = \''.TS_( 'Update Paused' ).'\';
407
* Image tags for the JavaScript widget UI.
409
* @internal Tblue> We get the whole img tags here (easier).
411
var enabled_icon_tag = \''.get_icon( 'enabled', 'imgtag', array( 'title' => T_( 'The widget is enabled.' ) ) ).'\';
412
var disabled_icon_tag = \''.get_icon( 'disabled', 'imgtag', array( 'title' => T_( 'The widget is disabled.' ) ) ).'\';
413
var activate_icon_tag = \''.get_icon( 'activate', 'imgtag', array( 'title' => T_( 'Enable this widget!' ) ) ).'\';
414
var deactivate_icon_tag = \''.get_icon( 'deactivate', 'imgtag', array( 'title' => T_( 'Disable this widget!' ) ) ).'\';
369
// Image tags for the JavaScript widget UI.
370
// Note Tblue> We get the whole img tags here (easier).
371
var enabled_icon_tag = \''.get_icon( 'enabled', 'imgtag', array( 'title' => T_('The widget is enabled.') ) ).'\';
372
var disabled_icon_tag = \''.get_icon( 'disabled', 'imgtag', array( 'title' => T_('The widget is disabled.') ) ).'\';
373
var activate_icon_tag = \''.get_icon( 'activate', 'imgtag', array( 'title' => T_('Enable this widget!') ) ).'\';
374
var deactivate_icon_tag = \''.get_icon( 'deactivate', 'imgtag', array( 'title' => T_('Disable this widget!') ) ).'\';
416
375
var b2evo_dispatcher_url = "'.$admin_url.'";' );
417
376
require_js( '#jqueryUI#' ); // auto requires jQuery
418
377
require_js( 'communication.js' ); // auto requires jQuery
419
378
require_js( 'blog_widgets.js' );
420
379
require_css( 'blog_widgets.css' );
423
// Display <html><head>...</head> section! (Note: should be done early if actions do not redirect)
381
// Display <html><head>...</head> section (should be done early if actions do not redirect)
424
382
$AdminUI->disp_html_head();
426
// Display title, menu, messages, etc. (Note: messages MUST be displayed AFTER the actions)
383
// Display title, menu, messages, etc... (messages MUST be displayed AFTER the actions)
427
384
$AdminUI->disp_body_top();
433
388
switch( $action )
441
// Begin payload block:
442
$AdminUI->disp_payload_begin();
445
$AdminUI->disp_view( 'widgets/views/_widget_list_available.view.php' );
447
// End payload block:
448
$AdminUI->disp_payload_end();
395
// Begin payload block
396
$AdminUI->disp_payload_begin();
399
$AdminUI->disp_view( 'widgets/views/_widget_list_available.view.php' );
402
$AdminUI->disp_payload_end();
453
case 'update': // on error
454
switch( $display_mode )
456
case 'js' : // js request
459
$AdminUI->disp_view( 'widgets/views/_widget.form.php' );
460
$output = ob_get_clean();
461
send_javascript_message( array( 'widgetSettings' => $output ) );
465
default : // take usual action
466
// Begin payload block:
467
$AdminUI->disp_payload_begin();
470
$AdminUI->disp_view( 'widgets/views/_widget.form.php' );
472
// End payload block:
473
$AdminUI->disp_payload_end();
406
case 'update': // on error
407
switch( $display_mode )
413
$AdminUI->disp_view( 'widgets/views/_widget.form.php' );
414
$output = ob_get_clean();
415
send_javascript_message( array( 'widgetSettings' => $output ) );
421
// Begin payload block
422
$AdminUI->disp_payload_begin();
425
$AdminUI->disp_view( 'widgets/views/_widget.form.php' );
428
$AdminUI->disp_payload_end();
481
// Begin payload block:
482
$AdminUI->disp_payload_begin();
486
// this will be enabled if js available:
487
echo '<div class="available_widgets">'."\n";
488
echo '<div class="available_widgets_toolbar"><a href="#" class="rollover floatright" style="padding: 1px 0;">'.get_icon('close').'</a>'.T_( 'Select widget to add:' ).'</div>'."\n";
489
echo '<div id="available_widgets_inner">'."\n";
490
$AdminUI->disp_view( 'widgets/views/_widget_list_available.view.php' );
491
echo '</div></div>'."\n";
493
<script type="text/javascript">
495
var blog = '.$Blog->ID.';
501
$AdminUI->disp_view( 'widgets/views/_widget_list.view.php' );
503
// End payload block:
504
$AdminUI->disp_payload_end();
435
// Begin payload block
436
$AdminUI->disp_payload_begin();
439
// this will be enabled if js available
440
echo '<div class="available_widgets">'."\n";
441
echo '<div class="available_widgets_toolbar"><a href="#" class="rollover floatright" style="padding: 1px 0;">'.get_icon('close').'</a>'.T_('Select widget to add:').'</div>'."\n";
442
echo '<div id="available_widgets_inner">'."\n";
443
$AdminUI->disp_view( 'widgets/views/_widget_list_available.view.php' );
444
echo '</div></div>'."\n";
446
<script type="text/javascript">
448
var blog = '.$Blog->ID.';
454
$AdminUI->disp_view( 'widgets/views/_widget_list.view.php' );
457
$AdminUI->disp_payload_end();
508
// Display body bottom, debug info and close </html>:
461
// Display body bottom, debug info, close </html>
509
462
$AdminUI->disp_global_footer();