Subversion Repositories Applications.gtt

Rev

Rev 94 | Details | Compare with Previous | Last modification | View Log | RSS feed

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