Location: PHPKode > projects > Sierra-php PHP Application Framework > sierra/lib/util/installer/SRA_InstallerMenuItem.php
<?php
// {{{ Header
/*
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
 | SIERRA : PHP Application Framework  http://code.google.com/p/sierra-php |
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
 | Copyright 2005 Jason Read                                               |
 |                                                                         |
 | Licensed under the Apache License, Version 2.0 (the "License");         |
 | you may not use this file except in compliance with the License.        |
 | You may obtain a copy of the License at                                 |
 |                                                                         |
 |     http://www.apache.org/licenses/LICENSE-2.0                          |
 |                                                                         |
 | Unless required by applicable law or agreed to in writing, software     |
 | distributed under the License is distributed on an "AS IS" BASIS,       |
 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.|
 | See the License for the specific language governing permissions and     |
 | limitations under the License.                                          |
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
 */
// }}}

// {{{ Imports

// }}}

// {{{ Constants

// }}}

// {{{ SRA_InstallerMenuItem
/**
 * defines an action that may be invoked through the installer. this action may 
 * be either displaying another sub-menu, or collecting some data from the user 
 * and using that data to make a configuration change, or some other 
 * installation related action
 * @author  Jason Read <hide@address.com>
 * @package sierra.util.installer
 */
class SRA_InstallerMenuItem {
  // public attributes
  /**
	 * the unique identifier for this menu item
	 * @type string
	 */
	var $id;
  
  
  // private attributes
  
  /**
	 * the base configuration of this menu item
	 * @type hash
	 */
	var $_conf;
  
  /**
	 * if the purpose of this menu-item is to display data (the data displayed is 
   * the string returned by "handler"), this attribute can be set to TRUE (1) in 
   * which case the screen will be cleared, the data displayed, and the user 
   * prompted "Press enter to continue"
	 * @type boolean
	 */
	var $_displayData;
  
  /**
	 * whether or not to exit the installer after this menu item action has been 
   * completed successfully
	 * @type boolean
	 */
	var $_exit;
  
  /**
	 * the installer instance this menu belongs to
	 * @type SRA_Installer
	 */
	var $_installer;
  
  /**
	 * the menu instance this menu item belongs to
	 * @type SRA_InstallerMenu
	 */
	var $_menu;
  
  /**
	 * the name of the method in the installer object that should be invoked to 
   * handle the action associated with this menu item. either "handler" or 
   * "menu" may be specified, but not both. this method should have the 
   * following signature: 
   *   (string : $menuItem, hash : $data) : string
   * where $menuItem is the menu-item "key", $data is a hash (indexed by 
   * resource identifier) containing data collection based on the resource 
   * identifiers specified in the "prompt" attribute and the return value 
   * (optional) is a message that should be displayed to the user
	 * @type string
	 */
	var $_method;
  
  /**
	 * this optional attribute may be used to dynamically populate menu items. it 
   * should be the name of an installer method that should be invoked and return 
   * an array of hashes (or single hash) each of which defines a single menu 
   * item to be displayed in the menu where each hash may have the same 
   * attributes (minus "builder") as the "menu-item" element. if this method 
   * return NULL, this menu-item will be excluded from the menu. the menu items 
   * configurations returned will automatically inherit attributes of this 
   * menu-item that are not defined
	 * @type string
	 */
	var $_methodBuilder;
  
  /**
	 * if "prompt" is specified, this attribute may be used to specify the name of 
   * a method in the installer object that should be invoked to determine the 
   * default values for the data that the user will be prompted for. this method 
   * should have the following signature:
   *   (string : $menuItem, string : $id, hash : $data) : string
   * where $menuItem is the menu-item "key", $id is the "prompt" resource 
   * identifier of the question that this method should return the default value 
   * for, and $data is the hash (indexed by resource identifier) of data that 
   * has already been collected. if this method returns NULL, the "prompt" 
   * default value will be used ([default])
	 * @type string
	 */
	var $_methodDefaults;
  
  /**
	 * this optional method may be used to specify the name of a method in the 
   * installer object that should be invoked to determine whether or not this 
   * menu-item should be included in the menu. this method should have the 
   * following signature:
   *   (string : $menuItem) : boolean
   * where $menuItem is the menu-item "key"
	 * @type string
	 */
	var $_methodInclude;
  
  /**
	 * if "prompt" is specified, this attribute may be used to specify the name of 
   * a method in the installer object that should be invoked to determine 
   * whether or not user input is valid for a given "prompt" resource 
   * identifier. this method should have the following signature:
   *   (string : $menuItem, string : $id, string : $val, hash : $data) : boolean
   * where $menuItem is the menu-item "key", $id is the "prompt" resource 
   * identifier of the question that this method should validate, $val is the 
   * value provided by the user, and $data is the hash (indexed by resource 
   * identifier) of data that has already been collected. if defined, this 
   * method should return TRUE if the data is valid, FALSE otherwise. if it 
   * returns FALSE, the entire menu-item action will be aborted
	 * @type string
	 */
	var $_methodValidator;
  
  /**
	 * whether or not the previous menu should be displayed after this menu item 
   * action has been completed successfully
	 * @type boolean
	 */
	var $_previousMenu;
  
  /**
	 * this attribute may be used to prompt the user for data prior to invoking 
   * $_method. when set, this attribute will be an array of hashes (indexed by 
   * the prompt value key - the resource identifier minus $_promptKeyRemove), 
   * where each each has the following keys:
   *   allowNull:       boolean indicating whether or not this question is 
   *                    optional
   *   default:         the default value
   *   options:         an array of valid response options
   *   question:        the question to prompt the user with
   *   removeIfDefault: boolean indicating whether or not this prompt value 
   *                    should be excluded from the $data hash if it is equal to 
   *                    [default]
   *   validateFailMsg: custom message that should be displayed in the user 
   *                    enter invalid data (when $_methodValidator returns 
   *                    FALSE)
	 * @type array
	 */
	var $_prompt;
  
  /**
	 * an optional header that should be displayed prior to prompting the user for 
   * data
	 * @type string
	 */
	var $_promptHeader;
  
  /**
	 * the resource identifier for this menu item's title. use the "getTitle" 
   * method to get the localized value
	 * @type string
	 */
	var $_resource;
  
  
  /**
	 * resource identifier for the confirmation message that should be displayed 
   * (user must respond positively) before the action associated with this menu 
   * item will be invoked. use the "getConfirm" method to get the localized 
   * value
	 * @type string
	 */
	var $_resourceConfirm;
  
  /**
	 * the name of a method in "class" that should be invoked to retrieve custom 
   * resource keys to included in "resource" and "confirm" whenever they are rendered
	 * @type string
	 */
	var $_resourceKeys;
  
  /**
	 * if this menu item should display another menu, this attribute will be the 
   * identifier of that menu
	 * @type SRA_InstallerMenu
	 */
	var $_subMenu;
  
  
	// {{{ SRA_InstallerMenuItem
	/**
	 * parses the menu item configuration data and sets the appropriate instance 
   * variables. if there is a problem with the configuration, the instance 
   * variable "err" will be assigned to an appropriate error object (the error 
   * will be logged)
   * @param array $conf the configuration to parse
   * @param SRA_InstallerMenu $menu the menu instance this menu item belongs to
   * @param SRA_Installer $installer the installer instance this menu belongs to
   * @access public
	 */
	function SRA_InstallerMenuItem($conf, &$menu, &$installer) {
    if (isset($conf['attributes'])) $conf = $conf['attributes'];
    
    $this->_conf = $conf;
    $this->id = $conf['key'];
    $this->_resourceConfirm = isset($conf['confirm']) ? $conf['confirm'] : NULL;
    $this->_displayData = isset($conf['display-data']) && $conf['display-data'] == '1';
    $this->_exit = isset($conf['exit']) && $conf['exit'] == '1';
    $this->_resource = $conf['resource'] ? $conf['resource'] : $this->id;
    $this->_resourceKeys = isset($conf['resource-keys']) ? $conf['resource-keys'] : NULL;
    $this->_installer =& $installer;
    $this->_previousMenu = isset($conf['previous-menu']) && $conf['previous-menu'] == '1';
    $this->_subMenu = isset($conf['menu']) ? $conf['menu'] : NULL;
    if ($this->_subMenu && !$installer->menuIsValid($this->_subMenu)) {
      $err = 'menu ' . $this->_subMenu . ' is not valid';
    }
    $this->_menu =& $menu;
    $this->_method = isset($conf['handler']) ? $conf['handler'] : NULL;
    if ($this->_method && !method_exists($installer->installer, $this->_method)) {
      $err = 'handler method ' . $this->_method . ' is not valid';
    }
    $this->_methodBuilder = isset($conf['builder']) ? $conf['builder'] : NULL;
    if ($this->_methodBuilder && !method_exists($installer->installer, $this->_methodBuilder)) {
      $err = 'builder method ' . $this->_methodBuilder . ' is not valid';
    }
    $this->_methodDefaults = isset($conf['defaults-handler']) ? $conf['defaults-handler'] : NULL;
    if ($this->_methodDefaults && !method_exists($installer->installer, $this->_methodDefaults)) {
      $err = 'defaults-handler method ' . $this->_methodDefaults . ' is not valid';
    }
    $this->_methodInclude = isset($conf['include-handler']) ? $conf['include-handler'] : NULL;
    $methodInclude = $this->_methodInclude;
    $reverse = SRA_Util::beginsWith($methodInclude, '!');
    if ($reverse) { $methodInclude = substr($methodInclude, 1); }
    if ($methodInclude && !method_exists($installer->installer, $methodInclude)) {
      $err = 'include-handler method ' . $this->_methodInclude . ' is not valid';
    }
    $this->_methodValidator = isset($conf['validator']) ? $conf['validator'] : NULL;
    if ($this->_methodValidator && !method_exists($installer->installer, $this->_methodValidator)) {
      $err = 'validator method ' . $this->_methodValidator . ' is not valid';
    }
    if ($this->_resourceKeys && !method_exists($installer->installer, $this->_resourceKeys)) {
      $err = 'resource-keys method ' . $this->_resourceKeys . ' is not valid';
    }
    if (isset($conf['prompt'])) {
      $promptKeyRemove = isset($conf['prompt-key-remove']) ? $conf['prompt-key-remove'] : NULL;
      $this->_prompt = array();
      foreach(explode(' ', $conf['prompt']) as $resource) {
        $prompt = explode('|', $installer->resources->getString($resource));
        $id = $promptKeyRemove ? str_replace($promptKeyRemove, '', $resource) : $resource;
        $this->_prompt[$id] = array();
        $this->_prompt[$id]['allowNull'] = isset($prompt[4]) && $prompt[4] == '1';
        if (isset($prompt[2]) && $prompt[2] !== '') { $this->_prompt[$id]['default'] = $prompt[2]; }
        if (isset($prompt[1]) && $prompt[1] !== '') { $this->_prompt[$id]['options'] = explode('/', $prompt[1]); }
        $this->_prompt[$id]['question'] = $prompt[0];
        $this->_prompt[$id]['removeIfDefault'] = isset($prompt[3]) && $prompt[3] == '1';
        if (isset($prompt[5]) && $prompt[5] !== '') { $this->_prompt[$id]['validateFailMsg'] = $prompt[5]; }
      }
      $this->_promptHeader = isset($conf['prompt-header']) ? $installer->resources->getString($conf['prompt-header']) : NULL;
    }
    if (!$this->_subMenu && !$this->_method) {
      $err = 'either "menu" or "handler" must be specified';
    }
    
    if ($err) { $this->err = SRA_Error::logError('SRA_InstallerMenuItem: ' . $this->id . ' Failed - ' . $err, __FILE__, __LINE__); }
	}
	// }}}
  
	// {{{ getConfirm
	/**
	 * returns the localized confirm message for this menu item (or NULL if there 
   * is not one)
	 * @access public
	 * @return string
	 */
	function getConfirm() {
    $resourceKeys = $this->_resourceKeys;
		return $this->_resourceConfirm ? $this->_installer->resources->getString($this->_resourceConfirm, $resourceKeys ? $this->_installer->installer->${resourceKeys}() : NULL) : NULL;
	}
	// }}}
  
	// {{{ getMenuItem
	/**
	 * returns the menu item identified by $id. this will usually be an instance 
   * of this menu item, unless $this->_methodBuilder is defined and returns 
   * multiplie menu items
   * @param string $id the identifier of the menu item to return
	 * @access public
	 * @return SRA_InstallerMenuItem
	 */
	function &getMenuItem($id) {
		$menuItems =& $this->getMenuItems();
    $nl = NULL;
    return isset($menuItems[$id]) && SRA_InstallerMenuItem::isValid($menuItems[$id]) ? $menuItems[$id] : $nl;
	}
	// }}}
  
	// {{{ getMenuItems
	/**
	 * returns an associative array of menu items corresponding with this menu 
   * item. this array will be indexed by the menu item identifier. usually this 
   * will simply be a single SRA_InstallerMenuItem instance, UNLESS 
   * $this->_methodBuilder has been defined. this method returns NULL if no 
   * items should be included for this menu item (if $this->_methodBuilder is 
   * defined and does not return any items or if $this->_methodInclude is 
   * defined and returns FALSE)
	 * @access public
	 * @return SRA_InstallerMenuItem[]
	 */
	function &getMenuItems() {
    $options = array();
    $methodInclude = $this->_methodInclude;
    $reverse = SRA_Util::beginsWith($methodInclude, '!');
    if ($reverse) { $methodInclude = substr($methodInclude, 1); }
    if (!$methodInclude || (!$reverse && $this->_installer->installer->${methodInclude}()) || ($reverse && !$this->_installer->installer->${methodInclude}())) {
      $methodBuilder = $this->_methodBuilder;
      if (!$methodBuilder) {
        $options[$this->id] =& $this;
      }
      else if ($builderOptions = $this->_installer->installer->${methodBuilder}()) {
        foreach($builderOptions as $conf) {
          $conf = array_merge($this->_conf, $conf);
          if ($conf['builder'] == $this->_conf['builder']) unset($conf['builder']);
          if (SRA_InstallerMenuItem::isValid($item = new SRA_InstallerMenuItem($conf, $this->_menu, $this->_installer)) && ($items =& $item->getMenuItems())) {
            $keys = array_keys($items);
            foreach($keys as $key) {
              $options[$key] = $items[$key];
            }
          }
        }
      }
    }
    $nl = NULL;
    return count($options) ? $options : $nl;
	}
	// }}}
  
	// {{{ getMenuOptions
	/**
	 * returns a hash representing the options that should be included in the menu 
   * that this menu-item pertains. the key in this hash will be the  menu-item 
   * id and the value will be the menu option title. this method returns NULL if 
   * no options should be included in the menu for this menu item
	 * @access public
	 * @return hash
	 */
	function getMenuOptions() {
    $options = array();
    if ($items =& $this->getMenuItems()) {
      $keys = array_keys($items);
      foreach($keys as $key) {
        $options[$items[$key]->id] = $items[$key]->getTitle();
      }
    }
    return count($options) ? $options : NULL;
	}
	// }}}
  
	// {{{ getTitle
	/**
	 * returns the localized title for this menu
	 * @access public
	 * @return string
	 */
	function getTitle() {
    $resourceKeys = $this->_resourceKeys;
		return $this->_installer->resources->getString($this->_resource, $resourceKeys ? $this->_installer->installer->${resourceKeys}() : NULL);
	}
	// }}}
  
	// {{{ run
	/**
	 * invoked by the installer when this menu item has been selected by the user
   * returns a optional notification string to display on top of the next menu
	 * @access public
	 * @return string
	 */
	function run() {
    $ret = '';
    if (!$this->_resourceConfirm || $this->_installer->confirm($this->getConfirm())) {
      // invoke handler method
      if ($this->_method) {
        $data = NULL;
        if ($this->_prompt) {
          $data = array();
          $this->_installer->clear();
          if ($this->_promptHeader) {
            echo $this->_promptHeader . "\n\n";
          }
          $keys = array_keys($this->_prompt);
          $methodDefaults = $this->_methodDefaults;
          $methodValidator = $this->_methodValidator;
          for($i=0; $i<count($keys); $i++) {
            $key = $keys[$i];
            $default = $methodDefaults && ($temp = $this->_installer->installer->${methodDefaults}($this->id, $key, $data)) ? $temp : $this->_prompt[$key]['default'];
            
            if ($methodDefaults && $default == SRA_INSTALLER_PROMPT_SKIP) { continue; }
            
            $data[$key] = $this->_installer->getUserInput($this->_prompt[$key]['question'], $default, $this->_prompt[$key]['allowNull'], $this->_prompt[$key]['options'], TRUE);
            if (trim(strtolower($data[$key])) == strtolower($this->_installer->resourcesSys->getString('installer.prompt.na'))) { $data[$key] = NULL; }
            if ($this->_prompt[$key]['removeIfDefault'] && $data[$key] == $this->_prompt[$key]['default']) {
              unset($data[$key]);
            }
            if ($methodValidator && !$this->_installer->installer->${methodValidator}($this->id, $key, $data[$key], $data)) {
              echo ($this->_prompt[$key]['validateFailMsg'] ? $this->_prompt[$key]['validateFailMsg'] : $this->_installer->resourcesSys->getString('installer.error.validator')) . "\n";
              $i--;
            }
          }
        }
        $method = $this->_method;
        $msg = $this->_installer->installer->${method}($this->id, $data);
        $ret = $this->_displayData && $msg ? $this->_installer->waitForEnter($msg) : $msg;
        if ($this->_previousMenu) { $this->_installer->setPreviousMenu(); }
        if ($this->_exit) { $this->_installer->terminate($ret); }
      }
      // display nested menu
      if ($this->_subMenu) {
        $this->_installer->setMenu($this->_subMenu);
      }
    }
    return $ret;
	}
	// }}}
	
	
	// Static methods
	
	// {{{ isValid
	/**
	 * Static method that returns true if the object parameter is a 
   * SRA_InstallerMenuItem object
	 * @param object $object the object to validate
	 * @access public
	 * @return boolean
	 */
	function isValid( & $object ) {
		return (is_object($object) && (!isset($object->err) || !SRA_Error::isError($object->err)) && strtolower(get_class($object)) == 'sra_installermenuitem');
	}
	// }}}
  
}
// }}}
?>
Return current item: Sierra-php PHP Application Framework