Changeset 2297 for branches

Show
Ignore:
Timestamp:
12/13/10 22:18:56 (17 months ago)
Author:
petsagouris
Message:

[Branch 1.5] Merged the metadata class into a single function. This needs to find its place.
Maybe make a big abstract class for all these utility functions... or just find a semantically proper place to put them.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • branches/1.5/libs/extensions/GenericPHPConfig/class.metadata.php

    r2153 r2297  
    2929 * 
    3030 */ 
    31 class generic_pmd { 
    32  
    33         /** 
    34          * plugin meta data 
    35          * 
    36          */ 
    37         public $plugin = array();         // id->row hash, with individual info fields 
    38         public $config = array();         // extracted config variables 
    39  
    40         /** 
    41          * separated dependency fields 
    42          * hash id->(id,id,...) 
    43          * 
    44          */ 
    45         public $depends = array();       // enforced dependencies, +virtnames 
    46         public $replaces = array();     // negative dependencies, +virtnames 
    47         public $suggests = array();     // relaxed dep 
    48         public $conflicts = array();   // similar to $replaces, but keeps current plugin off if other enabled 
    49  
    50         /** 
    51          * Virtual plugin names are used by depends: and replaces: 
    52          * @var array 
    53          */ 
    54         public $provides = array();     // hash alias->(id,id,id,) list 
    55  
    56         /** 
    57          * constructor stub 
    58          */ 
    59         public function __construct() 
    60         { 
    61         } 
     31class generic_pmd 
     32{ 
    6233 
    6334        /** 
    6435         * Get metainformation data from a single <em>.php</em> plugin. 
    6536         * We only read first 4KiB of file 
    66          * 
    67          */ 
    68         public function read($fn, $size=4096) 
    69         { 
    70  
    71                 // read from given filename 
    72                 if (file_exists($fn) and ($f = fopen($fn, "r"))) { 
    73                         $src = fread($f, $size); 
    74                         fclose($f); 
    75                         $src .= "\n*/?>";   // add this, else parsing for /*..*/ might fail, because file possible shortened to 4096 byte 
    76                         return $this->parse($src); 
    77                 } else { 
    78                         // file not found/readable 
    79                         $this->error("The file '".$fn."' couldn't be found in your plugins folder."); 
    80                 } 
    81         } 
    82  
    83         /** 
    84          * Parses out meta informations from a .php script 
    85          * - does not add [fn] filename itself 
    86          * - does not parse [config] itself 
    87          * the data ends up in $this->plugin[] sorted by $id 
    8837         * 
    8938         * Individual entries typically contain: 
     
    11362         * @param string $src The source 
    11463         */ 
    115         private function parse($src) 
     64        public function read($fn, $size = 4096) 
    11665        { 
     66 
     67                // read from given filename 
     68                if (!file_exists($fn)) { 
     69                        trigger_error('Could not find file \''.$fn.'\'!', E_USER_NOTICE); 
     70                } 
     71                if (!$src = file_get_contents($fn, NULL, NULL, NULL, $size)) { 
     72                        trigger_error('Could not read file \''.$fn.'\'!', E_USER_NOTICE); 
     73                } 
     74 
     75                $src .= "\n*/?>";   // add this, else parsing for /*..*/ might fail, because file possible shortened to 4096 byte 
     76 
    11777                $info = array(); 
    11878 
    119                 // first comment block 
    120                 $src = $this->extract_first_comment($src); 
     79                // clean out first line 
     80                $tmp_src = preg_replace("/^<\?(php)?[^\n]*/i", "", $src); 
     81 
     82                // extract /* ... */ comment block or lines of #... #... and //... //... 
     83                if (preg_match("_^\s*/\*+(.+?)\*+/_s", $tmp_src, $uu) || (preg_match("_^\s*((^\s*(#+|//+)\s*.+?$\n)+)_ms", $tmp_src, $uu))) { 
     84                        $tmp_src = $uu[1]; 
     85                } else { 
     86                        $tmp_src = NULL; 
     87                } 
     88 
     89                // cut comment/whitespace prefixes like _*__ or  __#_ or _//__ from 
     90                // lines - with same length from everyone! - don't care about actual 
     91                // pattern, but allow shortened lines (missing spaces after # or *) 
     92                preg_match("_^([*#/ ]+)\w+( \w+)?:_m", $tmp_src, $uu); 
     93                if ($uu) { 
     94                        $src = preg_replace("_^[*#/ ]{0,".strlen($uu[1])."}_m", "", $tmp_src); 
     95                } else { 
     96                        $src = false; 
     97                } 
    12198 
    12299                // find empty line and split cfg:block from help text part 
    123100                if (preg_match("/^(.+?)\n[ \t]*\n(.+)$/s", $src, $uu)) { 
    124101                        $src = $uu[1]; 
    125  
    126102                        // add second part as help text 
    127103                        $info["help"] = trim($uu[2]); 
     
    144120                // ok - folder used for plugins, name used for themes 
    145121                if (isset($info["folder"]) || isset($info["name"])) { 
    146                         return($info); 
     122                        return $info; 
    147123                } 
    148124        } 
    149125 
    150         /** 
    151          * Gets first block of asterisk /* comment or # hash or // slash comment, 
    152          * removes leading whitespace and comment characters 
    153          * 
    154          * @param string $src The source 
    155          */ 
    156         private function extract_first_comment($src) 
    157         { 
    158  
    159                 // clean out first line 
    160                 $src = preg_replace("/^<\?(php)?[^\n]*/i", "", $src); 
    161  
    162                 // extract /* ... */ comment block or lines of #... #... and //... //... 
    163                 if (preg_match("_^\s*/\*+(.+?)\*+/_s", $src, $uu) || (preg_match("_^\s*((^\s*(#+|//+)\s*.+?$\n)+)_ms", $src, $uu))) { 
    164                         $src = $uu[1]; 
    165                 } else { 
    166                         return; 
    167                 } 
    168  
    169                 // cut comment/whitespace prefixes like _*__ or  __#_ or _//__ from 
    170                 // lines - with same length from everyone! - don't care about actual 
    171                 // pattern, but allow shortened lines (missing spaces after # or *) 
    172                 preg_match("_^([*#/ ]+)\w+( \w+)?:_m", $src, $uu); 
    173                 if ($uu) { 
    174                         $n = strlen($uu[1]); 
    175                         $src = preg_replace("_^[*#/ ]{0,$n}_m", "", $src); 
    176                         return($src); 
    177                 } 
    178  
    179                 return false; 
    180         } 
    181  
    182         /** 
    183          * Reads in <em>.php</em> plugin meta data from given directory and up-to three subdirectories. 
    184          * The data gets stored into <em>$this->$plugin</em> for later use, augmented 
    185          * by every plugins filename relative to the supplied basedir. 
    186          * 
    187          * @param string $basedir the folder in which to look into 
    188          * @return array 
    189          */ 
    190         public function scan($basedir) 
    191         { 
    192  
    193                 // reading in 
    194                 $basedir = realpath($basedir); 
    195  
    196                 // each file 
    197                 foreach ($this->scan_subdirs($basedir) as $num => $fn) { 
    198  
    199                         // basename == id 
    200                         $id = basename($fn, ".php"); 
    201  
    202                         // parse 
    203                         if ($e = $this->read($fn)) { 
    204  
    205                                 // has plugin custom set id: ?  (should not happen, but who knows if this might be useful?) 
    206                                 if (!empty($e["id"])) { 
    207                                         $id = $e["id"]; 
    208                                 } else { 
    209                                         $e["id"] = $id; 
    210                                 } 
    211  
    212                                 // WordPress plugin scheme compatibility 
    213                                 if ($e["plugin name"]) { 
    214                                         // allows to read in WordPress plugin comment too, 
    215                                         // http://codex.wordpress.org/Writing_a_Plugin 
    216                                         $wp_compat = array("plugin name" => "title", "description" => "description", "plugin uri" => "url", "author uri" => "author_url"); 
    217                                         foreach ($this->wp_compat as $from => $to) 
    218                                                 if (!isset($e[$to])) { 
    219                                                         $e[$to] = $e[$from]; 
    220                                                         unset($e[$from]); 
    221                                                 } 
    222                                         $e["api"] = "wordpress"; 
    223                                 } 
    224  
    225                                 // add localized filename 
    226                                 $fn = substr($fn, strlen($basedir) + 1); 
    227                                 $e["fn"] = $fn; 
    228  
    229                                 // append to list 
    230                                 if (isset($this->plugin[$id])) { 
    231                                         $this->error("a plugin with the name '$id' is already registered (second_fn=$fn, registered={$this->plugin[$id][fn]})\n"); 
    232                                 } else { 
    233                                         $this->plugin[$id] = $e; 
    234                                 } 
    235                         } 
    236                 } 
    237  
    238                 // plugin dependencies 
    239                 $this->extract_lists(); 
    240  
    241                 // send it back even if probably unused 
    242                 return $this->plugin; 
    243         } 
    244  
    245         /** 
    246          * Separates dependency fields and config variables out of all plugin entries 
    247          */ 
    248         private function extract_lists() 
    249         { 
    250  
    251                 // extract list fields 
    252                 $fields = array("depends", "suggests", "replaces", "conflicts"); 
    253                 foreach ($this->plugin as $id => $e) { 
    254  
    255                         // provides: 
    256                         if ($e["provides"]) 
    257                                 foreach (explode(",", $e["provides"]) as $set) 
    258                                         if ($set = trim($set)) { 
    259                                                 $this->provides[$set][] = $id;  // only the first gets used 
    260                                         } 
    261  
    262                         // depends: 
    263                         foreach ($fields as $field) { 
    264                                 if (isset($e[$field])) { 
    265                                         foreach (explode(",", $e["depends"]) as $set) { 
    266                                                 if ($set = trim($set)) { 
    267                                                         $this->{$field}[$id][] = $set; 
    268                                                 } 
    269                                         } 
    270                                 } 
    271                         } 
    272  
    273                         // config: 
    274                         if ($e["config"]) { 
    275                                 // currently doesn't get unfold into plugin $e entry, 
    276                                 // but just into $this->config[] list 
    277                                 $cfg_txt = $e["config"]; 
    278                                 foreach ($this->parse_options($cfg_txt, $id) as $opt) { 
    279                                         $this->config[$opt["name"]] = $opt; 
    280                                 } 
    281                         } 
    282                 } 
    283         } 
    284  
    285         /** 
    286          * Look for <em>.php</em> files in subdirectories 
    287          * 
    288          * @param string $basedir the path in which to look 
    289          * @return array An array with the paths. 
    290          */ 
    291         private function scan_subdirs($basedir) 
    292         { 
    293                 $r = array(); 
    294                 if ($dh = opendir($basedir)) { 
    295                         while ($fn = readdir($dh)) { 
    296                                 if ($fn[0] != ".") { 
    297                                         if (is_dir("$basedir/$fn")) { 
    298                                                 foreach ($this->scan_subdirs("$basedir/$fn") as $fn) { 
    299                                                         $r[] = $fn; 
    300                                                 } 
    301                                         } elseif (strpos($fn, ".php")) { 
    302                                                 $r[] = "$basedir/$fn"; 
    303                                         } 
    304                                 } 
    305                         } 
    306                         closedir($dh); 
    307                 } 
    308                 return $r; 
    309         } 
    310  
    311         /** 
    312          * Extract <em>config:</em> options pseudo XML into array. 
    313          * 
    314          * <code> 
    315          * <var name="app[setting]" value="default_1" title=".." /> 
    316          *   -> 
    317          * array( 
    318          *   "is" => "var", 
    319          *   "plugin" => "config_option_was_found_in_this_php_plugin_script", 
    320          *   "name" => "app[setting]", 
    321          *   "value" => "default_1", 
    322          *   "title" => "name of first setting", 
    323          *   "description" => "should better be present", 
    324          *  # "multi" => array("val1" => "title1", "v2" => "t2", ...), 
    325          *  # "type" => "text", 
    326          *  # "..." => "depending on var type, could have other options", 
    327          * ) 
    328          * </code> 
    329          * 
    330          * @param string $str 
    331          * @param string $plugin 
    332          * @return array An array per config option / varname 
    333          */ 
    334         private function parse_options($str, $plugin) 
    335         { 
    336                 $r = array(); 
    337  
    338                 // search for < angle brackets > first 
    339                 preg_match_all("_<(\w+)(.+?)/\s*>_ims", $str, $uu); 
    340                 foreach ($uu[1] as $i => $optiontype) { 
    341                         $inner = $uu[2][$i]; 
    342  
    343                         // prepare new 
    344                         $entry = array( 
    345                                 "is" => $optiontype, 
    346                                 "plugin" => $plugin, 
    347                         ); 
    348  
    349                         // extract individual fields 
    350                         preg_match_all("_\s+([-\w:]+)=[\"\']([^\"\']*?)[\"\']_msi", $inner, $vv); 
    351                         foreach ($vv[1] as $j => $field) { 
    352                                 $entry[$field] = $vv[2][$j]; 
    353                         } 
    354  
    355                         // clean name= 
    356                         $entry["name"] = preg_replace("/[\$\"\'\s]/", "", $entry["name"]); 
    357  
    358                         // split up multi= value (our value= field holds the default entry instead) 
    359                         if (strpos($entry["multi"], "|")) { 
    360                                 $opt = array(); 
    361                                 foreach (explode("|", $entry["multi"]) as $o) { 
    362                                         if (strpos($o, "=")) { 
    363                                                 $opt[strtok($o, "=")] = strtok("\n"); 
    364                                         } else { 
    365                                                 $opt[$o] = $o; 
    366                                         } 
    367                                 } 
    368                                 $entry["multi"] = $opt; 
    369                         } 
    370  
    371                         // rename, just in case (actually default= is not recommended, and value= should be used) 
    372                         if (isset($row["default"]) && empty($row["value"])) { 
    373                                 $row["value"] = $row["default"]; 
    374                         } 
    375  
    376                         // add to list 
    377                         $r[] = $entry; 
    378                 } 
    379                 return($r); 
    380         } 
    381  
    382         /** 
    383          * Returns plugins grouped by entries. 
    384          * 
    385          * @param string $field value - or comparison value 
    386          * @param string $cmp 
    387          * @return array 
    388          */ 
    389         public function by($field, $cmp=NULL) 
    390         { 
    391                 $r = array(); 
    392                 foreach ($this->plugin as $id => $row) { 
    393                         if ((empty($cmp) && isset($row[$field])) || ($cmp == strtolower($row[$field]))) { 
    394                                 $r[$row[$field]][$id] = $row; 
    395                         } 
    396                 } 
    397                 return $r; 
    398         } 
    399  
    400         /** 
    401          * Complain 
    402          * @param string $s the error message 
    403          */ 
    404         private function error($s) 
    405         { 
    406                 trigger_error($s, E_USER_WARNING); 
    407                 $this->error = 1; 
    408         } 
    409  
    410126} 
    411 ?>