]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/Irc/extlib/phergie/Phergie/Plugin/Php/Source/Local.php
Merge branch '0.9.x' into 1.0.x
[quix0rs-gnu-social.git] / plugins / Irc / extlib / phergie / Phergie / Plugin / Php / Source / Local.php
1 <?php
2 /**
3  * Phergie 
4  *
5  * PHP version 5
6  *
7  * LICENSE
8  *
9  * This source file is subject to the new BSD license that is bundled
10  * with this package in the file LICENSE.
11  * It is also available through the world-wide-web at this URL:
12  * http://phergie.org/license
13  *
14  * @category  Phergie 
15  * @package   Phergie_Plugin_Php
16  * @author    Phergie Development Team <team@phergie.org>
17  * @copyright 2008-2010 Phergie Development Team (http://phergie.org)
18  * @license   http://phergie.org/license New BSD License
19  * @link      http://pear.phergie.org/package/Phergie_Plugin_Php
20  */
21
22 /**
23  * Data source for {@see Phergie_Plugin_Php}. This source reads function 
24  * descriptions from a file and stores them in a SQLite database. When a 
25  * function description is requested, the function is retrieved from the 
26  * local database.
27  *
28  * @category Phergie 
29  * @package  Phergie_Plugin_Php
30  * @author   Phergie Development Team <team@phergie.org>
31  * @license  http://phergie.org/license New BSD License
32  * @link     http://pear.phergie.org/package/Phergie_Plugin_Php
33  * @uses     extension pdo 
34  * @uses     extension pdo_sqlite 
35  * @uses     Phergie_Plugin_Command pear.phergie.org
36  */
37 class Phergie_Plugin_Php_Source_Local implements Phergie_Plugin_Php_Source
38 {
39     /**
40      * Local database for storage
41      *
42      * @var PDO 
43      */
44     protected $database;
45
46     /**
47      * Source of the PHP function summary
48      *
49      * @var string
50      */
51     protected $url = 'http://cvs.php.net/viewvc.cgi/phpdoc/funcsummary.txt?revision=HEAD';
52
53     /**
54      * Constructor to initialize the data source.
55      *
56      * @return void
57      */
58     public function __construct()
59     {
60         $path = dirname(__FILE__);
61
62         try {
63             $this->database = new PDO('sqlite:' . $path . '/functions.db');
64             $this->buildDatabase();
65             // @todo Modify this to be rethrown as an appropriate 
66             //       Phergie_Plugin_Exception and handled in Phergie_Plugin_Php
67         } catch (PDOException $e) {
68             echo 'PDO failure: '.$e->getMessage();
69         } 
70     }
71
72     /**
73      * Searches for a description of the function.
74      * 
75      * @param string $function Search pattern to match against the function 
76      *        name, wildcards supported using %
77      *
78      * @return array|null Associative array containing the function name and 
79      *         description or NULL if no results are found
80      */
81     public function findFunction($function)
82     {
83         // Remove possible parentheses
84         $split = preg_split('{\(|\)}', $function);
85         $function = (count($split)) ? array_shift($split) : $function;
86
87         // Prepare the database statement
88         $stmt = $this->database->prepare('SELECT `name`, `description` FROM `functions` WHERE `name` LIKE :function');
89         $stmt->execute(array(':function' => $function));
90
91         // Check the results
92         if (count($stmt) > 0) {
93             $result = $stmt->fetch(PDO::FETCH_ASSOC);
94             /**
95              * @todo add class and function URLS
96              * class methods: http://php.net/manual/en/classname.methodname.php
97              * functions: http://php.net/manual/en/function.functionname.php
98              * where '_' is replaced with '-'
99              */
100             return $result;
101         }
102
103         // No results found, return
104         return null;
105     }
106
107     /**
108      * Build the database and parses the function summary file into it.
109      *
110      * @param bool $rebuild TRUE to force a rebuild of the table used to 
111      *        house function information, FALSE otherwise, defaults to FALSE
112      *
113      * @return void
114      */
115     protected function buildDatabase($rebuild = false)
116     {
117         // Check to see if the functions table exists
118         $checkstmt = $this->database->query("SELECT COUNT(*) FROM `sqlite_master` WHERE `name` = 'functions'");
119         $checkstmt->execute();
120         $result = $checkstmt->fetch(PDO::FETCH_ASSOC);
121         unset( $checkstmt );
122         $table = $result['COUNT(*)'];
123         unset( $result );
124         // If the table doesn't exist, create it
125         if (!$table) {
126                 $this->database->exec('CREATE TABLE `functions` (`name` VARCHAR(255), `description` TEXT)');
127                 $this->database->exec('CREATE UNIQUE INDEX `functions_name` ON `functions` (`name`)');
128         }
129
130         // If we created a new table, fill it with data
131         if (!$table || $rebuild) {
132             // Get the contents of the source file
133             // @todo Handle possible error cases better here; the @ operator 
134             //       shouldn't be needed
135             $contents = @file($this->url, FILE_IGNORE_NEW_LINES + FILE_SKIP_EMPTY_LINES);
136
137             if (!$contents) {
138                 return;
139             }
140
141             // Parse the contents
142             $valid = array();
143             $firstPart = '';
144             $lineNumber = 0;
145             foreach ($contents as $line) {
146                 // Clean the current line
147                 $line = trim($line);
148
149                 // Skip comment lines
150                 if (0 === strpos($line, '#')) {
151                     // reset the line if the current line is odd
152                     if (($lineNumber % 2) !== 0) {
153                         $lineNumber--;
154                     }
155                     continue;
156                 }
157
158                 /*
159                  * If the current line is even, it's the first part of the
160                  * complete function description ...
161                  */
162                 if (($lineNumber % 2) === 0) {
163                     $firstPart = $line;
164                 } else {
165                     // ... it's the last part of the complete function description
166                     $completeLine = $firstPart . ' ' . $line;
167                     $firstPart = '';
168                     if (preg_match('{^([^\s]*)[\s]?([^)]*)\(([^\)]*)\)[\sU]+([\sa-zA-Z0-9\.,\-_()]*)$}', $completeLine, $matches)) {
169                         $valid[] = $matches;
170                     }
171                 }
172                 // Up the line number before going to the next line
173                 $lineNumber++;
174             }
175             // free up some memory
176             unset($contents);
177
178             // Process the valid matches
179             if (count($valid) > 0) {
180                 // Clear the database
181                 $this->database->exec('DELETE * FROM `functions`');
182
183                 // Prepare the sql statement
184                 $stmt = $this->database->prepare('INSERT INTO `functions` (`name`, `description`) VALUES (:name, :description)');
185                 $this->database->beginTransaction();
186
187                 // Insert the data
188                 foreach ($valid as $function) {
189                     // Extract function values
190                     list( , $retval, $name, $params, $desc) = $function;
191                     if (empty($name)) {
192                         $name = $retval;
193                         $retval = '';
194                     }
195                     // Reconstruct the complete function line
196                     $line = trim($retval . ' ' . $name . '(' . $params . ') - ' . $desc);
197                     // Execute the statement
198                     $stmt->execute(array(':name' => $name, ':description' => $line));
199                 }
200                 
201                 // Commit the changes to the database
202                 $this->database->commit();
203             }
204             // free up some more memory
205             unset($valid);
206         }
207     }
208 }