b2evolution PHP Cross Reference Blogging Systems

Source: /inc/widgets/widgets.ctrl.php - 605 lines - 17523 bytes - Text - Print

Description: This file implements the UI controller for managing widgets inside of a blog. b2evolution - {@link http://b2evolution.net/} Released under GNU GPL License - {@link http://b2evolution.net/about/license.html}

   1  <?php
   2  /**
   3   * This file implements the UI controller for managing widgets inside of a blog.
   4   *
   5   * b2evolution - {@link http://b2evolution.net/}
   6   * Released under GNU GPL License - {@link http://b2evolution.net/about/license.html}
   7   * @copyright (c)2003-2014 by Francois Planque - {@link http://fplanque.com/}
   8   *
   9   * {@internal Open Source relicensing agreement:
  10   * }}
  11   *
  12   * {@internal Below is a list of authors who have contributed to design/coding of this file: }}
  13   * @author fplanque: Francois PLANQUE.
  14   *
  15   * @package admin
  16   *
  17   * @version $Id: widgets.ctrl.php 6136 2014-03-08 07:59:48Z manuel $
  18   */
  19  if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
  20  
  21  /**
  22   * @var AdminUI
  23   */
  24  global $AdminUI;
  25  /**
  26   * @var Plugins
  27   */
  28  global $Plugins;
  29  
  30  // Memorize this as the last "tab" used in the Blog Settings:
  31  $UserSettings->set( 'pref_coll_settings_tab', 'widgets' );
  32  $UserSettings->dbupdate();
  33  
  34  load_class( 'widgets/model/_widget.class.php', 'ComponentWidget' );
  35  
  36  
  37  // Check permissions on requested blog and autoselect an appropriate blog if necessary.
  38  // This will prevent a fat error when switching tabs and you have restricted perms on blog properties.
  39  if( $selected = autoselect_blog( 'blog_properties', 'edit' ) ) // Includes perm check
  40  {    // We have a blog to work on:
  41  
  42      if( set_working_blog( $selected ) )    // set $blog & memorize in user prefs
  43      {    // Selected a new blog:
  44          $BlogCache = & get_BlogCache();
  45          /**
  46           * @var Blog
  47           */
  48          $Blog = & $BlogCache->get_by_ID( $blog );
  49      }
  50  
  51      /**
  52       * @var Blog
  53       */
  54      $edited_Blog = & $Blog;
  55  }
  56  else
  57  {    // We could not find a blog we have edit perms on...
  58      // Note: we may still have permission to edit categories!!
  59      // redirect to blog list:
  60      header_redirect( '?ctrl=collections' );
  61      // EXITED:
  62      $Messages->add( T_('Sorry, you have no permission to edit blog properties.'), 'error' );
  63      $action = 'nil';
  64      $tab = '';
  65  }
  66  
  67  param( 'action', 'string', 'list' );
  68  param( 'display_mode', 'string', 'normal' );
  69  $display_mode = ( in_array( $display_mode, array( 'js', 'normal' ) ) ? $display_mode : 'normal' );
  70  if( $display_mode == 'js' )
  71  {    // Javascript in debug mode conflicts/fails.
  72      // fp> TODO: either fix the debug javascript or have an easy way to disable JS in the debug output.
  73      $debug = 0;
  74      $debug_jslog = false;
  75  }
  76  // This should probably be handled with teh existing $mode var
  77  
  78  /*
  79   * Init the objects we want to work on.
  80   */
  81  switch( $action )
  82  {
  83       case 'nil':
  84       case 'list':
  85       case 'reload':
  86          // Do nothing
  87          break;
  88  
  89      case 'create':
  90          param( 'type', 'string', true );
  91          param( 'code', 'string', true );
  92      case 'new':
  93          param( 'container', 'string', true, true );    // memorize
  94          break;
  95  
  96      case 're-order' : // js request
  97          param( 'container_list', 'string', true );
  98          $containers_list = explode( ',', $container_list );
  99          $containers = array();
 100          foreach( $containers_list as $a_container )
 101          {    // add each container and grab its widgets:
 102              if( $container_name = trim( str_replace( array( 'container_', '_' ), array( '', ' ' ), $a_container ), ',' ) )
 103              {
 104                  $containers[ $container_name ] = explode( ',', param( trim( $a_container, ',' ), 'string', true ) );
 105              }
 106          }
 107          break;
 108  
 109      case 'edit':
 110      case 'update':
 111      case 'delete':
 112      case 'move_up':
 113      case 'move_down':
 114      case 'toggle':
 115          param( 'wi_ID', 'integer', true );
 116          $WidgetCache = & get_WidgetCache();
 117          $edited_ComponentWidget = & $WidgetCache->get_by_ID( $wi_ID );
 118          // Take blog from here!
 119          // echo $edited_ComponentWidget->coll_ID;
 120           set_working_blog( $edited_ComponentWidget->coll_ID );
 121          $BlogCache = & get_BlogCache();
 122          /**
 123          * @var Blog
 124          */
 125          $Blog = & $BlogCache->get_by_ID( $blog );
 126  
 127          break;
 128  
 129      default:
 130          debug_die( 'Init objects: unhandled action' );
 131  }
 132  
 133  if( ! valid_blog_requested() )
 134  {
 135      debug_die( 'Invalid blog requested' );
 136  }
 137  
 138  switch( $display_mode )
 139  {
 140      case 'js' : // js response needed
 141  // fp> when does this happen -- should be documented
 142          if( !$current_User->check_perm( 'blog_properties', 'edit', false, $blog ) )
 143          {    // user doesn't have permissions
 144              $Messages->add( T_('You do not have permission to perform this action' ) );
 145  // fp>does this only happen when we try to edit settings. The hardcoded 'closeWidgetSettings' response looks bad.
 146              send_javascript_message( array( 'closeWidgetSettings' => array() ) );
 147          }
 148          break;
 149  
 150      case 'normal':
 151      default : // take usual approach
 152          $current_User->check_perm( 'blog_properties', 'edit', true, $blog );
 153  }
 154  
 155  // Get Skin used by current Blog:
 156  $blog_normal_skin_ID = $Blog->get_setting( 'normal_skin_ID' );
 157  $SkinCache = & get_SkinCache();
 158  $Skin = & $SkinCache->get_by_ID( $blog_normal_skin_ID );
 159  // Make sure containers are loaded for that skin:
 160  $container_list = $Skin->get_containers();
 161  
 162  
 163  /**
 164   * Perform action:
 165   */
 166  switch( $action )
 167  {
 168       case 'nil':
 169       case 'new':
 170       case 'edit':
 171          // Do nothing
 172          break;
 173  
 174      case 'create':
 175          // Add a Widget to container:
 176  
 177          // Check that this action request is not a CSRF hacked request:
 178          $Session->assert_received_crumb( 'widget' );
 179  
 180          if( !in_array( $container, $container_list ) )
 181          {
 182              $Messages->add( T_('WARNING: you are adding to a container that does not seem to be part of the current skin.'), 'error' );
 183          }
 184  
 185          switch( $type )
 186          {
 187              case 'core':
 188                  // Check the requested core widget is valid:
 189                  $objtype = $code.'_Widget';
 190                  load_class( 'widgets/widgets/_'.$code.'.widget.php', $objtype );
 191                  $edited_ComponentWidget = new $objtype();
 192                  break;
 193  
 194              case 'plugin':
 195                  if( ! $Plugin = & $Plugins->get_by_code( $code ) )
 196                  {
 197                      debug_die( 'Requested plugin not found' );
 198                  }
 199                  if( ! $Plugins->has_event( $Plugin->ID, 'SkinTag' ) )
 200                  {
 201                      debug_die( 'Requested plugin does not support SkinTag' );
 202                  }
 203                  $edited_ComponentWidget = new ComponentWidget( NULL, 'plugin', $code );
 204                  break;
 205  
 206              default:
 207                  debug_die( 'Unhandled widget type' );
 208          }
 209  
 210          $edited_ComponentWidget->set( 'coll_ID', $Blog->ID );
 211          $edited_ComponentWidget->set( 'sco_name', $container );
 212          $edited_ComponentWidget->set( 'enabled', 1 );
 213  
 214          // INSERT INTO DB:
 215          $edited_ComponentWidget->dbinsert();
 216  
 217          $Messages->add( sprintf( T_('Widget &laquo;%s&raquo; has been added to container &laquo;%s&raquo;.'),
 218                      $edited_ComponentWidget->get_name(), T_($container)    ), 'success' );
 219  
 220          switch( $display_mode )
 221          {
 222              case 'js' :    // this is a js call, lets return the settings page -- fp> what do you mean "settings page" ?
 223                  // fp> wthis will visually live insert the new widget into the container; it probably SHOULD open the edit properties right away
 224                  send_javascript_message( array(
 225                      'addNewWidgetCallback' => array(
 226                          $edited_ComponentWidget->ID,
 227                          $container,
 228                          $edited_ComponentWidget->get( 'order' ),
 229                          $edited_ComponentWidget->get_name(),
 230                      ),
 231                      // Open widget settings:
 232                      'editWidget' => array(
 233                          'wi_ID_'.$edited_ComponentWidget->ID,
 234                      ),
 235                  ) );
 236                  break;
 237  
 238              case 'normal' :
 239              default : // take usual action
 240                  header_redirect( '?ctrl=widgets&action=edit&wi_ID='.$edited_ComponentWidget->ID );
 241                  break;
 242          }
 243          break;
 244  
 245  
 246      case 'update':
 247          // Update Settings
 248  
 249          // Check that this action request is not a CSRF hacked request:
 250          $Session->assert_received_crumb( 'widget' );
 251  
 252          $edited_ComponentWidget->load_from_Request();
 253  
 254          if(    ! param_errors_detected() )
 255          {    // Update settings:
 256              $edited_ComponentWidget->dbupdate();
 257              $Messages->add( T_('Widget settings have been updated'), 'success' );
 258              switch( $display_mode )
 259              {
 260                  case 'js' : // js reply
 261                      $edited_ComponentWidget->init_display( array() );
 262                      send_javascript_message(array( 'widgetSettingsCallback' => array( $edited_ComponentWidget->ID, $edited_ComponentWidget->get_desc_for_list() ), 'closeWidgetSettings' => array() ), true );
 263                      break;
 264              }
 265              $action = 'list';
 266              $Session->set( 'fadeout_id', $edited_ComponentWidget->ID );
 267              header_redirect( '?ctrl=widgets&blog='.$Blog->ID, 303 );
 268          }
 269          elseif( $display_mode == 'js' )
 270          { // send errors back as js
 271              send_javascript_message( array(), true );
 272          }
 273          break;
 274  
 275  
 276      case 'move_up':
 277          // Move the widget up:
 278  
 279          // Check that this action request is not a CSRF hacked request:
 280          $Session->assert_received_crumb( 'widget' );
 281  
 282          $order = $edited_ComponentWidget->order;
 283          $DB->begin();
 284  
 285           // Get the previous element
 286          $row = $DB->get_row( 'SELECT *
 287                                                          FROM T_widget
 288                                                       WHERE wi_coll_ID = '.$Blog->ID.'
 289                                                            AND wi_sco_name = '.$DB->quote($edited_ComponentWidget->sco_name).'
 290                                                           AND wi_order < '.$order.'
 291                                                       ORDER BY wi_order DESC
 292                                                       LIMIT 0,1' );
 293          if( !empty( $row) )
 294          {
 295              $prev_ComponentWidget = new ComponentWidget( $row );
 296              $prev_order = $prev_ComponentWidget->order;
 297  
 298              $edited_ComponentWidget->set( 'order', 0 );    // Temporary
 299              $edited_ComponentWidget->dbupdate();
 300  
 301              $prev_ComponentWidget->set( 'order', $order );
 302              $prev_ComponentWidget->dbupdate();
 303  
 304              $edited_ComponentWidget->set( 'order', $prev_order );
 305              $edited_ComponentWidget->dbupdate();
 306  
 307          }
 308          $DB->commit();
 309          break;
 310  
 311      case 'move_down':
 312          // Move the widget down:
 313  
 314          // Check that this action request is not a CSRF hacked request:
 315          $Session->assert_received_crumb( 'widget' );
 316  
 317          $order = $edited_ComponentWidget->order;
 318          $DB->begin();
 319  
 320           // Get the next element
 321          $row = $DB->get_row( 'SELECT *
 322                                                          FROM T_widget
 323                                                       WHERE wi_coll_ID = '.$Blog->ID.'
 324                                                            AND wi_sco_name = '.$DB->quote($edited_ComponentWidget->sco_name).'
 325                                                           AND wi_order > '.$order.'
 326                                                       ORDER BY wi_order ASC
 327                                                       LIMIT 0,1' );
 328          if( !empty( $row ) )
 329          {
 330              $next_ComponentWidget = new ComponentWidget( $row );
 331              $next_order = $next_ComponentWidget->order;
 332  
 333              $edited_ComponentWidget->set( 'order', 0 );    // Temporary
 334              $edited_ComponentWidget->dbupdate();
 335  
 336              $next_ComponentWidget->set( 'order', $order );
 337              $next_ComponentWidget->dbupdate();
 338  
 339              $edited_ComponentWidget->set( 'order', $next_order );
 340              $edited_ComponentWidget->dbupdate();
 341  
 342          }
 343          $DB->commit();
 344          break;
 345  
 346      case 'toggle':
 347          // Enable or disable the widget:
 348  
 349          // Check that this action request is not a CSRF hacked request:
 350          $Session->assert_received_crumb( 'widget' );
 351  
 352          $enabled = $edited_ComponentWidget->get( 'enabled' );
 353          $edited_ComponentWidget->set( 'enabled', (int)! $enabled );
 354          $edited_ComponentWidget->dbupdate();
 355  
 356          if ( $enabled )
 357          {
 358              $msg = T_( 'Widget has been disabled.' );
 359          }
 360          else
 361          {
 362              $msg = T_( 'Widget has been enabled.' );
 363          }
 364          $Messages->add( $msg, 'success' );
 365  
 366          if ( $display_mode == 'js' )
 367          {
 368              // EXITS:
 369              send_javascript_message( array( 'doToggle' => array( $edited_ComponentWidget->ID, (int)! $enabled ) ) );
 370          }
 371          header_redirect( '?ctrl=widgets&blog='.$Blog->ID, 303 );
 372          break;
 373  
 374      case 'delete':
 375          // Remove a widget from container:
 376  
 377          // Check that this action request is not a CSRF hacked request:
 378          $Session->assert_received_crumb( 'widget' );
 379  
 380          $msg = sprintf( T_('Widget &laquo;%s&raquo; removed.'), $edited_ComponentWidget->get_name() );
 381          $edited_widget_ID = $edited_ComponentWidget->ID;
 382          $edited_ComponentWidget->dbdelete( true );
 383          unset( $edited_ComponentWidget );
 384          forget_param( 'wi_ID' );
 385          $Messages->add( $msg, 'success' );
 386  
 387          switch( $display_mode )
 388          {
 389              case 'js' :    // js call : return success message
 390                  send_javascript_message( array( 'doDelete' => $edited_widget_ID ) );
 391                  break;
 392  
 393              case 'normal' :
 394              default : // take usual action
 395                  // PREVENT RELOAD & Switch to list mode:
 396                  header_redirect( '?ctrl=widgets&blog='.$blog );
 397                  break;
 398          }
 399          break;
 400  
 401       case 'list':
 402          break;
 403  
 404       case 're-order' : // js request
 405           // Check that this action request is not a CSRF hacked request:
 406          $Session->assert_received_crumb( 'widget' );
 407  
 408           $DB->begin();
 409  
 410           // Reset the current orders and make container names temp to avoid duplicate entry errors
 411          $DB->query( 'UPDATE T_widget
 412                                          SET wi_order = wi_order * -1,
 413                                                  wi_sco_name = CONCAT( \'temp_\', wi_sco_name )
 414                                      WHERE wi_coll_ID = '.$Blog->ID );
 415  
 416          foreach( $containers as $container => $widgets )
 417          {    // loop through each container and set new order
 418              $order = 0; // reset counter for this container
 419              foreach( $widgets as $widget )
 420              {    // loop through each widget
 421                  if( $widget = preg_replace( '~[^0-9]~', '', $widget ) )
 422                  { // valid widget id
 423                      $order++;
 424                      $DB->query( 'UPDATE T_widget
 425                                                      SET wi_order = '.$order.',
 426                                                              wi_sco_name = '.$DB->quote( $container ).'
 427                                                  WHERE wi_ID = '.$widget.'
 428                                                    AND wi_coll_ID = '.$Blog->ID );    // Doh! Don't trust the client request!!
 429                  }
 430              }
 431          }
 432  
 433          // Cleanup deleted widgets and empty temp containers
 434          $DB->query( 'DELETE FROM T_widget
 435                                      WHERE wi_order < 1
 436                                          AND wi_coll_ID = '.$Blog->ID ); // Doh! Don't touch other blogs!
 437  
 438          $DB->commit();
 439  
 440           $Messages->add( T_( 'Widgets updated' ), 'success' );
 441           send_javascript_message( array( 'sendWidgetOrderCallback' => array( 'blog='.$Blog->ID ) ) ); // exits() automatically
 442           break;
 443  
 444  
 445      case 'reload':
 446          // Reload containers:
 447  
 448          // Check that this action request is not a CSRF hacked request:
 449          $Session->assert_received_crumb( 'widget' );
 450  
 451           // Check permission:
 452          $current_User->check_perm( 'options', 'edit', true );
 453  
 454          $SkinCache = & get_SkinCache();
 455          /**
 456           * @var Skin
 457           */
 458          $edited_Skin = & $SkinCache->get_by_ID( $blog_normal_skin_ID );
 459  
 460          // Look for containers in skin file:
 461          $edited_Skin->discover_containers();
 462  
 463          // Save to DB:
 464          $edited_Skin->db_save_containers();
 465  
 466          header_redirect( '?ctrl=widgets&blog='.$Blog->ID, 303 );
 467          break;
 468  
 469      default:
 470          debug_die( 'Action: unhandled action' );
 471  }
 472  
 473  if( $display_mode == 'normal' )
 474  {    // this is a normal (not a JS) request
 475      // fp> This probably shouldn't be handled like this but with $mode
 476      /**
 477       * Display page header, menus & messages:
 478       */
 479      $AdminUI->set_coll_list_params( 'blog_properties', 'edit', array( 'ctrl' => 'widgets' ),
 480                  T_('All'), '?ctrl=collections&amp;blog=0' );
 481  
 482      $AdminUI->set_path( 'blogs', 'widgets' );
 483  
 484      // load the js and css required to make the magic work
 485      add_js_headline( '
 486      /**
 487       * @internal T_ array of translation strings required by the UI
 488       */
 489      var T_arr = new Array();
 490      T_arr["Changes pending"] = \''.TS_( 'Changes pending' ).'\';
 491      T_arr["Saving changes"] = \''.TS_( 'Saving changes' ).'\';
 492      T_arr["Widget order unchanged"] = \''.TS_( 'Widget order unchanged' ).'\';
 493      T_arr["Update cancelled"] = \''.TS_( 'Update cancelled' ).'\';
 494      T_arr["Update Paused"] = \''.TS_( 'Update Paused' ).'\';
 495  
 496      /**
 497       * Image tags for the JavaScript widget UI.
 498       *
 499       * @internal Tblue> We get the whole img tags here (easier).
 500       */
 501      var enabled_icon_tag = \''.get_icon( 'enabled', 'imgtag', array( 'title' => T_( 'The widget is enabled.' ) ) ).'\';
 502      var disabled_icon_tag = \''.get_icon( 'disabled', 'imgtag', array( 'title' => T_( 'The widget is disabled.' ) ) ).'\';
 503      var activate_icon_tag = \''.get_icon( 'activate', 'imgtag', array( 'title' => T_( 'Enable this widget!' ) ) ).'\';
 504      var deactivate_icon_tag = \''.get_icon( 'deactivate', 'imgtag', array( 'title' => T_( 'Disable this widget!' ) ) ).'\';
 505  
 506      var b2evo_dispatcher_url = "'.$admin_url.'";' );
 507      require_js( '#jqueryUI#' ); // auto requires jQuery
 508      require_js( 'communication.js' ); // auto requires jQuery
 509      require_js( 'blog_widgets.js' );
 510      require_css( 'blog_widgets.css' );
 511  
 512  
 513      $AdminUI->breadcrumbpath_init( true );
 514      $AdminUI->breadcrumbpath_add( T_('Settings'), '?ctrl=coll_settings&amp;blog=$blog$' );
 515      $AdminUI->breadcrumbpath_add( T_('Widgets'), '?ctrl=widgets&amp;blog=$blog$' );
 516  
 517      // Display <html><head>...</head> section! (Note: should be done early if actions do not redirect)
 518      $AdminUI->disp_html_head();
 519  
 520      // Display title, menu, messages, etc. (Note: messages MUST be displayed AFTER the actions)
 521      $AdminUI->disp_body_top();
 522  }
 523  
 524  /**
 525   * Display payload:
 526   */
 527  switch( $action )
 528  {
 529      case 'nil':
 530          // Do nothing
 531          break;
 532  
 533  
 534      case 'new':
 535          // Begin payload block:
 536          $AdminUI->disp_payload_begin();
 537  
 538          // Display VIEW:
 539          $AdminUI->disp_view( 'widgets/views/_widget_list_available.view.php' );
 540  
 541          // End payload block:
 542          $AdminUI->disp_payload_end();
 543          break;
 544  
 545  
 546      case 'edit':
 547      case 'update':    // on error
 548          switch( $display_mode )
 549          {
 550              case 'js' : // js request
 551                  ob_start();
 552                  // Display VIEW:
 553                  $AdminUI->disp_view( 'widgets/views/_widget.form.php' );
 554                  $output = ob_get_clean();
 555                  send_javascript_message( array( 'widgetSettings' => $output ) );
 556                  break;
 557  
 558              case 'normal' :
 559              default : // take usual action
 560                  // Begin payload block:
 561                  $AdminUI->disp_payload_begin();
 562  
 563                  // Display VIEW:
 564                  $AdminUI->disp_view( 'widgets/views/_widget.form.php' );
 565  
 566                  // End payload block:
 567                  $AdminUI->disp_payload_end();
 568                  break;
 569          }
 570          break;
 571  
 572  
 573      case 'list':
 574      default:
 575          // Begin payload block:
 576          $AdminUI->disp_payload_begin();
 577  
 578          // Display VIEW:
 579  
 580          // this will be enabled if js available:
 581          echo '<div class="available_widgets">'."\n";
 582          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";
 583          echo '<div id="available_widgets_inner">'."\n";
 584          $AdminUI->disp_view( 'widgets/views/_widget_list_available.view.php' );
 585          echo '</div></div>'."\n";
 586          echo '
 587          <script type="text/javascript">
 588              <!--
 589              var blog = '.$Blog->ID.';
 590              // -->
 591          </script>
 592          ';
 593  
 594          // Display VIEW:
 595          $AdminUI->disp_view( 'widgets/views/_widget_list.view.php' );
 596  
 597          // End payload block:
 598          $AdminUI->disp_payload_end();
 599          break;
 600  }
 601  
 602  // Display body bottom, debug info and close </html>:
 603  $AdminUI->disp_global_footer();
 604  
 605  ?>

title

Description

title

Description

title

Description

title

title

Body