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

Documentation generated on Mon, 11 Mar 2019 14:36:20 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.