1. <?php
  2. /**
  3. * Creates the page to add simple or global replacements.
  4. *
  5. * Replacements are install time search and replace strings
  6. * that can be used to set certain package variables to
  7. * values found on the user's system or that are specific
  8. * to the version of the installed package.
  9. *
  10. * @category   PEAR
  11. * @package    PEAR_PackageFileManager_Frontend_Web
  12. * @author     Laurent Laville <pear@laurent-laville.org>
  13. * @copyright  2005-2006 Laurent Laville
  14. * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
  15. * @since      File available since Release 0.1.0
  16. */
  17.  
  18. require_once 'Pager/Pager.php';
  19.  
  20. /**
  21. * Creates the page to add simple or global replacements.
  22. *
  23. * @category   PEAR
  24. * @package    PEAR_PackageFileManager_Frontend_Web
  25. * @author     Laurent Laville <pear@laurent-laville.org>
  26. * @copyright  2005-2006 Laurent Laville
  27. * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
  28. * @since      Class available since Release 0.1.0
  29. */
  30. class ReplacementsPage extends TabbedPage
  31. {
  32.     /**
  33.      * Builds the current form-page.
  34.      *
  35.      * @since  0.1.0
  36.      * @access public
  37.      */
  38.     function buildForm()
  39.     {
  40.         $this->buildTabs();
  41.         // tab caption
  42.         $this->addElement('header', null, 'Add a replacement option for one or all files');
  43.  
  44.         $fe =& PEAR_PackageFileManager_Frontend::singleton();
  45.         $sess =& $fe->container();
  46.  
  47.         $selection = $this->getSubmitValue('files');
  48.         if (isset($selection) && !is_array($selection)) {
  49.             $selection = array($selection);
  50.         }
  51.  
  52.         $selection_count = empty($selection) ? 0 : count($selection);
  53.         $fe->log('debug',
  54.             str_pad($this->getAttribute('id') .'('. __LINE__ .')', 20, '.') .
  55.             ' selection='. serialize($selection)
  56.         );
  57.  
  58.         list($page, $action) = $this->controller->getActionName();
  59.  
  60.         // selection list (false) or edit dialog frame (true)
  61.         if ($action == 'edit' && $selection_count > 0) {
  62.             $editDialog = true;
  63.         }elseif ($action == 'save' || $action == 'new') {
  64.             $editDialog = true;
  65.         } else {
  66.             $editDialog = false;
  67.         }
  68.  
  69.         // set default dependencies list used when we click on 'Reset' button
  70.         $fe->setDefaults('files');
  71.  
  72.         if (!$editDialog) {
  73.  
  74.             // File list Generator options list: (value => text, with value === text)
  75.             $settings = $fe->getOption(array('settings', 'pfm'), false);
  76.             $generator = $settings['pfm']['filelistgenerator'];
  77.             sort($generator, SORT_ASC);
  78.             $generator = array_combine($generator, $generator);
  79.  
  80.             // We need a group combo box + button for the file list plugin generator.
  81.             $plugin = array();
  82.             $plugin[] = &HTML_QuickForm::createElement('select', 'filelistgenerator', 'plugin', $generator);
  83.             $plugin[] = &HTML_QuickForm::createElement('submit', $this->getButtonName('list'), 'List');
  84.             $this->addGroup($plugin, 'plugin', 'File list generator :', '', false);
  85.  
  86.             $flplugin = $this->getSubmitValue('filelistgenerator');
  87.  
  88.             $hdr = array('Path', 'Replaces');
  89.             $table = new HTML_Table(array('class' => 'tableone'));
  90.             $htmltableDecorator = new PEAR_PackageFileManager_Frontend_Decorator_HTMLTable($fe);
  91.             $htmltableDecorator->setHtmlTable($table);
  92.             $htmltableDecorator->getFileList(false, false, $flplugin, $hdr);
  93.             // We need a simple static html area for package files list.
  94.             $this->addElement('static', 'packagefiles', '', $htmltableDecorator->toHtml());
  95.  
  96.             $def = array('filelistgenerator' => 'File');
  97.             $this->setDefaults($def);
  98.  
  99.             $commands = array('ignore', 'edit', 'remove');
  100.             $nocmd    = array('commit');
  101.  
  102.         } else {
  103.             $types = array('', 'package-info','pear-config','php-const');
  104.  
  105.             $const = get_defined_constants();
  106.             $const = array_keys($const);
  107.             sort($const, SORT_ASC);
  108.  
  109.             $pearConfig =& new PEAR_Config();
  110.             $keys = $pearConfig->getKeys();
  111.             sort($keys, SORT_ASC);
  112.  
  113.             $package_info = array('name','summary','description','version',
  114.                 'release_date','release_license','release_state','release_notes'
  115.             );
  116.  
  117.             // for each "replace type"
  118.             for ($i = 0; $i < 4; $i++) {
  119.                 $select_type[$types[$i]] = $types[$i];
  120.                 // retrieve associative "replace to" values
  121.                 switch ($i) {
  122.                     case 0: // none
  123.                         $select_to[$types[$i]][''] = '';
  124.                         break;
  125.                     case 1: // from package-info
  126.                         foreach($package_info as $section) {
  127.                             $select_to[$types[$i]][$section] = $section;
  128.                         }
  129.                         break;
  130.                     case 2: // from pear-config
  131.                         foreach($keys as $config) {
  132.                             $select_to[$types[$i]][$config] = $config;
  133.                         }
  134.                         break;
  135.                     case 3: // from php-const
  136.                         foreach($const as $j => $constName) {
  137.                             $select_to[$types[$i]][$constName] = $constName;
  138.                         }
  139.                         break;
  140.                 }
  141.             }
  142.  
  143.             // we need a simple text box for the string to replace
  144.             $this->addElement('text', 'replace_from', 'Replace:', array('size' => 40));
  145.  
  146.             // we need a multiple-select box for list of file targets
  147.             $rPath =& $this->addElement('select', 'replace_file');
  148.             $rPath->setMultiple(true);
  149.             $label  = 'Into file';
  150.             $label .= ($selection_count > 1) ? 's' : '';
  151.             $label .= ':';
  152.             $rPath->setLabel($label);
  153.             $rPath->freeze();
  154.  
  155.             $replace_type =& $this->addElement('hierselect', 'replace_type', null,
  156.                 array('class' => 'flat'), '<br />');
  157.             $replace_type->setLabel('Type:');
  158.             $replace_type->setOptions(array($select_type, $select_to));
  159.  
  160.             // we need a simple select box for platform exception list
  161.             $platform = array('', 'windows', '(*ix|*ux)');
  162.             $platform = array_combine($platform, $platform);
  163.             $this->addElement('select', 'platform_exception', 'Platform exception:', $platform);
  164.  
  165.             if ($selection_count == 0) {
  166.                 $key1 = -1;
  167.                 $def = array();
  168.                 $rPath->load($sess['files']['mapping']);
  169.             } else {
  170.                 $keys = $needle = array_keys($selection);
  171.                 $key1 = array_shift($needle);
  172.  
  173.                 $params = array(
  174.                     'httpMethod'  => 'POST',
  175.                     'clearIfVoid' => false,
  176.                     'perPage'     => 1,
  177.                     'itemData'    => $sess['files'][$key1]['replacements']
  178.                 );
  179.                 $pager =& Pager::factory($params);
  180.                 $pgid  = $pager->getCurrentPageID();
  181.                 $item  = $pager->getPageData();
  182.                 $fe->log('debug',
  183.                     str_pad($this->getAttribute('id') .'('. __LINE__ .')', 20, '.') .
  184.                     ' page id.='. $pgid
  185.                 );
  186.                 $fe->log('debug',
  187.                     str_pad($this->getAttribute('id') .'('. __LINE__ .')', 20, '.') .
  188.                     ' item id.='. serialize($item)
  189.                 );
  190.                 $fe->log('debug',
  191.                     str_pad($this->getAttribute('id') .'('. __LINE__ .')', 20, '.') .
  192.                     ' item ct.='. $pager->numItems()
  193.                 );
  194.                 $links = $pager->getLinks();
  195.  
  196.                 if ($item) {
  197.                     $item = array_shift($item);
  198.                     // We need a simple static html area for paging between replace items.
  199.                     $this->addElement('static', 'paging', 'Item #:', $links['pages']);
  200.                 }
  201.  
  202.                 $files = array();
  203.                 foreach($keys as $k) {
  204.                     $files[$k] = $sess['files']['mapping'][$k];
  205.                 }
  206.                 $rPath->load($files, $keys);
  207.                 $def = array(
  208.                     'replace_file' => $keys,
  209.                     'replace_from' => $item['from'],
  210.                     'replace_type' => array($item['type'], $item['to']),
  211.                     'platform_exception' => $sess['files'][$key1]['platform']
  212.                 );
  213.             }
  214.  
  215.             $this->addElement('hidden', 'replaceid', $pgid - 1);
  216.  
  217.             // old values of edit user
  218.             $this->setDefaults($def);
  219.  
  220.             $commands = array('new', 'save', 'cancel');
  221.             $nocmd    = array('commit','reset');
  222.         }
  223.         // applies new filters to the element values
  224.         $this->applyFilter('__ALL__', 'trim');
  225.         // apply form rules
  226.         $this->addFormRule(array(&$this, 'cbValidateReplacement'));
  227.  
  228.         // Buttons of the wizard to do the job
  229.         $this->buildButtons($nocmd, $commands);
  230.     }
  231.  
  232.     /**
  233.      * Callback to validate Replacement form page in edit mode
  234.      *
  235.      * @return TRUE on form validation success, errors array if form validation failed
  236.      * @since  0.1.0
  237.      * @access private
  238.      */
  239.     function cbValidateReplacement($fields)
  240.     {
  241.         $errors = array();
  242.         if (empty($fields['replace_from']) && intval($fields['replace_type'][1]) > 0) {
  243.             $errors['replace_from'] = 'String to replace is required';
  244.         }
  245.         return empty($errors)? true: $errors;
  246.     }
  247.  
  248.     /**
  249.      * Sets the default values for the replacements page
  250.      *
  251.      * @return void
  252.      * @since  0.1.0
  253.      * @access public
  254.      * @see    HTML_QuickForm_Controller::applyDefaults()
  255.      */
  256.     function applyDefaults()
  257.     {
  258.         list($page, $action) = $this->controller->getActionName();
  259.         $fe =& PEAR_PackageFileManager_Frontend::singleton();
  260.         $fe->log('debug',
  261.             str_pad($this->getAttribute('id') .'('. __LINE__ .')', 20, '.') .
  262.             " applyDefaults ActionName=($page,$action)"
  263.         );
  264.  
  265.         if ($action == 'reset') {
  266.             $fe->getFileList(true);
  267.         }
  268.     }
  269. }
  270.  
  271. /**
  272. * Manage actions to ignore file from selection or edit simple/global replacements.
  273. *
  274. * @category   PEAR
  275. * @package    PEAR_PackageFileManager_Frontend_Web
  276. * @author     Laurent Laville <pear@laurent-laville.org>
  277. * @copyright  2005-2006 Laurent Laville
  278. * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
  279. * @since      Class available since Release 0.1.0
  280. */
  281. class ReplacementsPageAction extends HTML_QuickForm_Action
  282. {
  283.     /**
  284.      * Processes the request.
  285.      *
  286.      * @param  object   HTML_QuickForm_Page  the current form-page
  287.      * @param  string   Current action name, as one Action object can serve multiple actions
  288.      * @since  0.1.0
  289.      * @access public
  290.      */
  291.     function perform(&$page, $actionName)
  292.     {
  293.         $page->isFormBuilt() or $page->buildForm();
  294.         $pageName = $page->getAttribute('id');
  295.         $fe =& PEAR_PackageFileManager_Frontend::singleton();
  296.         $fe->log('debug',
  297.             str_pad($pageName .'('. __LINE__ .')', 20, '.') .
  298.             ' ActionProcess='. $actionName
  299.         );
  300.  
  301.         if ($actionName == 'edit' || $actionName == 'cancel') {
  302.             return $page->handle('display');
  303.         }
  304.  
  305.         // save the form values and validation status to the session
  306.         $sess =& $fe->container();
  307.         $sess['values'][$pageName] = $page->exportValues();
  308.         $sess['valid'][$pageName]  = $page->validate();
  309.  
  310.         if (isset($sess['valid'][$pageName]) && $sess['valid'][$pageName]) {
  311.  
  312.             switch ($actionName) {
  313.                 case 'list':
  314.                     unset($sess['files']);
  315.                     $fe->getFilelist(false, false, $sess['values'][$pageName]['filelistgenerator']);
  316.                     $fe->setDefaults('files', null, true);
  317.                     break;
  318.                 case 'ignore':
  319.                     $selection = $page->getSubmitValue('files');
  320.                     if (is_array($selection)) {
  321.                         $keys = array_keys($selection);
  322.                         foreach ($keys as $k) {
  323.                             $fe->log('info',
  324.                                 str_pad($pageName .'('. __LINE__ .')', 20, '.') .
  325.                                 ' ignore file: "' . $sess['files']['mapping'][$k] . '"'
  326.                             );
  327.                             $sess['files'][$k]['ignore'] = true;
  328.                         }
  329.                     }
  330.                     break;
  331.                 case 'remove':
  332.                     $selection = $page->getSubmitValue('files');
  333.                     if (is_array($selection)) {
  334.                         $keys = array_keys($selection);
  335.                         foreach ($keys as $k) {
  336.                             $sess['files'][$k]['replacements'] = array();
  337.                         }
  338.                     }
  339.                     break;
  340.                 case 'new':
  341.                 case 'save':
  342.                     $data = $page->exportValues(array(
  343.                         'replace_file','replace_from','replace_type','platform_exception')
  344.                     );
  345.  
  346.                     $keys = $data['replace_file'];
  347.                     $fe->log('info',
  348.                         str_pad($pageName .'('. __LINE__ .')', 20, '.') .
  349.                         ' replace files: '. serialize($keys)
  350.                     );
  351.                     if (!is_array($keys)) {
  352.                         $keys = array($keys);
  353.                     }
  354.                     foreach($keys as $k) {
  355.                         if ($actionName == 'new') {
  356.                             $rid = count($sess['files'][$k]['replacements']);
  357.                         } else {
  358.                             $rid = $sess['values'][$pageName]['replaceid'];
  359.                         }
  360.                         $sess['files'][$k]['replacements'][$rid] = array(
  361.                             'from' => $data['replace_from'],
  362.                             'type' => $data['replace_type'][0],
  363.                             'to'   => $data['replace_type'][1]
  364.                         );
  365.                         $sess['files'][$k]['platform'] = empty($data['platform_exception'])
  366.                             ? false : $data['platform_exception'];
  367.                         $fe->log('info',
  368.                             str_pad($pageName .'('. __LINE__ .')', 20, '.') .
  369.                             ' add replacement: "'. $types[$data['replace_type'][0]] .
  370.                             '" (from='. $data['replace_from'] .', to='. $data['to'] .
  371.                             ') for "'. $data['mapping'] .'"'
  372.                         );
  373.                     }
  374.                     break;
  375.             }
  376.             return $page->handle('jump');
  377.         }
  378.         return $page->handle('display');
  379.     }
  380. }
  381. ?>