Initial repo created
[timetracker.git] / WEB-INF / lib / pear / PEAR / Task / Postinstallscript.php
1 <?php
2 /**
3  * <tasks:postinstallscript>
4  *
5  * PHP versions 4 and 5
6  *
7  * @category   pear
8  * @package    PEAR
9  * @author     Greg Beaver <cellog@php.net>
10  * @copyright  1997-2009 The Authors
11  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
12  * @version    CVS: $Id: Postinstallscript.php 313023 2011-07-06 19:17:11Z dufuz $
13  * @link       http://pear.php.net/package/PEAR
14  * @since      File available since Release 1.4.0a1
15  */
16 /**
17  * Base class
18  */
19 require_once 'PEAR/Task/Common.php';
20 /**
21  * Implements the postinstallscript file task.
22  *
23  * Note that post-install scripts are handled separately from installation, by the
24  * "pear run-scripts" command
25  * @category   pear
26  * @package    PEAR
27  * @author     Greg Beaver <cellog@php.net>
28  * @copyright  1997-2009 The Authors
29  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
30  * @version    Release: 1.9.4
31  * @link       http://pear.php.net/package/PEAR
32  * @since      Class available since Release 1.4.0a1
33  */
34 class PEAR_Task_Postinstallscript extends PEAR_Task_Common
35 {
36     var $type = 'script';
37     var $_class;
38     var $_params;
39     var $_obj;
40     /**
41      *
42      * @var PEAR_PackageFile_v2
43      */
44     var $_pkg;
45     var $_contents;
46     var $phase = PEAR_TASK_INSTALL;
47
48     /**
49      * Validate the raw xml at parsing-time.
50      *
51      * This also attempts to validate the script to make sure it meets the criteria
52      * for a post-install script
53      * @param PEAR_PackageFile_v2
54      * @param array The XML contents of the <postinstallscript> tag
55      * @param PEAR_Config
56      * @param array the entire parsed <file> tag
57      * @static
58      */
59     function validateXml($pkg, $xml, $config, $fileXml)
60     {
61         if ($fileXml['role'] != 'php') {
62             return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
63             $fileXml['name'] . '" must be role="php"');
64         }
65         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
66         $file = $pkg->getFileContents($fileXml['name']);
67         if (PEAR::isError($file)) {
68             PEAR::popErrorHandling();
69             return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
70                 $fileXml['name'] . '" is not valid: ' .
71                 $file->getMessage());
72         } elseif ($file === null) {
73             return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
74                 $fileXml['name'] . '" could not be retrieved for processing!');
75         } else {
76             $analysis = $pkg->analyzeSourceCode($file, true);
77             if (!$analysis) {
78                 PEAR::popErrorHandling();
79                 $warnings = '';
80                 foreach ($pkg->getValidationWarnings() as $warn) {
81                     $warnings .= $warn['message'] . "\n";
82                 }
83                 return array(PEAR_TASK_ERROR_INVALID, 'Analysis of post-install script "' .
84                     $fileXml['name'] . '" failed: ' . $warnings);
85             }
86             if (count($analysis['declared_classes']) != 1) {
87                 PEAR::popErrorHandling();
88                 return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
89                     $fileXml['name'] . '" must declare exactly 1 class');
90             }
91             $class = $analysis['declared_classes'][0];
92             if ($class != str_replace(array('/', '.php'), array('_', ''),
93                   $fileXml['name']) . '_postinstall') {
94                 PEAR::popErrorHandling();
95                 return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
96                     $fileXml['name'] . '" class "' . $class . '" must be named "' .
97                     str_replace(array('/', '.php'), array('_', ''),
98                     $fileXml['name']) . '_postinstall"');
99             }
100             if (!isset($analysis['declared_methods'][$class])) {
101                 PEAR::popErrorHandling();
102                 return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
103                     $fileXml['name'] . '" must declare methods init() and run()');
104             }
105             $methods = array('init' => 0, 'run' => 1);
106             foreach ($analysis['declared_methods'][$class] as $method) {
107                 if (isset($methods[$method])) {
108                     unset($methods[$method]);
109                 }
110             }
111             if (count($methods)) {
112                 PEAR::popErrorHandling();
113                 return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
114                     $fileXml['name'] . '" must declare methods init() and run()');
115             }
116         }
117         PEAR::popErrorHandling();
118         $definedparams = array();
119         $tasksNamespace = $pkg->getTasksNs() . ':';
120         if (!isset($xml[$tasksNamespace . 'paramgroup']) && isset($xml['paramgroup'])) {
121             // in order to support the older betas, which did not expect internal tags
122             // to also use the namespace
123             $tasksNamespace = '';
124         }
125         if (isset($xml[$tasksNamespace . 'paramgroup'])) {
126             $params = $xml[$tasksNamespace . 'paramgroup'];
127             if (!is_array($params) || !isset($params[0])) {
128                 $params = array($params);
129             }
130             foreach ($params as $param) {
131                 if (!isset($param[$tasksNamespace . 'id'])) {
132                     return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
133                         $fileXml['name'] . '" <paramgroup> must have ' .
134                         'an ' . $tasksNamespace . 'id> tag');
135                 }
136                 if (isset($param[$tasksNamespace . 'name'])) {
137                     if (!in_array($param[$tasksNamespace . 'name'], $definedparams)) {
138                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
139                             $fileXml['name'] . '" ' . $tasksNamespace .
140                             'paramgroup> id "' . $param[$tasksNamespace . 'id'] .
141                             '" parameter "' . $param[$tasksNamespace . 'name'] .
142                             '" has not been previously defined');
143                     }
144                     if (!isset($param[$tasksNamespace . 'conditiontype'])) {
145                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
146                             $fileXml['name'] . '" ' . $tasksNamespace .
147                             'paramgroup> id "' . $param[$tasksNamespace . 'id'] .
148                             '" must have a ' . $tasksNamespace .
149                             'conditiontype> tag containing either "=", ' .
150                             '"!=", or "preg_match"');
151                     }
152                     if (!in_array($param[$tasksNamespace . 'conditiontype'],
153                           array('=', '!=', 'preg_match'))) {
154                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
155                             $fileXml['name'] . '" ' . $tasksNamespace .
156                             'paramgroup> id "' . $param[$tasksNamespace . 'id'] .
157                             '" must have a ' . $tasksNamespace .
158                             'conditiontype> tag containing either "=", ' .
159                             '"!=", or "preg_match"');
160                     }
161                     if (!isset($param[$tasksNamespace . 'value'])) {
162                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
163                             $fileXml['name'] . '" ' . $tasksNamespace .
164                             'paramgroup> id "' . $param[$tasksNamespace . 'id'] .
165                             '" must have a ' . $tasksNamespace .
166                             'value> tag containing expected parameter value');
167                     }
168                 }
169                 if (isset($param[$tasksNamespace . 'instructions'])) {
170                     if (!is_string($param[$tasksNamespace . 'instructions'])) {
171                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
172                             $fileXml['name'] . '" ' . $tasksNamespace .
173                             'paramgroup> id "' . $param[$tasksNamespace . 'id'] .
174                             '" ' . $tasksNamespace . 'instructions> must be simple text');
175                     }
176                 }
177                 if (!isset($param[$tasksNamespace . 'param'])) {
178                     continue; // <param> is no longer required
179                 }
180                 $subparams = $param[$tasksNamespace . 'param'];
181                 if (!is_array($subparams) || !isset($subparams[0])) {
182                     $subparams = array($subparams);
183                 }
184                 foreach ($subparams as $subparam) {
185                     if (!isset($subparam[$tasksNamespace . 'name'])) {
186                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
187                             $fileXml['name'] . '" parameter for ' .
188                             $tasksNamespace . 'paramgroup> id "' .
189                             $param[$tasksNamespace . 'id'] . '" must have ' .
190                             'a ' . $tasksNamespace . 'name> tag');
191                     }
192                     if (!preg_match('/[a-zA-Z0-9]+/',
193                           $subparam[$tasksNamespace . 'name'])) {
194                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
195                             $fileXml['name'] . '" parameter "' .
196                             $subparam[$tasksNamespace . 'name'] .
197                             '" for ' . $tasksNamespace . 'paramgroup> id "' .
198                             $param[$tasksNamespace . 'id'] .
199                             '" is not a valid name.  Must contain only alphanumeric characters');
200                     }
201                     if (!isset($subparam[$tasksNamespace . 'prompt'])) {
202                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
203                             $fileXml['name'] . '" parameter "' .
204                             $subparam[$tasksNamespace . 'name'] .
205                             '" for ' . $tasksNamespace . 'paramgroup> id "' .
206                             $param[$tasksNamespace . 'id'] .
207                             '" must have a ' . $tasksNamespace . 'prompt> tag');
208                     }
209                     if (!isset($subparam[$tasksNamespace . 'type'])) {
210                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
211                             $fileXml['name'] . '" parameter "' .
212                             $subparam[$tasksNamespace . 'name'] .
213                             '" for ' . $tasksNamespace . 'paramgroup> id "' .
214                             $param[$tasksNamespace . 'id'] .
215                             '" must have a ' . $tasksNamespace . 'type> tag');
216                     }
217                     $definedparams[] = $param[$tasksNamespace . 'id'] . '::' .
218                     $subparam[$tasksNamespace . 'name'];
219                 }
220             }
221         }
222         return true;
223     }
224
225     /**
226      * Initialize a task instance with the parameters
227      * @param array raw, parsed xml
228      * @param array attributes from the <file> tag containing this task
229      * @param string|null last installed version of this package, if any (useful for upgrades)
230      */
231     function init($xml, $fileattribs, $lastversion)
232     {
233         $this->_class = str_replace('/', '_', $fileattribs['name']);
234         $this->_filename = $fileattribs['name'];
235         $this->_class = str_replace ('.php', '', $this->_class) . '_postinstall';
236         $this->_params = $xml;
237         $this->_lastversion = $lastversion;
238     }
239
240     /**
241      * Strip the tasks: namespace from internal params
242      *
243      * @access private
244      */
245     function _stripNamespace($params = null)
246     {
247         if ($params === null) {
248             $params = array();
249             if (!is_array($this->_params)) {
250                 return;
251             }
252             foreach ($this->_params as $i => $param) {
253                 if (is_array($param)) {
254                     $param = $this->_stripNamespace($param);
255                 }
256                 $params[str_replace($this->_pkg->getTasksNs() . ':', '', $i)] = $param;
257             }
258             $this->_params = $params;
259         } else {
260             $newparams = array();
261             foreach ($params as $i => $param) {
262                 if (is_array($param)) {
263                     $param = $this->_stripNamespace($param);
264                 }
265                 $newparams[str_replace($this->_pkg->getTasksNs() . ':', '', $i)] = $param;
266             }
267             return $newparams;
268         }
269     }
270
271     /**
272      * Unlike other tasks, the installed file name is passed in instead of the file contents,
273      * because this task is handled post-installation
274      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
275      * @param string file name
276      * @return bool|PEAR_Error false to skip this file, PEAR_Error to fail
277      *         (use $this->throwError)
278      */
279     function startSession($pkg, $contents)
280     {
281         if ($this->installphase != PEAR_TASK_INSTALL) {
282             return false;
283         }
284         // remove the tasks: namespace if present
285         $this->_pkg = $pkg;
286         $this->_stripNamespace();
287         $this->logger->log(0, 'Including external post-installation script "' .
288             $contents . '" - any errors are in this script');
289         include_once $contents;
290         if (class_exists($this->_class)) {
291             $this->logger->log(0, 'Inclusion succeeded');
292         } else {
293             return $this->throwError('init of post-install script class "' . $this->_class
294                 . '" failed');
295         }
296         $this->_obj = new $this->_class;
297         $this->logger->log(1, 'running post-install script "' . $this->_class . '->init()"');
298         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
299         $res = $this->_obj->init($this->config, $pkg, $this->_lastversion);
300         PEAR::popErrorHandling();
301         if ($res) {
302             $this->logger->log(0, 'init succeeded');
303         } else {
304             return $this->throwError('init of post-install script "' . $this->_class .
305                 '->init()" failed');
306         }
307         $this->_contents = $contents;
308         return true;
309     }
310
311     /**
312      * No longer used
313      * @see PEAR_PackageFile_v2::runPostinstallScripts()
314      * @param array an array of tasks
315      * @param string install or upgrade
316      * @access protected
317      * @static
318      */
319     function run()
320     {
321     }
322 }
323 ?>