PHPConfig
[ class tree: PHPConfig ] [ index: PHPConfig ] [ all elements ]

Source for file PHPConfig.php

Documentation is available at PHPConfig.php

  1. <?php
  2.  
  3. /**
  4.  * Class for GUI-based configuration of a php.ini file
  5.  *
  6.  * PHP Version 5
  7.  *
  8.  * This class is based on the PHP-Gtk2 extension and provides a
  9.  * user-friendly interface for editing php.ini files. All the possible
  10.  * configuration options have been defined in a separate XML file .
  11.  * This allows for easy addition of directives as PHP is
  12.  * developed further.
  13.  *
  14.  * The class can parse any existing ini file, or create new ones. Parsing
  15.  * of existing files is currently a little inefficient, suggestions for
  16.  * improvement are welcome. New files and files previously generated by
  17.  * Gtk2_PHPConfig are parsed at a good speed though.
  18.  *
  19.  * The interface displays all available configuration sections on the left
  20.  * pane, and their corresponding options in the top right pane. The bottom
  21.  * right pane displays the description of the option selected and the
  22.  * facility to change the value of that option.
  23.  *
  24.  * @todo    Implement Christian's suggestion of asking for confirmation when a
  25.  *           file is overwritten while doing a "save as"
  26.  * @todo    Add facility to add directives, apart from additions to XML
  27.  * @todo    Clicking Cancel on the File-Open dialog generates a notice
  28.  *
  29.  * @category Gtk2
  30.  * @package  PHPConfig
  31.  * @author   Anant Narayanan <anant@php.net>
  32.  * @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
  33.  * @link     http://pear.php.net/package/Gtk2_PHPConfig
  34.  *
  35.  */
  36.  
  37. /**
  38.  * Gtk2_PHPConfig
  39.  *
  40.  * @category Gtk2
  41.  * @package  PHPConfig
  42.  * @author   Anant Narayanan <anant@php.net>
  43.  * @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
  44.  * @link     http://pear.php.net/package/Gtk2_PHPConfig
  45.  */
  46. class Gtk2_PHPConfig extends GtkWindow
  47. {
  48.     // {{{ properties
  49.  
  50.     /**
  51.      * Tree that displays the available configuration sections.
  52.      *
  53.      * @var GtkTreeView 
  54.      * @access protected
  55.      */
  56.     protected $sectionTree;
  57.  
  58.     /**
  59.      * Tree that displays the current section's corresponding options.
  60.      *
  61.      * @var GtkTreeView 
  62.      * @access protected
  63.      */
  64.     protected $optionTree;
  65.  
  66.     /**
  67.      * Description of the currently selected option.
  68.      *
  69.      * @var GtkTextBuffer 
  70.      * @access protected
  71.      */
  72.     protected $optionDesc;
  73.  
  74.     /**
  75.      * Comments associated with the currently selected option.
  76.      *
  77.      * @var GtkTextBuffer 
  78.      * @access protected
  79.      */
  80.     protected $optionComments;
  81.  
  82.     /**
  83.      * The entry box that will accept the value of the current option from
  84.      * the user.
  85.      *
  86.      * @var GtkEntry 
  87.      * @access protected
  88.      */
  89.     protected $optionEntry;
  90.  
  91.     /**
  92.      * The file name of the php.ini file currently open. Will be set to
  93.      * null if a new file is to be generated.
  94.      *
  95.      * @var string 
  96.      * @access protected
  97.      */
  98.     protected $fileName;
  99.  
  100.     /**
  101.      * The XML definition file holding descriptions of all possible php.ini
  102.      * directives.
  103.      *
  104.      * @var DOMDocument 
  105.      * @access protected
  106.      */
  107.     protected $xmlDefs;
  108.  
  109.     /**
  110.      * The XPath object to the XML definition file.
  111.      *
  112.      * @var DOMXPath 
  113.      * @access protected
  114.      */
  115.     protected $xpath;
  116.  
  117.     /**
  118.      * A flag that determined whether the current file is saved or not.
  119.      *
  120.      * @var bool 
  121.      * @access protected
  122.      */
  123.     protected $saved;
  124.  
  125.     /**
  126.      * A buffer used to temporarily store the contents of the currently
  127.      * open file when the save as option is used
  128.      *
  129.      * @var Array 
  130.      * @access protected
  131.      */
  132.     protected $saveasBuffer;
  133.  
  134.     /**
  135.      * The "buffer" array that stores the current values of all the
  136.      * options.
  137.      *
  138.      * @var Array 
  139.      * @access protected
  140.      */
  141.     protected $optionIndex;
  142.  
  143.     /**
  144.      * The progress window that displays the percentage by which a file
  145.      * is parsed.
  146.      *
  147.      * @var GtkWindow 
  148.      * @access protected
  149.      */
  150.     protected $progress;
  151.  
  152.     /**
  153.      * The extension modules loaded/unloaded in the current file parsed.
  154.      *
  155.      * @var Array 
  156.      * @access protected
  157.      */
  158.     protected $extensions;
  159.  
  160.     //}}}
  161.     //{{{ constants
  162.  
  163.     /**
  164.      * Title of the Window.
  165.      */
  166.     const TITLE = "The PHP Configuration GUI";
  167.  
  168.     /**
  169.      * Array Index - Current Value of a directive
  170.      */
  171.     const DIR_CURRENT = "Current";
  172.  
  173.     /**
  174.      * Array Index - Default Value of a directive
  175.      */
  176.     const DIR_DEFAULT = "Default";
  177.  
  178.     /**
  179.      * Array Index - Line number of directive
  180.      */
  181.     const DIR_NUMBER = "LineNumber";
  182.     /**
  183.      * Array Index - Comments in a directive
  184.      */
  185.     const COMMENT_NORMAL = "CommentsN";
  186.  
  187.     /**
  188.      * Array Index - InLine comments of directive
  189.      */
  190.     const COMMENT_INLINE = "CommentsI";
  191.  
  192.     /**
  193.      * Extension Option - Extension is enabled
  194.      */
  195.     const EXT_ENABLED = "Enabled";
  196.  
  197.     /**
  198.      * Extension Option - Extension is disabled
  199.      */
  200.     const EXT_DISABLED = "Disabled";
  201.  
  202.     //}}}
  203.     //{{{ __construct()
  204.  
  205.     /**
  206.      * Sets the classes' properties and calls the creation of the GUI
  207.      * interface.
  208.      *
  209.      * @param string $fileName Filename of the ini file to be edited.
  210.      *                          Will be null if a new file is to be created.
  211.      *
  212.      * @return void 
  213.      */
  214.     function __construct($fileName)
  215.     {
  216.         parent::__construct();
  217.         include_once "PEAR/Config.php";
  218.         $this->fileName = $fileName;
  219.         $this->saved    = false;
  220.         $this->xmlDefs  = new DomDocument();
  221.         //where data is stored
  222.         $dataDir = PEAR_Config::singleton()->get("data_dir".
  223.             DIRECTORY_SEPARATOR . "Gtk2_PHPConfig";
  224.         $this->xmlDefs->load($dataDir."/phpinidefs.xml");
  225.         $this->xpath = new DOMXPath($this->xmlDefs);
  226.         //optionIndex
  227.         $this->optionIndex = $this->getValues();
  228.         $this->buildGUI();
  229.     }
  230.  
  231.     //}}}
  232.     //{{{ buildGUI()
  233.  
  234.     /**
  235.      * Creates the user interface to facilitate editing of the ini files.
  236.      * Also calls other functions that parse the XML definition file and
  237.      * then displays the configuration options.
  238.      *
  239.      * @return void 
  240.      */
  241.     function buildGUI()
  242.     {
  243.         /* Creating the layout boxes */
  244.         $MainVBox = new GtkVBox();
  245.         $TopHPane = new GtkHPaned();
  246.         $TopHPane->set_position(200);
  247.         $rightVPane = new GtkVPaned();
  248.  
  249.         /* Displaying the configuration sections */
  250.         $sectionList       $this->buildSectionList();
  251.         $this->sectionTree = $sectionList;
  252.         // add sectionList to a scrolled window
  253.         $leftScroll = new GtkScrolledWindow();
  254.         $leftScroll->set_policy(Gtk::POLICY_NEVERGtk::POLICY_AUTOMATIC);
  255.         $leftScroll->add($sectionList);
  256.  
  257.         /* Creating the tree that will display configuration options */
  258.         $model = new GtkListStore(Gobject::TYPE_STRING,
  259.             Gobject::TYPE_STRING,
  260.             Gobject::TYPE_STRING);
  261.         $tree  = new GtkTreeView($model);
  262.         // set the optionTree
  263.         $this->optionTree = $tree;
  264.  
  265.         $rightScroll = new GtkScrolledWindow();
  266.         $rightScroll->set_policy(Gtk::POLICY_AUTOMATICGtk::POLICY_AUTOMATIC);
  267.         $rightScroll->add($tree);
  268.         $rightScroll->set_size_request(-1400);
  269.  
  270.         $bottomHBox = new GtkHBox();
  271.         $bottomHBox->pack_start($this->buildDescBox()truetrue);
  272.         $bottomHBox->pack_start($this->buildValueBox()falsefalse);
  273.  
  274.         $rightVPane->pack1($rightScroll);
  275.         $rightVPane->pack2($bottomHBox);
  276.  
  277.         $TopHPane->add1($leftScroll);
  278.         $TopHPane->add2($rightVPane);
  279.         $MainVBox->pack_start($this->buildMenu()falsefalse);
  280.         $MainVBox->pack_start($TopHPanetruetrue);
  281.  
  282.         /* Initialise the main window */
  283.         $this->add($MainVBox);
  284.         $this->setTitle();
  285.         $this->show_all();
  286.         $this->set_size_request(800600);
  287.         $this->set_position(Gtk::WIN_POS_CENTER);
  288.         $this->connect_simple("delete-event"array($this"quit"));
  289.     }
  290.  
  291.     //}}}
  292.     //{{{ buildMenu()
  293.  
  294.     /**
  295.      * Creates and returns the menu for the GUI
  296.      *
  297.      * @return GtkMenuBar   The Menu bar of the GUI
  298.      */
  299.     function buildMenu()
  300.     {
  301.         $theMenu   = new GtkMenuBar();
  302.         $menuAccel = new GtkAccelGroup();
  303.         $this->add_accel_group($menuAccel);
  304.  
  305.         /* Creating the menu */
  306.         $fileMenu = new GtkMenu();
  307.  
  308.         $fileNew = new GtkImageMenuItem(Gtk::STOCK_NEW$menuAccel);
  309.         $fileNew->connect_simple("activate"array($this"newFile"));
  310.         $fileMenu->append($fileNew);
  311.  
  312.         $fileOpen = new GtkImageMenuItem(Gtk::STOCK_OPEN$menuAccel);
  313.         $fileOpen->connect_simple("activate"array($this"openFile"));
  314.         $fileMenu->append($fileOpen);
  315.  
  316.         $fileSep = new GtkSeparatorMenuItem();
  317.         $fileMenu->append($fileSep);
  318.  
  319.         $fileSave = new GtkImageMenuItem(Gtk::STOCK_SAVE$menuAccel);
  320.         $fileSave->connect_simple("activate"array($this"saveFile"));
  321.         $fileMenu->append($fileSave);
  322.  
  323.         $fileSaveAs = new GtkImageMenuItem(Gtk::STOCK_SAVE_AS$menuAccel);
  324.         $fileSaveAs->connect_simple("activate"array($this"onSaveFileAs"));
  325.         $fileMenu->append($fileSaveAs);
  326.  
  327.         $fileQuit = new GtkImageMenuItem(Gtk::STOCK_QUIT$menuAccel);
  328.         $fileQuit->connect_simple("activate"array($this"quit"));
  329.         $fileMenu->append($fileQuit);
  330.  
  331.         $fileButton = new GtkMenuItem("_File");
  332.         $fileButton->set_submenu($fileMenu);
  333.         $theMenu->append($fileButton);
  334.  
  335.         return $theMenu;
  336.     }
  337.  
  338.     //}}}
  339.     //{{{ buildDescBox()
  340.  
  341.     /**
  342.      * Creates and the description and comment boxes.
  343.      *
  344.      * @return GtkVBox  The descriptiona and comment boxes.
  345.      */
  346.     function buildDescBox()
  347.     {
  348.         /* Layout for the description and value setting boxes */
  349.         $descVBox   = new GtkVBox();
  350.         $descTitle  = new GtkFrame("Description");
  351.         $descWindow = new GtkScrolledWindow();
  352.         $descWindow->set_policy(Gtk::POLICY_AUTOMATICGtk::POLICY_AUTOMATIC);
  353.         $description = new GtkTextBuffer();
  354.         $descShow    = new GtkTextView($description);
  355.         $descShow->set_wrap_mode(Gtk::WRAP_WORD);
  356.         $descShow->set_size_request(-1150);
  357.         $this->optionDesc = $description;
  358.         $descWindow->add($descShow);
  359.         $commentTitle  = new GtkFrame("Comments");
  360.         $commentWindow = new GtkScrolledWindow();
  361.         $commentWindow->set_policy(Gtk::POLICY_AUTOMATICGtk::POLICY_AUTOMATIC);
  362.         $comments    = new GtkTextBuffer();
  363.         $commentShow = new GtkTextView($comments);
  364.         $commentShow->set_wrap_mode(Gtk::WRAP_WORD);
  365.         $this->optionComments = $comments;
  366.         $commentWindow->add($commentShow);
  367.         $descVBox->pack_start($descTitlefalsefalse);
  368.         $descTitle->add($descWindow);
  369.         $descVBox->pack_start($commentTitlefalsefalse);
  370.         $commentTitle->add($commentWindow);
  371.  
  372.         return $descVBox;
  373.     }
  374.  
  375.     //}}}
  376.     //{{{ buildValueBox()
  377.  
  378.     /**
  379.      * Creates and returns the value setting box
  380.      *
  381.      * @return  GtkVBox     The Value setting box.
  382.      */
  383.     function buildValueBox()
  384.     {
  385.         $valueVBox  = new GtkVBox();
  386.         $valueLabel = new GtkLabel("Set a value for the option");
  387.  
  388.         $entryBox   = new GtkHBox();
  389.         $valueEntry = new GtkEntry();
  390.         $valueEntry->connect_simple("activate"array($this"onValueSubmit"));
  391.         $this->optionEntry = $valueEntry;
  392.         //unset button
  393.         $valueUnset = new GtkButton(null);
  394.         $unsetIcon  = GtkImage::new_from_stock(Gtk::STOCK_CANCEL,
  395.             Gtk::ICON_SIZE_BUTTON);
  396.         $valueUnset->set_image($unsetIcon);
  397.         $entryBox->pack_start($valueEntrytruetrue);
  398.         $entryBox->pack_start($valueUnsetfalsefalse);
  399.  
  400.         $valueSubmit  = new GtkButton("Set Value");
  401.         $commentLabel = new GtkLabel("Comments are also added\n" .
  402.             "Use the red cross to unset.");
  403.         $setIcon      = GtkImage::new_from_stock(Gtk::STOCK_OK,
  404.             Gtk::ICON_SIZE_BUTTON);
  405.         $valueSubmit->set_image($setIcon);
  406.  
  407.         $valueSubmit->connect_simple("clicked"array($this"onValueSubmit"));
  408.         $valueUnset->connect_simple("clicked"array($this"onValueUnset"));
  409.  
  410.         /* Adding all the widgets and finalising layout */
  411.         $valueVBox->pack_start($valueLabelfalsefalse);
  412.         $valueVBox->pack_start($entryBoxfalsefalse);
  413.         $valueVBox->pack_start($valueSubmitfalsefalse);
  414.         $valueVBox->pack_start($commentLabelfalsefalse);
  415.  
  416.         return $valueVBox;
  417.     }
  418.  
  419.     //}}}
  420.     //{{{ buildSectionList()
  421.  
  422.     /**
  423.      * Generates a list of available configuration sections after parsing
  424.      * the XML definition file.
  425.      *
  426.      * @return GtkTreeView 
  427.      */
  428.     function buildSectionList()
  429.     {
  430.         /* Creating a new model to store configuration sections */
  431.         $model     = new GtkListStore(Gobject::TYPE_STRING);
  432.         $listItems $this->getSections();
  433.         foreach ($listItems as $item{
  434.             $model->append(array($item));
  435.         }
  436.         $tree     = new GtkTreeView($model);
  437.         $renderer = new GtkCellRendererText();
  438.         $tree->append_column(new GtkTreeViewColumn("Sections",
  439.             $renderer,
  440.             "text",
  441.             0));
  442.  
  443.         $itemSelect $tree->get_selection();
  444.         $itemSelect->set_mode(Gtk::SELECTION_SINGLE);
  445.         $itemSelect->connect("changed"array($this,"onSectionSelect"));
  446.         return $tree;
  447.     }
  448.  
  449.     //}}}
  450.     //{{{ onOptionSelect()
  451.  
  452.     /**
  453.      * Sets the description of the configuration option currently selected
  454.      * and displays it along with comments, if any.
  455.      *
  456.      * @param object $selected selected object
  457.      *
  458.      * @return void 
  459.      */
  460.     function onOptionSelect($selected)
  461.     {
  462.         list($model$iter)   $selected->get_selected();
  463.         list($sModel$sIter$this->sectionTree->get_selection()->get_selected();
  464.         if (!$iter || !$sIter{
  465.             return;
  466.         }
  467.         $option  $model->get_value($iter0);
  468.         $section $sModel->get_value($sIter0);
  469.         /* Querying XML definition file for configuration options
  470.          * corresponding to the currently selected confugration section
  471.          */
  472.  
  473.         if ($section == "Dynamic Extensions"{
  474.             $desc $this->xpath->query('/php-config-options/section/option[@id="extension"]/desc')->item(0)->nodeValue;
  475.             $this->optionEntry->set_text(self::EXT_ENABLED);
  476.             $this->optionDesc->set_text($desc);
  477.             $this->optionComments->set_text("");
  478.         else {
  479.             $desc     $this->xpath->query('/php-config-options/section/option[@id="'.$option.'"]/desc')->item(0)->nodeValue;
  480.             $defvalue $this->xpath->query('/php-config-options/section/option[@id="'.$option.'"]/default')->item(0)->nodeValue;
  481.             $this->optionEntry->set_text($defvalue);
  482.             $this->optionDesc->set_text($desc);
  483.             $this->optionComments->set_text($this->optionIndex[$option][self::COMMENT_NORMAL]);
  484.         }
  485.     }
  486.  
  487.     //}}}
  488.     //{{{ onSectionSelect
  489.  
  490.     /**
  491.      * Retreives and displays the set of configuration options associated
  492.      * with the currently selected configuration section.
  493.      *
  494.      * @param GtkTreeSelection $selected Selection object corresponding to the
  495.      *                                    currently selected configuration section.
  496.      *
  497.      * @return void 
  498.      */
  499.     function onSectionSelect($selected)
  500.     {
  501.         list($model$iter$selected->get_selected();
  502.         if (!$iter{
  503.             return;
  504.         }
  505.         $section     =  $model->get_value($iter0);
  506.         $optionList  $this->getOptions($section);
  507.         $optionModel $this->optionTree->get_model();
  508.         $optionModel->clear();
  509.  
  510.         /* Filling the model with corresponding configuration options */
  511.         foreach ($optionList as $option{
  512.             $optionModel->append(array($option[0]$option[1]$option[2]));
  513.         }
  514.         for ($i=0;$i<4;$i++{
  515.             if ($this->optionTree->get_column(0)) {
  516.                 $this->optionTree->remove_column($this->optionTree->get_column(0));
  517.             }
  518.         }
  519.         $cell = new GtkCellRendererText();
  520.         //what to name the column?
  521.         if ($section "Dynamic Extensions"{
  522.             $nameColumn = new GtkTreeViewColumn("Extension"$cell"text"0);
  523.         else {
  524.             $nameColumn = new GtkTreeViewColumn("Option"$cell"text"0);
  525.         }
  526.  
  527.         $currColumn = new GtkTreeViewColumn("Current Value"$cell"text"1);
  528.         $defColumn  = new GtkTreeViewColumn("Default Value"$cell"text"2);
  529.         $nameColumn->set_sort_column_id(0);
  530.         $nameColumn->set_resizable(true);
  531.         $currColumn->set_sort_column_id(1);
  532.         $currColumn->set_resizable(true);
  533.         $defColumn->set_sort_column_id(2);
  534.         $defColumn->set_resizable(true);
  535.  
  536.         $this->optionTree->append_column($nameColumn);
  537.         $this->optionTree->append_column($currColumn);
  538.         $this->optionTree->append_column($defColumn);
  539.  
  540.         $optionSelect $this->optionTree->get_selection();
  541.         $optionSelect->set_mode(Gtk::SELECTION_SINGLE);
  542.         $optionSelect->connect("changed"array($this"onOptionSelect"));
  543.  
  544.         /* Initial description is empty */
  545.         $this->optionDesc->set_text("");
  546.     }
  547.  
  548.     //}}}
  549.     //{{{ getSections()
  550.  
  551.     /**
  552.      * Returns an array of possible configuration sections after parsing the
  553.      * XML definition file.
  554.      *
  555.      * @return  Array 
  556.      */
  557.     function getSections()
  558.     {
  559.         $sectionNodes $this->xmlDefs->getElementsByTagName("section");
  560.         foreach ($sectionNodes as $sectionNode{
  561.             $sectionName $sectionNode->getAttribute("name");
  562.             $sections[]  $sectionName;
  563.         }
  564.         return $sections;
  565.     }
  566.  
  567.     //}}}
  568.     //{{{ getOptions()
  569.  
  570.     /**
  571.      * Returns an array of possible configuration options corresponding to
  572.      * a particular configuration section.
  573.      *
  574.      * @param string $section Name of the configuration section for
  575.      *                         which the configuration options must be
  576.      *                         returned.
  577.      *
  578.      * @return  Array 
  579.      */
  580.     function getOptions($section)
  581.     {
  582.         $optionList = array();
  583.  
  584.         if ($section=="Dynamic Extensions"{
  585.             foreach ($this->extensions as $extName=>$extData{
  586.                 $optionList[=
  587.                     array($extName,
  588.                           $extData[self::DIR_CURRENT],
  589.                           self::EXT_DISABLED);
  590.             }
  591.         else {
  592.             $optionNodes =
  593.                 $this->xpath->query('/php-config-options/section[@name="' .
  594.                     $section '"]/option');
  595.             foreach ($optionNodes as $optionNode{
  596.                 $optionName   $optionNode->getAttribute("id");
  597.                 $optionList[=
  598.                     array($optionName,
  599.                           $this->optionIndex[$optionName][self::DIR_CURRENT],
  600.                           $this->optionIndex[$optionName][self::DIR_DEFAULT]);
  601.             }
  602.         }
  603.         return $optionList;
  604.     }
  605.  
  606.     //}}}
  607.     //{{{ saveFile()
  608.  
  609.     /**
  610.      * Saves the current state of configuration into a file. Filename will
  611.      * be prompted for if a new file is to be generated.
  612.      *
  613.      * @param bool $saveas is this a 'saveas' operation. default to false.
  614.      *
  615.      * @return void 
  616.      */
  617.     function saveFile($saveas = false)
  618.     {
  619.         if ($this->fileName != null{
  620.             $toWrite $this->optionIndex;
  621.             $newFile = false;
  622.             if (!file_exists($this->fileName)) {
  623.                 $fp fopen($this->fileName"w+");
  624.                 fclose($fp);
  625.                 $newFile    = true;
  626.                 $lineNumber = 0;
  627.             }
  628.  
  629.             $theFile file($this->fileName);
  630.             $entry   = 0;
  631.             foreach ($toWrite as $option=>$value{
  632.                 /* Empty or Disabled configuration options are not written
  633.                  * to the file. */
  634.                 if (!$newFile{
  635.                     $lineNumber $value[self::DIR_NUMBER];
  636.                 else {
  637.                     $lineNumber += 1;
  638.                 }
  639.                 if (trim($value[self::COMMENT_INLINE]== ""{
  640.                     $inline "\n";
  641.                 else {
  642.                     $inline " ;".$value[self::COMMENT_INLINE]."\n";
  643.                 }
  644.                 if ($value[self::DIR_CURRENT!= "Disabled" &&
  645.                     trim($value[self::DIR_CURRENT]!= ""{
  646.                     if (trim($value[self::COMMENT_NORMAL]!= ""{
  647.                         $theFile[$lineNumber"\n;/ ".str_replace("\n""\n;/ ",
  648.                         $value[self::COMMENT_NORMAL])."\n";
  649.                     }
  650.                     $theFile[$lineNumber$option " = " .
  651.                         $value[self::DIR_CURRENT$inline;
  652.                 elseif ($value[self::DIR_CURRENT== "Disabled" ||
  653.                           trim($value[self::DIR_CURRENT]== ""{
  654.                         $theFile[$lineNumber";"
  655.                             . $option " = "
  656.                             . $value[self::DIR_DEFAULT$inline;
  657.                 }
  658.             }
  659.  
  660.             foreach ($this->extensions as $extName=>$value{
  661.                 if (!$newFile{
  662.                     $lineNumber $value[self::DIR_NUMBER];
  663.                 else {
  664.                     $lineNumber += 1;
  665.                 }
  666.                 if (trim($value[self::COMMENT_INLINE]== ""{
  667.                     $inline "\n";
  668.                 else {
  669.                     $inline " ;".$value[self::COMMENT_INLINE]."\n";
  670.                 }
  671.                 if ($value[self::DIR_CURRENT== self::EXT_ENABLED{
  672.                     $theFile[$lineNumber"extension = ".$extName.$inline;
  673.                 else {
  674.                     $theFile[$lineNumber";extension = ".$extName.$inline;
  675.                 }
  676.             }
  677.             $this->saved = true;
  678.             file_put_contents($this->fileName$theFile);
  679.  
  680.         else {
  681.             /* New file to be saved, prompt for filename */
  682.             $filePrompt = new GtkFileChooserDialog("Save file as:",
  683.                 $this,
  684.                 Gtk::FILE_CHOOSER_ACTION_SAVE,
  685.                 array(Gtk::STOCK_CANCEL,
  686.                     Gtk::RESPONSE_CANCEL,
  687.                     Gtk::STOCK_SAVE,
  688.                     Gtk::RESPONSE_ACCEPT));
  689.  
  690.             if ($filePrompt->run(== Gtk::RESPONSE_ACCEPT{
  691.                 $this->onSaveFile($filePrompt$saveas);
  692.                 $this->saved = true;
  693.             }
  694.             $filePrompt->destroy();
  695.         }
  696.         $this->setTitle();
  697.     }
  698.  
  699.     //}}}
  700.     //{{{ onSaveFile()
  701.  
  702.     /**
  703.      * Called in case a new file is to be generated after a filename has
  704.      * been prompted for. Sets the filename property to the filename chosen
  705.      * by the user and calls the saveFile() function.
  706.      *
  707.      * @param GtkFileSelection $filePrompt File selection dialog
  708.      *                                      object that called
  709.      *                                      this function.
  710.      * @param bool             $saveas     is this a 'saveas' operation.
  711.      *
  712.      * @return void 
  713.      */
  714.     function onSaveFile($filePrompt$saveas)
  715.     {
  716.         $this->fileName = $filePrompt->get_filename();
  717.         if ($saveas{
  718.             $saveasFile fopen($this->fileName"w+");
  719.             file_put_contents($this->fileName$this->saveasBuffer);
  720.             fclose($saveasFile);
  721.         }
  722.         $this->saveFile();
  723.     }
  724.  
  725.     //}}}
  726.     //{{{ onSaveFileAs()
  727.  
  728.     /**
  729.      * Called in case the "Save As..." option is selected. The function
  730.      * will prompt for a filename to save the file as.
  731.      *
  732.      * @return void 
  733.      */
  734.     function onSaveFileAs()
  735.     {
  736.         if ($this->fileName != null{
  737.             $this->saveasBuffer = file($this->fileName);
  738.             $this->fileName     = null;
  739.             $this->saveFile(true);
  740.         else {
  741.             $this->saveFile();
  742.         }
  743.     }
  744.  
  745.     //}}}
  746.     //{{{ onValueSubmit()
  747.  
  748.     /**
  749.      * Sets the new user-defined value for the configuration option in the
  750.      * buffer.
  751.      *
  752.      * @return void 
  753.      */
  754.     function onValueSubmit()
  755.     {
  756.         $selection $this->optionTree->get_selection();
  757.         //set what's selected
  758.         list($model$iter)   $selection->get_selected();
  759.         list($sModel$sIter=
  760.             $this->sectionTree->get_selection()->get_selected();
  761.         if (!$iter || !$sIter{
  762.             return;
  763.         }
  764.  
  765.         $option  $model->get_value($iter0);
  766.         $section $sModel->get_value($sIter0);
  767.         $value   $this->optionEntry->get_text();
  768.         $model->set($iter1$value);
  769.  
  770.         /* Retreive the comments, if any, in the buffer */
  771.         $comments $this->optionComments;
  772.         $comments $comments->get_text($comments->get_start_iter(),
  773.                                         $comments->get_end_iter());
  774.  
  775.         if ($section == "Dynamic Extensions"{
  776.             $this->extensions[$option][self::DIR_CURRENT$value;
  777.             if (trim($comments!= ""{
  778.                 $this->extensions[$option][self::COMMENT_NORMAL$comments;
  779.             }
  780.         else {
  781.             $this->optionIndex[$option][self::DIR_CURRENT$value;
  782.             if (trim($comments!= ""{
  783.                 $this->extensions[$option][self::COMMENT_NORMAL$comments;
  784.             }
  785.         }
  786.  
  787.         /* Set saved flag to false */
  788.         $this->saved = false;
  789.         $this->setTitle();
  790.     }
  791.  
  792.     //}}}
  793.     //{{{ onValueUnset()
  794.  
  795.     /**
  796.      * Unsets the value of the currently selected configuration directive to
  797.      * disabled so that it does not appear in the configuration file.
  798.      *
  799.      *  @return void 
  800.      */
  801.     function onValueUnset()
  802.     {
  803.         $selection            $this->optionTree->get_selection();
  804.         list($model$iter)   $selection->get_selected();
  805.         list($sModel$sIter$this->sectionTree->get_selection()->get_selected();
  806.         if (!$iter || !$sIter{
  807.             return;
  808.         }
  809.  
  810.         $option  $model->get_value($iter0);
  811.         $section $sModel->get_value($sIter0);
  812.         $model->set($iter1"Disabled");
  813.  
  814.         if ($section == "Dynamic Extensions"{
  815.             $this->extensions[$option][self::DIR_CURRENT= self::EXT_DISABLED;
  816.         else {
  817.             $this->optionIndex[$option][self::DIR_CURRENT"Disabled";
  818.         }
  819.  
  820.         $this->saved = false;
  821.         $this->setTitle();
  822.     }
  823.  
  824.     //}}}
  825.     //{{{ getValues()
  826.  
  827.     /**
  828.      * Parses the XML definition file and returns the initial state of the
  829.      * buffer. Additionally, if an existing file is opened, parses that
  830.      * file and modifies the buffer to reflect the current state of that
  831.      * file.
  832.      *
  833.      * @return  Array 
  834.      */
  835.     function getValues()
  836.     {
  837.         $index       = array();
  838.         $extensions  = array();
  839.         $current     "";
  840.         $comment     "";
  841.         $optionNodes $this->xmlDefs->getElementsByTagName("option");
  842.         $options     = array();
  843.         foreach ($optionNodes as $node{
  844.             $options[= array($node->getAttribute("id"),
  845.                 $node->getElementsByTagName("default")->item(0)->nodeValue);
  846.         }
  847.         $this->showProgress();
  848.  
  849.         foreach ($options as $no => $optionData{
  850.             $total count($options);
  851.             if ($this->fileName != null{
  852.                 $optionName $optionData[0];
  853.                 $optionDef  $optionData[1];
  854.                 /* Set all configuration options to disabled. These values
  855.                  * will be rewritten after parsing the INI file
  856.                  */
  857.                 $index[$optionName= array(self::DIR_CURRENT=>"Disabled",
  858.                     self::DIR_DEFAULT => $optionDef,
  859.                     self::COMMENT_NORMAL => "",
  860.                     self::COMMENT_INLINE => "",
  861.                     self::DIR_NUMBER => "");
  862.                 $this->updateProgress(($no/$total)/10);
  863.             else {
  864.                 /* Set all configuration options to default values since a
  865.                  * new file is to be generated
  866.                  */
  867.                 $optionName $optionData[0];
  868.                 $optionDef  $optionData[1];
  869.                 // set option name
  870.                 $index[$optionName= array(self::DIR_CURRENT => $optionDef,
  871.                     self::DIR_DEFAULT => $optionDef,
  872.                     self::COMMENT_NORMAL => "",
  873.                     self::COMMENT_INLINE => "",
  874.                     self::DIR_NUMBER => "");
  875.                 $this->updateProgress($no/$total);
  876.             }
  877.         }
  878.         if ($this->fileName != null{
  879.             $status file($this->fileName);
  880.             $total  count($status);
  881.             foreach ($status as $no=>$line{
  882.                 $this->updateProgress(0.1 + (0.9 * ($no $total)));
  883.                 foreach ($options as $opNo => $data{
  884.                     if (strpos($line"extension"!== false{
  885.                         if (substr($line09== "extension"{
  886.                             $extStatus = self::EXT_ENABLED;
  887.                         elseif (substr($line19== "extension"{
  888.                             $extStatus = self::EXT_DISABLED;
  889.                         }
  890.                         if (isset($extStatus)) {
  891.                             $check explode("="$line);
  892.                             if (trim($check[0]== "extension" ||
  893.                                 trim($check[0]== ";extension"{
  894.                                 $extValue    $check[1];
  895.                                 $remComments explode(";"$extValue);
  896.                                 $extName     trim($remComments[0]);
  897.                                 if (array_key_exists(1$remComments)) {
  898.                                     $extensions[$extName][self::COMMENT_INLINE=
  899.                                         $remComments[1];
  900.                                 else {
  901.                                     $extensions[$extName][self::COMMENT_INLINE"";
  902.                                 }
  903.                                 $extensions[$extName][self::DIR_CURRENT=
  904.                                     $extStatus;
  905.                                 $extensions[$extName][self::DIR_NUMBER]  $no;
  906.                             }
  907.                         }
  908.                     }
  909.                     if (strpos($line$data[0])!==false{
  910.                         $delFlag      = false;
  911.                         $optionName   trim($data[0]);
  912.                         $optionLength strlen(trim($optionName));
  913.                         $optionShown  substr($line0$optionLength);
  914.                         $optionHidden substr($line1$optionLength);
  915.                         if ($optionShown == $optionName{
  916.                             $whereis   strpos($line"=");
  917.                             $directive substr($line0$whereis);
  918.                             $values    substr($line,
  919.                                 $whereis + 1,
  920.                                 strlen($line$whereis);
  921.                             $values    explode(";"$values);
  922.                             /* Check if this is not part of a bigger extension */
  923.                             if (strlen(trim($directive)) ==
  924.                                 strlen(trim($optionName))) {
  925.                                 $index[$optionName][self::DIR_CURRENT]    =
  926.                                     trim($values[0]);
  927.                                 $index[$optionName][self::COMMENT_NORMAL=
  928.                                     $comment;
  929.                                 $index[$optionName][self::DIR_NUMBER]     =
  930.                                     $no;
  931.                                 if (array_key_exists(1$values)) {
  932.                                     $index[$optionName][self::COMMENT_INLINE=
  933.                                         trim($values[1]);
  934.                                 }
  935.                             }
  936.                             $comment "";
  937.                             $delFlag = true;
  938.                         elseif ($optionHidden == $optionName
  939.                                && $optionHidden != "extension"{
  940.                             $index[$optionName][self::DIR_CURRENT== "Disabled";
  941.                             $index[$optionName][self::COMMENT_NORMAL"";
  942.                             $index[$optionName][self::DIR_NUMBER]     $no;
  943.                             //reset flag
  944.                             $delFlag = true;
  945.                         elseif (substr($line02== ";/" && $optionHi{
  946.                             if ($line != $current{
  947.                                 $current $line;
  948.                                 if (substr($line21== " "{
  949.                                     $comment .= substr($line3strlen($line)-3);
  950.                                 else {
  951.                                     $comment .= substr($line2strlen($line)-2);
  952.                                 }
  953.                             }
  954.                         }
  955.                         /* Performance enhancing trick */
  956.                         if ($delFlag{
  957.                             unset($options[$opNo]);
  958.                         }
  959.                     }
  960.                 }
  961.             }
  962.         }
  963.         $this->progress->destroy();
  964.         $this->extensions = $extensions;
  965.         return $index;
  966.     }
  967.  
  968.     //}}}
  969.     //{{{ showProgress()
  970.  
  971.     /**
  972.      * Creates and displays a progress bar that indicates
  973.      * by what amount a file has been parsed.
  974.      *
  975.      * @return void 
  976.      */
  977.     function showProgress()
  978.     {
  979.         while (Gtk::events_pending()) {
  980.                 Gtk::main_iteration();
  981.         }
  982.         $progressWin = new GtkWindow();
  983.         $progressWin->set_modal(true);
  984.         $progressWin->set_transient_for($this);
  985.         $progressWin->set_title("Parsing File...");
  986.         $progressBar = new GtkProgressBar();
  987.         $progressBar->set_orientation(Gtk::PROGRESS_LEFT_TO_RIGHT);
  988.         $progressWin->add($progressBar);
  989.         $this->progress = $progressWin;
  990.         $this->progress->set_size_request(30050);
  991.         $this->progress->set_position(Gtk::WIN_POS_CENTER);
  992.         $this->progress->show_all();
  993.  
  994.         return true;
  995.     }
  996.  
  997.     //}}}
  998.     //{{{ updateProgress()
  999.  
  1000.     /**
  1001.      * Updates the progress by the fraction received as an argument by
  1002.      * the function.
  1003.      *
  1004.      * @param int $fraction The fraction by which the progress bar must
  1005.      *                       be updated.
  1006.      *
  1007.      * @return true 
  1008.      */
  1009.     function updateProgress($fraction)
  1010.     {
  1011.         while (Gtk::events_pending()) {
  1012.                 Gtk::main_iteration();
  1013.         }
  1014.         $theBar $this->progress->get_child();
  1015.         $theBar->set_fraction($fraction);
  1016.         $percent round(($fraction*100))."%";
  1017.         $theBar->set_text($percent);
  1018.         return true;
  1019.     }
  1020.  
  1021.     //}}}
  1022.     //{{{ openFile()
  1023.  
  1024.     /**
  1025.      * Prompts for saving of file that is currently opened and opens a
  1026.      * dialog that prompts for the next file the user wishes to open.
  1027.      *
  1028.      * @return void 
  1029.      */
  1030.     function openFile()
  1031.     {
  1032.         if ($this->savePrompt()) {
  1033.             $filePrompt = new GtkFileChooserDialog("Open Existing file:"$this,
  1034.             Gtk::FILE_CHOOSER_ACTION_OPENarray(Gtk::STOCK_CANCEL,
  1035.                 Gtk::RESPONSE_CANCEL,
  1036.                 Gtk::STOCK_OPEN,
  1037.                 Gtk::RESPONSE_ACCEPT));
  1038.         }
  1039.  
  1040.         if ($filePrompt->run(== Gtk::RESPONSE_ACCEPT{
  1041.             $this->fileName    = $filePrompt->get_filename();
  1042.             $this->optionIndex = $this->getValues();
  1043.         else {
  1044.             if (is_object($filePrompt)) {
  1045.                 $filePrompt->destroy();
  1046.             }
  1047.         }
  1048.  
  1049.         $itemSelect $this->sectionTree->get_selection();
  1050.         $this->onSectionSelect($itemSelect);
  1051.         $this->setTitle();
  1052.     }
  1053.  
  1054.     //}}}
  1055.     //{{{ newFile()
  1056.  
  1057.     /**
  1058.      * Creates a new file to be edited after prompting for saving of the
  1059.      * existing file that is open.
  1060.      *
  1061.      * @return void 
  1062.      */
  1063.     function newFile()
  1064.     {
  1065.         $this->savePrompt();
  1066.         $this->fileName    = null;
  1067.         $this->optionIndex = $this->getValues();
  1068.         $this->saved       = false;
  1069.         $this->setTitle();
  1070.     }
  1071.  
  1072.     //}}}
  1073.     //{{{ savePrompt()
  1074.  
  1075.     /**
  1076.      * Checks whether the existing open file is saved or not. If not,
  1077.      * prompts the user to save it.
  1078.      *
  1079.      * @return  bool    Returns true if users wants to quit, false
  1080.      *                   otherwise.
  1081.      */
  1082.     function savePrompt()
  1083.     {
  1084.         if ($this->saved{
  1085.             return true;
  1086.         else {
  1087.             /* Display confirmation dialog since buffer is not saved */
  1088.             $saveDialog = new GtkMessageDialog($this,
  1089.                 1,
  1090.                 Gtk::MESSAGE_QUESTION,
  1091.                 Gtk::BUTTONS_NONE,
  1092.                 "Do you want to save your existing INI file?");
  1093.             $saveDialog->add_button(Gtk::STOCK_CANCELGtk::RESPONSE_CANCEL);
  1094.             $saveDialog->add_button(Gtk::STOCK_NOGtk::RESPONSE_NO);
  1095.             $saveDialog->add_button(Gtk::STOCK_YESGtk::RESPONSE_YES);
  1096.             $response $saveDialog->run();
  1097.             $saveDialog->destroy();
  1098.  
  1099.             if ($response == Gtk::RESPONSE_YES{
  1100.                 /* Save file */
  1101.                 $this->saveFile();
  1102.                 return true;
  1103.             elseif ($response == Gtk::RESPONSE_NO{
  1104.                 /* Don't save file */
  1105.                 return true;
  1106.             elseif ($response == Gtk::RESPONSE_CANCEL{
  1107.                 /* Don't quit */
  1108.                 return false;
  1109.             }
  1110.         }
  1111.     }
  1112.  
  1113.     //}}}
  1114.     //{{{ setTitle()
  1115.  
  1116.     /**
  1117.      * Sets the title of the window as required.
  1118.      *
  1119.      * @return    string    The title of the window.
  1120.      */
  1121.     function setTitle()
  1122.     {
  1123.         $asterisk "";
  1124.         if (!$this->saved{
  1125.             $asterisk "*";
  1126.         }
  1127.  
  1128.         if ($this->fileName==null{
  1129.             $title = self::TITLE." - New File (Default Values) ".$asterisk;
  1130.         else {
  1131.             $title = self::TITLE." - ".$this->fileName." ".$asterisk;
  1132.         }
  1133.  
  1134.         $this->set_title($title);
  1135.     }
  1136.  
  1137.     //}}}
  1138.     //{{{ quit()
  1139.  
  1140.     /**
  1141.      * Quits the main Gtk loop after checking whether the current state of
  1142.      * the buffer has been saved to a file or not.
  1143.      *
  1144.      * @return void 
  1145.      */
  1146.     function quit()
  1147.     {
  1148.         if ($this->savePrompt()) {
  1149.             Gtk::main_quit();
  1150.         }
  1151.         return true;
  1152.     }
  1153.  
  1154.     //}}}
  1155.  
  1156. }
  1157.  
  1158. /* END */
  1159.  
  1160. ?>

Documentation generated on Sun, 24 Oct 2010 11:30:03 +0000 by phpDocumentor 1.4.3. PEAR Logo Copyright © PHP Group 2004.