b2evolution PHP Cross Reference Blogging Systems

Source: /inc/plugins/plugins.ctrl.php - 1059 lines - 32679 bytes - Text - Print

Description: This file implements the UI controller for plugins management. This file is part of the evoCore framework - {@link http://evocore.net/} See also {@link http://sourceforge.net/projects/evocms/}.

   1  <?php
   2  /**
   3   * This file implements the UI controller for plugins management.
   4   *
   5   * This file is part of the evoCore framework - {@link http://evocore.net/}
   6   * See also {@link http://sourceforge.net/projects/evocms/}.
   7   *
   8   * @copyright (c)2003-2014 by Francois Planque - {@link http://fplanque.com/}
   9   * Parts of this file are copyright (c)2004-2006 by Daniel HAHLER - {@link http://thequod.de/contact}.
  10   *
  11   * {@internal License choice
  12   * - If you have received this file as part of a package, please find the license.txt file in
  13   *   the same folder or the closest folder above for complete license terms.
  14   * - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/)
  15   *   then you must choose one of the following licenses before using the file:
  16   *   - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php
  17   *   - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php
  18   * }}
  19   *
  20   * {@internal Open Source relicensing agreement:
  21   * Daniel HAHLER grants Francois PLANQUE the right to license
  22   * Daniel HAHLER's contributions to this file and the b2evolution project
  23   * under any OSI approved OSS license (http://www.opensource.org/licenses/).
  24   * }}
  25   *
  26   * @package admin
  27   *
  28   * {@internal Below is a list of authors who have contributed to design/coding of this file: }}
  29   * @author fplanque: Francois PLANQUE.
  30   * @author blueyed: Daniel HAHLER
  31   *
  32   * @version $Id: plugins.ctrl.php 6136 2014-03-08 07:59:48Z manuel $
  33   */
  34  if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
  35  
  36  global $dispatcher;
  37  
  38  
  39  // Check permission to display:
  40  $current_User->check_perm( 'options', 'view', true );
  41  
  42  // Memorize this as the last "tab" used in the Blog Settings:
  43  $UserSettings->set( 'pref_glob_settings_tab', $ctrl );
  44  $UserSettings->dbupdate();
  45  
  46  
  47  $AdminUI->set_path( 'options', 'plugins' );
  48  
  49  $action = param_action( 'list' );
  50  
  51  $UserSettings->param_Request( 'plugins_disp_avail', 'plugins_disp_avail', 'integer', 0 );
  52  
  53  /**
  54   * @var Plugins_admin
  55   */
  56  $admin_Plugins = & get_Plugins_admin();
  57  $admin_Plugins->restart();
  58  
  59  // Pre-walk list of plugins
  60  while( $loop_Plugin = & $admin_Plugins->get_next() )
  61  {
  62      if( $loop_Plugin->status == 'broken' && ! isset( $admin_Plugins->plugin_errors[$loop_Plugin->ID] ) )
  63      { // The plugin is not "broken" anymore (either the problem got fixed or it was "broken" from a canceled "install_db_schema" action)
  64          // TODO: set this to the previous status (dh)
  65          $Plugins->set_Plugin_status( $loop_Plugin, 'disabled' );
  66      }
  67  }
  68  
  69  
  70  /*
  71   * Action Handling part I
  72   * Actions that delegate to other actions (other than list):
  73   */
  74  switch( $action )
  75  {
  76      case 'del_settings_set':
  77          // Delete a set from an array type setting:
  78          param( 'plugin_ID', 'integer', true );
  79          param( 'set_path' );
  80  
  81          $edit_Plugin = & $admin_Plugins->get_by_ID($plugin_ID);
  82  
  83          load_funcs('plugins/_plugin.funcs.php');
  84          _set_setting_by_path( $edit_Plugin, 'Settings', $set_path, NULL );
  85  
  86          // Don't delete from the db yet. It will be updated in the db when Save button is clicked. It works similar as the async pair of this action
  87          #$edit_Plugin->Settings->dbupdate();
  88  
  89          $action = 'edit_settings';
  90  
  91          break;
  92  
  93      case 'add_settings_set': // delegates to edit_settings
  94          // Add a new set to an array type setting:
  95          param( 'plugin_ID', 'integer', true );
  96          param( 'set_path', 'string', '' );
  97  
  98          $edit_Plugin = & $admin_Plugins->get_by_ID($plugin_ID);
  99  
 100          load_funcs('plugins/_plugin.funcs.php');
 101          _set_setting_by_path( $edit_Plugin, 'Settings', $set_path, array() );
 102  
 103          // Don't update the db, before it is not filled. It will be saved when Save button is clicked.
 104          #$edit_Plugin->Settings->dbupdate();
 105  
 106          $action = 'edit_settings';
 107  
 108          break;
 109  }
 110  
 111  
 112  /*
 113   * Action Handling part II
 114   */
 115  switch( $action )
 116  {
 117      case 'disable_plugin':
 118          // Disable a plugin, only if it is "enabled"
 119  
 120          // Check that this action request is not a CSRF hacked request:
 121          $Session->assert_received_crumb( 'plugin' );
 122  
 123          $current_User->check_perm( 'options', 'edit', true );
 124  
 125          param( 'plugin_ID', 'integer', true );
 126  
 127          $action = 'list';
 128  
 129          $edit_Plugin = & $admin_Plugins->get_by_ID( $plugin_ID );
 130  
 131          if( empty($edit_Plugin) )
 132          {
 133              $Messages->add( sprintf( T_( 'The plugin with ID %d could not be instantiated.' ), $plugin_ID ), 'error' );
 134              break;
 135          }
 136          if( $edit_Plugin->status != 'enabled' )
 137          {
 138              $Messages->add( sprintf( T_( 'The plugin with ID %d is already disabled.' ), $plugin_ID ), 'note' );
 139              break;
 140          }
 141  
 142          // Check dependencies
 143          $msgs = $admin_Plugins->validate_dependencies( $edit_Plugin, 'disable' );
 144          if( ! empty( $msgs['error'] ) )
 145          {
 146              $Messages->add( T_( 'The plugin cannot be disabled because of the following dependencies:' ).' <ul><li>'.implode('</li><li>', $msgs['error']).'</li></ul>', 'error' );
 147              break;
 148          }
 149  
 150          // we call $Plugins(!) here: the Plugin gets disabled on the current page already and it should not get (un)registered on $admin_Plugins!
 151          $Plugins->set_Plugin_status( $edit_Plugin, 'disabled' ); // sets $edit_Plugin->status
 152  
 153          // invalidate all PageCaches
 154          invalidate_pagecaches();
 155  
 156          $Messages->add( /* TRANS: plugin name, class name and ID */ sprintf( T_('Disabled "%s" plugin (%s, #%d).'), $edit_Plugin->name, $edit_Plugin->classname, $edit_Plugin->ID ), 'success' );
 157  
 158          //save fadeout item
 159          $Session->set('fadeout_id', $plugin_ID);
 160  
 161          // Redirect so that a reload doesn't write to the DB twice:
 162          header_redirect( '?ctrl=plugins', 303 ); // Will EXIT
 163          // We have EXITed already at this point!!
 164  
 165          break;
 166  
 167  
 168      case 'enable_plugin':
 169          // Try to enable a plugin, only if it is in state "disabled" or "needs_config"
 170  
 171          // Check that this action request is not a CSRF hacked request:
 172          $Session->assert_received_crumb( 'plugin' );
 173  
 174          $current_User->check_perm( 'options', 'edit', true );
 175  
 176          param( 'plugin_ID', 'integer', true );
 177  
 178          $action = 'list';
 179  
 180          $edit_Plugin = & $admin_Plugins->get_by_ID( $plugin_ID );
 181  
 182          if( empty($edit_Plugin) )
 183          {
 184              $Messages->add( sprintf( T_( 'The plugin with ID %d could not be instantiated.' ), $plugin_ID ), 'error' );
 185              break;
 186          }
 187          if( $edit_Plugin->status == 'enabled' )
 188          {
 189              $Messages->add( /* TRANS: plugin name, class name and ID */ sprintf( T_( 'The "%s" plugin (%s, #%d) is already enabled.' ), $edit_Plugin->name, $edit_Plugin->classname, $plugin_ID ), 'note' );
 190              break;
 191          }
 192          if( $edit_Plugin->status == 'broken' )
 193          {
 194              $Messages->add( sprintf( T_( 'The plugin is in a broken state. It cannot be enabled.' ), $plugin_ID ), 'error' );
 195              break;
 196          }
 197  
 198          // Check dependencies
 199          $msgs = $admin_Plugins->validate_dependencies( $edit_Plugin, 'enable' );
 200          if( ! empty( $msgs['error'] ) )
 201          {
 202              $Messages->add( T_( 'The plugin cannot be enabled because of the following dependencies:' ).' <ul><li>'.implode('</li><li>', $msgs['error']).'</li></ul>' );
 203              break;
 204          }
 205  
 206          load_funcs('plugins/_plugin.funcs.php');
 207          if( install_plugin_db_schema_action( $edit_Plugin ) )
 208          { // Changes are done, or no changes
 209              $action = 'list';
 210          }
 211          else
 212          { // delta queries have to be confirmed in payload
 213              $action = 'install_db_schema';
 214              $next_action = 'enable_plugin';
 215              break;
 216          }
 217  
 218          // Try to enable plugin:
 219          $enable_return = $edit_Plugin->BeforeEnable();
 220          if( $enable_return === true )
 221          {
 222              // NOTE: we don't need to handle plug_version here, because it gets handled in Plugins::register() already.
 223  
 224              // Detect new events:
 225              $admin_Plugins->save_events( $edit_Plugin, array() );
 226  
 227              // we call $Plugins(!) here: the Plugin gets active on the current page already and it should not get (un)registered on $admin_Plugins!
 228              $Plugins->set_Plugin_status( $edit_Plugin, 'enabled' ); // sets $edit_Plugin->status
 229  
 230              // invalidate all PageCaches
 231              invalidate_pagecaches();
 232  
 233              $Messages->add( /* TRANS: plugin name, class name and ID */ sprintf( T_('Enabled "%s" plugin (%s, #%d).'), $edit_Plugin->name, $edit_Plugin->classname, $edit_Plugin->ID ), 'success' );
 234          }
 235          else
 236          {
 237              $Messages->add( T_('The plugin has not been enabled.').( empty($enable_return) ? '' : '<br />'.$enable_return ), 'error' );
 238          }
 239  
 240          //save fadeout item
 241          $Session->set('fadeout_id', $plugin_ID);
 242  
 243          // Redirect so that a reload doesn't write to the DB twice:
 244          header_redirect( '?ctrl=plugins', 303 ); // Will EXIT
 245          // We have EXITed already at this point!!
 246  
 247          break;
 248  
 249  
 250      case 'reload_plugins':
 251          // Register new events
 252          // Unregister obsolete events
 253          // Detect plugins with no code and try to have at least one plugin with the default code
 254  
 255          // Check that this action request is not a CSRF hacked request:
 256          $Session->assert_received_crumb( 'plugin' );
 257  
 258          // Check permission:
 259          $current_User->check_perm( 'options', 'edit', true );
 260  
 261          if( $admin_Plugins->reload_plugins() )
 262          { // Plugins have been changed
 263              $Messages->add( T_('Plugins have been reloaded.'), 'success' );
 264          }
 265          else
 266          {
 267              $Messages->add( T_('Plugins have not changed.'), 'note' );
 268          }
 269          $action = 'list';
 270  
 271          // Redirect so that a reload doesn't write to the DB twice:
 272          header_redirect( '?ctrl=plugins', 303 ); // Will EXIT
 273          // We have EXITed already at this point!!
 274          break;
 275  
 276  
 277      case 'install':
 278          // Install a plugin. This may be a two-step action, when DB changes have to be confirmed
 279          $action = 'list';
 280  
 281          // Check that this action request is not a CSRF hacked request:
 282          $Session->assert_received_crumb( 'plugin' );
 283  
 284          // Check permission:
 285          $current_User->check_perm( 'options', 'edit', true );
 286  
 287          param( 'plugin', 'string', true );
 288  
 289          $edit_Plugin = & $admin_Plugins->install( $plugin, 'broken' ); // "broken" by default, gets adjusted later
 290  
 291          if( is_string($edit_Plugin) )
 292          {
 293              $Messages->add( $edit_Plugin, 'error' );
 294              break;
 295          }
 296  
 297  
 298      case 'install_db_schema':
 299          // we come here from the first step ("install")
 300  
 301          // Check that this action request is not a CSRF hacked request:
 302          $Session->assert_received_crumb( 'plugin' );
 303  
 304          // Check permission:
 305          $current_User->check_perm( 'options', 'edit', true );
 306  
 307          param( 'plugin_ID', 'integer', 0 );
 308  
 309          if( $plugin_ID )
 310          { // second step:
 311              $edit_Plugin = & $admin_Plugins->get_by_ID( $plugin_ID );
 312  
 313              if( ! is_a($edit_Plugin, 'Plugin') )
 314              {
 315                  $Messages->add( sprintf( T_( 'The plugin with ID %d could not be instantiated.' ), $plugin_ID ), 'error' );
 316                  $action = 'list';
 317                  break;
 318              }
 319          }
 320  
 321          load_funcs('plugins/_plugin.funcs.php');
 322          if( install_plugin_db_schema_action( $edit_Plugin ) )
 323          { // Changes are done, or no changes
 324              $action = 'list';
 325          }
 326          else
 327          { // delta queries have to be confirmed in payload
 328              $next_action = 'install_db_schema';
 329              break;
 330          }
 331  
 332          $msg = sprintf( T_('Installed plugin &laquo;%s&raquo;.'), $edit_Plugin->classname );
 333          if( ($edit_settings_url = $edit_Plugin->get_edit_settings_url()) )
 334          {
 335              $msg .= ' <a href="'.$edit_settings_url.'">'.T_('Click here to configure').'</a>.';
 336          }
 337          $Messages->add( $msg, 'success' );
 338  
 339          // Install completed:
 340          $r = $admin_Plugins->call_method( $edit_Plugin->ID, 'AfterInstall', $params = array() );
 341  
 342          // invalidate all PageCaches
 343          invalidate_pagecaches();
 344  
 345          // Try to enable plugin:
 346          $enable_return = $edit_Plugin->BeforeEnable();
 347          if( $enable_return === true )
 348          {
 349              $Plugins->set_Plugin_status( $edit_Plugin, 'enabled' );
 350          }
 351          else
 352          {
 353              $Messages->add( T_('The plugin has not been enabled.').( empty($enable_return) ? '' : '<br />'.$enable_return ), 'error' );
 354              $Plugins->set_Plugin_status( $edit_Plugin, 'disabled' ); // does not unregister it
 355          }
 356  
 357          if( ! empty( $edit_Plugin->install_dep_notes ) )
 358          { // Add notes from dependencies
 359              foreach( $edit_Plugin->install_dep_notes as $note )
 360              {
 361                  $Messages->add( $note, 'note' );
 362              }
 363          }
 364          // Redirect so that a reload doesn't write to the DB twice:
 365          header_redirect( '?ctrl=plugins', 303 ); // Will EXIT
 366          // We have EXITed already at this point!!
 367          break;
 368  
 369  
 370      case 'uninstall':
 371          // Uninstall plugin:
 372  
 373          // Check that this action request is not a CSRF hacked request:
 374          $Session->assert_received_crumb( 'plugin' );
 375  
 376          // Check permission:
 377          $current_User->check_perm( 'options', 'edit', true );
 378  
 379          param( 'plugin_ID', 'integer', true );
 380          param( 'uninstall_confirmed_drop', 'integer', 0 );
 381  
 382          $action = 'list'; // leave 'uninstall' by default
 383  
 384          $edit_Plugin = & $admin_Plugins->get_by_ID( $plugin_ID );
 385  
 386          if( empty($edit_Plugin) )
 387          {
 388              $Messages->add( sprintf( T_( 'The plugin with ID %d could not be instantiated.' ), $plugin_ID ), 'error' );
 389              break;
 390          }
 391  
 392          // Check dependencies:
 393          $msgs = $admin_Plugins->validate_dependencies( $edit_Plugin, 'disable' );
 394          if( ! empty( $msgs['error'] ) )
 395          {
 396              $Messages->add( T_( 'The plugin cannot be uninstalled because of the following dependencies:' ).' <ul><li>'.implode('</li><li>', $msgs['error']).'</li></ul>', 'error' );
 397              break;
 398          }
 399          if( ! empty( $msgs['note'] ) )
 400          { // just notes:
 401              foreach( $msgs['note'] as $note )
 402              {
 403                  $Messages->add( $note, 'note' );
 404              }
 405          }
 406  
 407          // Ask plugin:
 408          $uninstall_ok = $admin_Plugins->call_method( $edit_Plugin->ID, 'BeforeUninstall', $params = array( 'unattended' => false ) );
 409  
 410          if( $uninstall_ok === false )
 411          { // Plugin said "NO":
 412              $Messages->add( sprintf( T_('Could not uninstall plugin #%d.'), $edit_Plugin->ID ), 'error' );
 413              break;
 414          }
 415  
 416          // See if we have (canonical) tables to drop:
 417          $uninstall_tables_to_drop = $DB->get_col( 'SHOW TABLES LIKE "'.$edit_Plugin->get_sql_table('%').'"' );
 418  
 419          if( $uninstall_ok === true )
 420          { // Plugin said "YES":
 421              // invalidate all PageCaches
 422              invalidate_pagecaches();
 423  
 424              if( $uninstall_tables_to_drop )
 425              { // There are tables with the prefix for this plugin:
 426                  if( $uninstall_confirmed_drop )
 427                  { // Drop tables:
 428                      $sql = 'DROP TABLE IF EXISTS '.implode( ', ', $uninstall_tables_to_drop );
 429                      $DB->query( $sql );
 430                      $Messages->add( T_('Dropped the table(s) of the plugin.'), 'success' );
 431                  }
 432                  else
 433                  {
 434                      $uninstall_ok = false;
 435                  }
 436              }
 437  
 438              if( $uninstall_ok )
 439              { // We either have no tables to drop or it has been confirmed:
 440                  $admin_Plugins->uninstall( $edit_Plugin->ID );
 441  
 442                  $Messages->add( /* %s = plugin's classname, %d = plugin's ID */
 443                  sprintf( T_('The &laquo;%s&raquo; plugin (#%d) has been uninstalled.'), $edit_Plugin->classname, $edit_Plugin->ID ), 'success' );
 444                  // Redirect so that a reload doesn't write to the DB twice:
 445                  header_redirect( '?ctrl=plugins', 303 ); // Will EXIT
 446                  // We have EXITed already at this point!!
 447                  break;
 448              }
 449          }
 450  
 451          // $ok === NULL (or other): execute plugin event BeforeUninstallPayload() below
 452          // $ok === false: let the admin confirm DB table dropping below
 453          $action = 'uninstall';
 454  
 455          break;
 456  
 457  
 458      case 'update_settings':
 459          // Update plugin settings:
 460  
 461          // Check that this action request is not a CSRF hacked request:
 462          $Session->assert_received_crumb( 'plugin' );
 463  
 464          // Check permission:
 465          $current_User->check_perm( 'options', 'edit', true );
 466  
 467          param( 'plugin_ID', 'integer', true );
 468  
 469          $edit_Plugin = & $admin_Plugins->get_by_ID( $plugin_ID );
 470          if( empty($edit_Plugin) )
 471          {
 472              $Messages->add( sprintf( T_( 'The plugin with ID %d could not be instantiated.' ), $plugin_ID ), 'error' );
 473              $action = 'list';
 474              break;
 475          }
 476  
 477          // Params from/for form:
 478          param( 'edited_plugin_name' );
 479          param( 'edited_plugin_shortdesc' );
 480          param( 'edited_plugin_code' );
 481          param( 'edited_plugin_priority' );
 482          param( 'edited_plugin_apply_rendering' );
 483          param( 'edited_plugin_displayed_events', 'array/string', array() );
 484          param( 'edited_plugin_events', 'array/integer', array() );
 485  
 486          $default_Plugin = & $admin_Plugins->register($edit_Plugin->classname);
 487  
 488          // Update plugin name:
 489          // (Only if changed to preserve initial localization feature and therefor also priorize NULL)
 490          if( $edit_Plugin->name != $edited_plugin_name )
 491          {
 492              $set_to = $edited_plugin_name == $default_Plugin->name ? NULL : $edited_plugin_name;
 493              $edit_Plugin->name = $edited_plugin_name;
 494              if( $DB->query( '
 495                  UPDATE T_plugins
 496                       SET plug_name = '.$DB->quote($set_to).'
 497                   WHERE plug_ID = '.$plugin_ID ) )
 498              {
 499                  $Messages->add( T_('Plugin name updated.'), 'success' );
 500              }
 501          }
 502  
 503          // Update plugin shortdesc:
 504          // (Only if changed to preserve initial localization feature and therefor also priorize NULL)
 505          if( $edit_Plugin->short_desc != $edited_plugin_shortdesc )
 506          {
 507              $set_to = $edited_plugin_shortdesc == $default_Plugin->short_desc ? NULL : $edited_plugin_shortdesc;
 508              $edit_Plugin->short_desc = $edited_plugin_shortdesc;
 509              if( $DB->query( '
 510                  UPDATE T_plugins
 511                       SET plug_shortdesc = '.$DB->quote($set_to).'
 512                   WHERE plug_ID = '.$plugin_ID ) )
 513              {
 514                  $Messages->add( T_('Plugin description updated.'), 'success' );
 515              }
 516          }
 517  
 518  
 519          // Plugin Events:
 520          $registered_events = $admin_Plugins->get_registered_events( $edit_Plugin );
 521  
 522          $enable_events = array();
 523          $disable_events = array();
 524          foreach( $edited_plugin_displayed_events as $l_event )
 525          {
 526              if( ! in_array( $l_event, $registered_events ) )
 527              { // unsupported event
 528                  continue;
 529              }
 530              if( isset($edited_plugin_events[$l_event]) && $edited_plugin_events[$l_event] )
 531              {
 532                  $enable_events[] = $l_event; // may be already there
 533              }
 534              else
 535              { // unset:
 536                  $disable_events[] = $l_event;
 537              }
 538          }
 539          if( $admin_Plugins->save_events( $edit_Plugin, $enable_events, $disable_events ) )
 540          {
 541              $Messages->add( T_('Plugin events have been updated.'), 'success' );
 542          }
 543  
 544  
 545          // Plugin code
 546          // Check if a ping plugin has a code (which is required) (this has to go after event handling!):
 547          if( $admin_Plugins->has_event($edit_Plugin->ID, 'ItemSendPing')
 548              && empty($edited_plugin_code) )
 549          {
 550              param_error( 'edited_plugin_code', sprintf( T_('This ping plugin needs a non-empty code.'), $edit_Plugin->name ) );
 551          }
 552          else
 553          {
 554              $updated = $admin_Plugins->set_code( $edit_Plugin->ID, $edited_plugin_code );
 555              if( is_string( $updated ) )
 556              {
 557                  param_error( 'edited_plugin_code', $updated );
 558                  $action = 'edit_settings';
 559              }
 560              elseif( $updated === 1 )
 561              {
 562                  $Messages->add( T_('Plugin code updated.'), 'success' );
 563              }
 564          }
 565  
 566  
 567          // Plugin priority
 568          if( param_check_range( 'edited_plugin_priority', 0, 100, T_('Plugin priority must be numeric (0-100).'), true ) )
 569          {
 570              $updated = $admin_Plugins->set_priority( $edit_Plugin->ID, $edited_plugin_priority );
 571              if( $updated === 1 )
 572              {
 573                  $Messages->add( T_('Plugin priority updated.'), 'success' );
 574              }
 575          }
 576          else
 577          {
 578              $action = 'edit_settings';
 579          }
 580  
 581          // Plugin specific settings:
 582          if( $edit_Plugin->Settings )
 583          {
 584              load_funcs('plugins/_plugin.funcs.php');
 585  
 586              // Loop through settings for this plugin:
 587              foreach( $edit_Plugin->GetDefaultSettings( $dummy = array('for_editing' => true) ) as $set_name => $set_meta )
 588              {
 589                  autoform_set_param_from_request( $set_name, $set_meta, $edit_Plugin, 'Settings' );
 590              }
 591  
 592              // Let the plugin handle custom fields:
 593              // We use call_method to keep track of this call, although calling the plugins PluginSettingsUpdateAction method directly _might_ work, too.
 594              $ok_to_update = $admin_Plugins->call_method( $edit_Plugin->ID, 'PluginSettingsUpdateAction', $tmp_params = array() );
 595  
 596              if( $ok_to_update === false )
 597              {    // Rollback settings: the plugin has said they should not get updated.
 598                  $edit_Plugin->Settings->reset();
 599              }
 600              elseif( $edit_Plugin->Settings->dbupdate() )
 601              {
 602                  $Messages->add( T_('Plugin settings have been updated.'), 'success' );
 603              }
 604          }
 605  
 606          // Check if it can stay enabled, if it is
 607          if( $edit_Plugin->status == 'enabled' )
 608          {
 609              $enable_return = $edit_Plugin->BeforeEnable();
 610              if( $enable_return !== true )
 611              {
 612                  $Plugins->set_Plugin_status( $edit_Plugin, 'needs_config' );
 613                  $Messages->add( T_('The plugin has been disabled.').( empty($enable_return) ? '' : '<br />'.$enable_return ), 'error' );
 614              }
 615          }
 616  
 617          if( ! $Messages->has_errors() )
 618          { // there were no errors, go back to list:
 619              //save fadeout item
 620              $Session->set('fadeout_id', $edit_Plugin->ID);
 621  
 622              // Redirect so that a reload doesn't write to the DB twice:
 623              header_redirect( '?ctrl=plugins', 303 ); // Will EXIT
 624  
 625              // We have EXITed already at this point!!
 626          }
 627  
 628          // Redisplay so user can fix errors:
 629          $action = 'edit_settings';
 630          break;
 631  
 632  
 633      case 'edit_settings':
 634          // Check permission:
 635          $current_User->check_perm( 'options', 'view', true );
 636  
 637          // Edit plugin settings:
 638          param( 'plugin_ID', 'integer', true );
 639  
 640          $edit_Plugin = & $admin_Plugins->get_by_ID( $plugin_ID );
 641  
 642          if( ! $edit_Plugin )
 643          {
 644              $Debuglog->add( 'The plugin with ID '.$plugin_ID.' was not found.', array('plugins', 'error') );
 645              $action = 'list';
 646              break;
 647          }
 648  
 649          // Detect new events, so they get displayed correctly in the "Edit events" fieldset:
 650          $admin_Plugins->save_events( $edit_Plugin, array() );
 651  
 652          // Inform Plugin that it gets edited:
 653          $admin_Plugins->call_method( $edit_Plugin->ID, 'PluginSettingsEditAction', $tmp_params = array() );
 654  
 655          // Params for form:
 656          $edited_plugin_name = $edit_Plugin->name;
 657          $edited_plugin_shortdesc = $edit_Plugin->short_desc;
 658          $edited_plugin_code = $edit_Plugin->code;
 659          $edited_plugin_priority = $edit_Plugin->priority;
 660  
 661          break;
 662  
 663  
 664      case 'default_settings':
 665          // Restore default settings
 666  
 667          // Check that this action request is not a CSRF hacked request:
 668          $Session->assert_received_crumb( 'plugin' );
 669  
 670          // Check permission:
 671          $current_User->check_perm( 'options', 'edit', true );
 672  
 673          param( 'plugin_ID', 'integer', true );
 674  
 675          $edit_Plugin = & $admin_Plugins->get_by_ID( $plugin_ID );
 676          if( !$edit_Plugin )
 677          {
 678              $Debuglog->add( 'The plugin with ID '.$plugin_ID.' was not found.', array('plugins', 'error') );
 679              $action = 'list';
 680              break;
 681          }
 682  
 683          // this returns NULL for code as it's seen as a duplicate plugin
 684          $default_Plugin = & $admin_Plugins->register($edit_Plugin->classname);
 685  
 686          // grab a raw copy of the plugin
 687          $raw_Plugin = new $edit_Plugin->classname();
 688  
 689          // Params for/"from" form:
 690          $edited_plugin_name = $default_Plugin->name;
 691          $edited_plugin_shortdesc = $default_Plugin->short_desc;
 692          $edited_plugin_code = $raw_Plugin->code;
 693          $edited_plugin_priority = $default_Plugin->priority;
 694  
 695          // Name and short desc:
 696          $DB->query( '
 697                  UPDATE T_plugins
 698                     SET plug_name = NULL,
 699                         plug_shortdesc = NULL
 700                   WHERE plug_ID = '.$plugin_ID );
 701  
 702          // Code:
 703          $updated = $admin_Plugins->set_code( $edit_Plugin->ID, $edited_plugin_code );
 704          if( is_string( $updated ) )
 705          { // error message
 706              param_error( 'edited_plugin_code', $updated );
 707              $action = 'edit_settings';
 708          }
 709          elseif( $updated === 1 )
 710          {
 711              $Messages->add( T_('Plugin code updated.'), 'success' );
 712          }
 713  
 714          // Priority:
 715          if( ! preg_match( '~^1?\d?\d$~', $edited_plugin_priority ) )
 716          {
 717              param_error( 'edited_plugin_priority', T_('Plugin priority must be numeric (0-100).') );
 718          }
 719          else
 720          {
 721              $updated = $admin_Plugins->set_priority( $edit_Plugin->ID, $edited_plugin_priority );
 722              if( $updated === 1 )
 723              {
 724                  $Messages->add( T_('Plugin priority updated.'), 'success' );
 725              }
 726          }
 727  
 728          // PluginSettings:
 729          if( $edit_Plugin->Settings )
 730          {
 731              if( $edit_Plugin->Settings->restore_defaults() )
 732              {
 733                  $Messages->add( T_('Restored default values.'), 'success' );
 734              }
 735              else
 736              {
 737                  $Messages->add( T_('Settings have not changed.'), 'note' );
 738              }
 739          }
 740  
 741          // Enable all events:
 742          if( $admin_Plugins->save_events( $edit_Plugin ) )
 743          {
 744              $Messages->add( T_('Plugin events have been updated.'), 'success' );
 745          }
 746  
 747          // Check if it can stay enabled, if it is
 748          if( $edit_Plugin->status == 'enabled' )
 749          {
 750              $enable_return = $edit_Plugin->BeforeEnable();
 751              if( $enable_return !== true )
 752              {
 753                  $Plugins->set_Plugin_status( $edit_Plugin, 'needs_config' );
 754                  $Messages->add( T_('The plugin has been disabled.').( empty($enable_return) ? '' : '<br />'.$enable_return ), 'error' );
 755              }
 756          }
 757  
 758          // blueyed>> IMHO it's good to see the new settings again. Perhaps we could use $action = 'list' for "Settings have not changed"?
 759          $action = 'edit_settings';
 760  
 761          break;
 762  
 763  
 764      case 'info':
 765      case 'disp_help':
 766      case 'disp_help_plain': // just the help, without any payload
 767  
 768          // Check permission: (with plugins... you never know...)
 769          $current_User->check_perm( 'options', 'view', true );
 770  
 771          param( 'plugin_class', 'string', true );
 772  
 773          if( ! ( $edit_Plugin = & $admin_Plugins->get_by_classname( $plugin_class ) ) )
 774          {    // Plugin is not installed:
 775              $edit_Plugin = & $admin_Plugins->register( $plugin_class );
 776  
 777              if( is_string($edit_Plugin) )
 778              {
 779                  $Messages->add($edit_Plugin, 'error');
 780                  $edit_Plugin = false;
 781                  $action = 'list';
 782              }
 783              else
 784              {
 785                  $admin_Plugins->unregister( $edit_Plugin, true /* force */ );
 786              }
 787          }
 788  
 789          if( $edit_Plugin->status == 'broken' )
 790          {
 791              $Messages->add( T_('The requested plugin doesn\'t exist!'), 'error' );
 792          }
 793  
 794          break;
 795  
 796  }
 797  
 798  
 799  // Extend titlearea for some actions and add JS:
 800  switch( $action )
 801  {
 802      case 'edit_settings':
 803          $AdminUI->append_to_titlearea( '<a href="'.regenerate_url('', 'action=edit_settings&amp;plugin_ID='.$edit_Plugin->ID).'">'
 804              .sprintf( T_('Edit plugin &laquo;%s&raquo; (ID %d)'), $edit_Plugin->name, $edit_Plugin->ID ).'</a>' );
 805          break;
 806  
 807      case 'disp_help_plain': // just the help, without any payload
 808      case 'disp_help':
 809          if( ! ($help_file = $edit_Plugin->get_help_file()) )
 810          {
 811              $action = 'list';
 812              break;
 813          }
 814  
 815          if( $action == 'disp_help_plain' )
 816          { // display it now and exit:
 817              readfile($help_file);
 818              exit(0);
 819          }
 820  
 821          $title = sprintf( T_('Help for plugin &laquo;%s&raquo;'), '<a href="'.$dispatcher.'?ctrl=plugins&amp;action=edit_settings&amp;plugin_ID='.$edit_Plugin->ID.'">'.$edit_Plugin->name.'</a>' );
 822          if( ! empty($edit_Plugin->help_url) )
 823          {
 824              $title .= ' '.action_icon( T_('External help page'), 'help', $edit_Plugin->help_url );
 825          }
 826          $AdminUI->append_to_titlearea( $title );
 827          break;
 828  }
 829  
 830  
 831  // Display load error from Plugins::register() (if any):
 832  if( isset($edit_Plugin) && is_object($edit_Plugin) && isset( $admin_Plugins->plugin_errors[$edit_Plugin->ID] )
 833          && ! empty($admin_Plugins->plugin_errors[$edit_Plugin->ID]['register']) )
 834  {
 835      $Messages->add( get_icon('warning').' '.$admin_Plugins->plugin_errors[$edit_Plugin->ID]['register'], 'error' );
 836  }
 837  
 838  
 839  $AdminUI->breadcrumbpath_init( false );
 840  $AdminUI->breadcrumbpath_add( T_('System'), '?ctrl=system',
 841          T_('Global settings are shared between all blogs; see Blog settings for more granular settings.') );
 842  $AdminUI->breadcrumbpath_add( T_('Plugin configuration'), '?ctrl=plugins' );
 843  
 844  init_plugins_js();
 845  
 846  // Display <html><head>...</head> section! (Note: should be done early if actions do not redirect)
 847  $AdminUI->disp_html_head();
 848  
 849  // Display title, menu, messages, etc. (Note: messages MUST be displayed AFTER the actions)
 850  $AdminUI->disp_body_top();
 851  
 852  // Begin payload block:
 853  $AdminUI->disp_payload_begin();
 854  
 855  switch( $action )
 856  {
 857      case 'disp_help':
 858          // Display plugin help:
 859          $help_file_body = implode( '', file($help_file) );
 860  
 861          // Try to extract the BODY part:
 862          if( preg_match( '~<body.*?>(.*)</body>~is', $help_file_body, $match ) )
 863          {
 864              $help_file_body = $match[1];
 865          }
 866  
 867          echo $help_file_body;
 868          unset($help_file_body);
 869          break;
 870  
 871  
 872      case 'install_db_schema':
 873          // Payload for 'install_db_schema' action if DB layout changes have to be confirmed:
 874          ?>
 875  
 876          <div class="panelinfo">
 877  
 878              <?php
 879              $Form = new Form( NULL, 'install_db_deltas', 'get' );
 880  
 881              $Form->global_icon( T_('Cancel installation!'), 'close', regenerate_url() );
 882  
 883              $Form->begin_form( 'fform', sprintf( /* TRANS: %d is ID, %d name */ T_('Finish setup for plugin #%d (%s)'), $edit_Plugin->ID, $edit_Plugin->name ) );
 884  
 885              $Form->add_crumb( 'plugin' );
 886              $Form->hidden_ctrl();
 887              $Form->hidden( 'action', $next_action );
 888              $Form->hidden( 'plugin_ID', $edit_Plugin->ID );
 889  
 890              echo '<p>'.T_('The plugin needs the following database changes.').'</p>';
 891  
 892              if( ! empty($install_db_deltas) )
 893              {
 894                  echo '<p>'.T_('The following database changes will be carried out. If you are not sure what this means, it will probably be alright.').'</p>';
 895  
 896                  echo '<ul>';
 897                  foreach( $install_db_deltas as $l_delta )
 898                  {
 899                      #echo '<li><code>'.nl2br($l_delta).'</code></li>';
 900                      echo '<li><pre>'.str_replace( "\t", '  ', $l_delta ).'</pre></li>';
 901                  }
 902                  echo '</ul>';
 903  
 904                  $Form->hidden( 'install_db_deltas_confirm_md5', md5(implode( '', $install_db_deltas )) );
 905              }
 906  
 907              $Form->submit( array( '', T_('Install!'), 'ActionButton' ) );
 908              $Form->end_form();
 909              ?>
 910  
 911          </div>
 912  
 913          <?php
 914          break;
 915  
 916  
 917      case 'uninstall': // We come here either if the plugin requested a call to BeforeUninstallPayload() or if there are tables to be dropped {{{
 918          ?>
 919  
 920          <div class="panelinfo">
 921  
 922              <?php
 923              $Form = new Form( '', 'uninstall_plugin', 'post' );
 924  
 925              $Form->global_icon( T_('Cancel uninstall!'), 'close', regenerate_url() );
 926  
 927              $Form->begin_form( 'fform', sprintf( /* TRANS: %d is ID, %d name */ T_('Uninstall plugin #%d (%s)'), $edit_Plugin->ID, $edit_Plugin->name ) );
 928  
 929              $Form->add_crumb( 'plugin' );
 930              // We may need to use memorized params in the next page
 931              $Form->hiddens_by_key( get_memorized( 'action,plugin_ID') );
 932              $Form->hidden( 'action', 'uninstall' );
 933              $Form->hidden( 'plugin_ID', $edit_Plugin->ID );
 934              $Form->hidden( 'uninstall_confirmed_drop', 1 );
 935  
 936              if( $uninstall_tables_to_drop )
 937              {
 938                  echo '<p>'.T_('Uninstalling this plugin will also delete its database tables:').'</p>'
 939                      .'<ul>'
 940                      .'<li>'
 941                      .implode( '</li><li>', $uninstall_tables_to_drop )
 942                      .'</li>'
 943                      .'</ul>';
 944              }
 945  
 946              if( $uninstall_ok === NULL )
 947              { // Plugin requested this:
 948                  $admin_Plugins->call_method( $edit_Plugin->ID, 'BeforeUninstallPayload', $params = array( 'Form' => & $Form ) );
 949              }
 950  
 951              echo '<p>'.T_('THIS CANNOT BE UNDONE!').'</p>';
 952  
 953              $Form->submit( array( '', T_('I am sure!'), 'DeleteButton' ) );
 954              $Form->end_form();
 955              ?>
 956  
 957          </div>
 958  
 959          <?php // }}}
 960          break;
 961  
 962  
 963      case 'edit_settings':
 964          $AdminUI->disp_view( 'plugins/views/_plugin_settings.form.php' );
 965          break;
 966  
 967  
 968      case 'info':
 969          if( $edit_Plugin->status == 'broken' )
 970          {
 971              break;
 972          }
 973  
 974          // Display plugin info:
 975          load_funcs('plugins/_plugin.funcs.php');
 976  
 977          $Form = new Form( $pagenow );
 978  
 979          if( $edit_Plugin->ID > 0 && $current_User->check_perm( 'options', 'edit', false ) )
 980          { // Edit settings button (if installed):
 981              $Form->global_icon( T_('Edit plugin settings!'), 'edit', $admin_url.'?ctrl=plugins&amp;action=edit_settings&amp;plugin_ID='.$edit_Plugin->ID );
 982          }
 983  
 984          // Close button:
 985          $Form->global_icon( T_('Close info!'), 'close', regenerate_url() );
 986  
 987          $Form->begin_form( 'fform', '&nbsp;' );
 988          $Form->hidden( 'ctrl', 'plugins' );
 989          $Form->begin_fieldset('Plugin info', array('class' => 'fieldset'));
 990          $Form->info_field( T_('Name'), $edit_Plugin->name );
 991          $Form->info_field( T_('Code'),
 992                  ( empty($edit_Plugin->code) ? ' - ' : $edit_Plugin->code ),
 993                  array( 'note' => T_('This 32 character code uniquely identifies the functionality of this plugin. It is only necessary to call the plugin by code (SkinTag) or when using it as a Renderer.') ) );
 994          $Form->info_field( T_('Short desc'), $edit_Plugin->short_desc );
 995          $Form->info_field( T_('Long desc'), $edit_Plugin->long_desc );
 996          if( $edit_Plugin->ID > 0 )
 997          { // do not display ID for non registered Plugins
 998              $Form->info_field( T_('ID'), $edit_Plugin->ID );
 999          }
1000          $Form->info_field( T_('Version'), $edit_Plugin->version );
1001          $Form->info_field( T_('Classname'), $edit_Plugin->classname );
1002          $Form->info_field( T_('Class file'), rel_path_to_base($edit_Plugin->classfile_path ) );
1003  
1004          // Help icons (to homepage and README.html), if available:
1005          $help_icons = array();
1006          if( $help_www = $edit_Plugin->get_help_link('$help_url') )
1007          {
1008              $help_icons[] = $help_www;
1009          }
1010          if( ! empty($help_icons) )
1011          {
1012              $Form->info_field( T_('Help'), implode( ' ', $help_icons ) );
1013          }
1014  
1015          $Form->end_fieldset();
1016  
1017          if( $edit_Plugin->ID < 1 )
1018          { // add "Install NOW" submit button (if not already installed)
1019              $registrations = $admin_Plugins->count_regs($edit_Plugin->classname);
1020  
1021              if( ! isset( $edit_Plugin->number_of_installs )
1022                      || ( $admin_Plugins->count_regs($edit_Plugin->classname) < $edit_Plugin->number_of_installs ) )
1023              { // number of installations are not limited or not reached yet
1024                  $Form->add_crumb('plugin');
1025                  $Form->hidden( 'action', 'install' );
1026                  $Form->hidden( 'plugin', $edit_Plugin->classname );
1027  
1028                  $Form->begin_fieldset( '', array( 'class'=>'fieldset center' ) );
1029                  $Form->submit( array( '', T_('Install NOW!'), 'ActionButton' ) );
1030                  $Form->end_fieldset();
1031              }
1032          }
1033  
1034          $Form->end_form();
1035          $action = '';
1036          break;
1037  
1038  }
1039  
1040  switch( $action )
1041  {
1042      case 'list':
1043          // Display VIEW:
1044          $AdminUI->disp_view( 'plugins/views/_plugin_list.view.php' );
1045          break;
1046  
1047      case 'list_available':
1048          // Display VIEW:
1049          $AdminUI->disp_view( 'plugins/views/_plugin_list_available.view.php' );
1050          break;
1051  }
1052  
1053  // End payload block:
1054  $AdminUI->disp_payload_end();
1055  
1056  // Display body bottom, debug info and close </html>:
1057  $AdminUI->disp_global_footer();
1058  
1059  ?>

title

Description

title

Description

title

Description

title

title

Body