Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 76
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
tao_install_services_CheckPHPConfigService
0.00% covered (danger)
0.00%
0 / 76
0.00% covered (danger)
0.00%
0 / 5
1122
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 42
0.00% covered (danger)
0.00%
0 / 1
210
 sortReports
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 checkData
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
156
 getComponentById
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3/*
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; under version 2
7 * of the License (non-upgradable).
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 *
18 * Copyright (c) 2002-2008 (original work) Public Research Centre Henri Tudor & University of Luxembourg
19 *                         (under the project TAO & TAO2);
20 *               2008-2010 (update and modification) Deutsche Institut für Internationale Pädagogische Forschung
21 *                         (under the project TAO-TRANSFER);
22 *               2009-2012 (update and modification) Public Research Centre Henri Tudor
23 *                         (under the project TAO-SUSTAIN & TAO-DEV);
24 *
25 */
26
27
28/**
29 * A Service implementation aiming at checking a series of configurable things
30 * such as PHP Extensions, PHP INI Values, PHP Runtime, File system,...
31 *
32 * Please refer to tao/install/api.php for more information about how to call this service.
33 *
34 * @access public
35 * @author Jerome Bogaerts, <jerome@taotesting.com>
36 * @package tao
37
38 */
39class tao_install_services_CheckPHPConfigService extends tao_install_services_Service
40{
41    /**
42     * Creates a new instance of the service.
43     * @param tao_install_services_Data $data The input data to be handled by the service.
44     * @throws InvalidArgumentException If the input data structured is malformed or is missing data.
45     */
46    public function __construct(tao_install_services_Data $data)
47    {
48        parent::__construct($data);
49    }
50
51    /**
52     * Executes the main logic of the service.
53     * @return tao_install_services_Data The result of the service execution.
54     */
55    public function execute()
56    {
57        // contains an array of 'component', associated input 'data'
58        // and service 'class'.
59        $componentToData = [];
60
61        $content = json_decode($this->getData()->getContent(), true);
62        if (self::getRequestMethod() == 'get') {
63            // We extract the checks to perform from the manifests
64            // depending on the distribution.
65            $content['value'] = tao_install_utils_ChecksHelper::getRawChecks($content['extensions']);
66        }
67
68        // Deal with checks to be done.
69        $collection = new common_configuration_ComponentCollection();
70        foreach ($content['value'] as $config) {
71            $class = new ReflectionClass('tao_install_services_' . $config['type'] . 'Service');
72            $buildMethod = $class->getMethod('buildComponent');
73            $args = new tao_install_services_Data(json_encode($config));
74            $component = $buildMethod->invoke(null, $args);
75            $collection->addComponent($component);
76
77            if (!empty($config['value']['silent']) && is_bool($config['value']['silent'])) {
78                $collection->silent($component);
79            }
80
81            $componentToData[] = ['component' => $component,
82                                       'id' => $config['value']['id'],
83                                       'data' => $args,
84                                       'class' => $class];
85        }
86
87        // Deal with the dependencies.
88        foreach ($content['value'] as $config) {
89            if (!empty($config['value']['dependsOn']) && is_array($config['value']['dependsOn'])) {
90                foreach ($config['value']['dependsOn'] as $d) {
91                    // Find the component it depends on and tell the ComponentCollection.
92                    $dependent = self::getComponentById($componentToData, $config['value']['id']);
93                    $dependency = self::getComponentById($componentToData, $d);
94                    if (!empty($dependent) && !empty($dependency)) {
95                        $collection->addDependency($dependent, $dependency);
96                    }
97                }
98            }
99        }
100
101
102        // Deal with results to be sent to the client.
103        $resultValue = [];
104        $reports = $collection->check();
105        foreach ($reports as $r) {
106            $component = $r->getComponent();
107
108
109            // For the retrieved component, what was the associated data and class ?
110            $associatedData = null;
111            $class = null;
112            foreach ($componentToData as $ctd) {
113                if ($component == $ctd['component']) {
114                    $associatedData = $ctd['data'];
115                    $class = $ctd['class'];
116                }
117            }
118
119            $buildMethod = $class->getMethod('buildResult');
120            $serviceResult = $buildMethod->invoke(null, $associatedData, $r, $component);
121            $resultValue[] = $serviceResult->getContent();
122        }
123
124        // Sort by 'optional'.
125        usort($resultValue, ['tao_install_services_CheckPHPConfigService' , 'sortReports']);
126
127
128        $resultData = json_encode(['type' => 'ReportCollection',
129            'value' => '{RETURN_VALUE}']);
130
131        $resultData = str_replace('"{RETURN_VALUE}"', '[' . implode(',', $resultValue) . ']', $resultData);
132        $this->setResult(new tao_install_services_Data($resultData));
133    }
134
135    /**
136     * Report sorting function.
137     * @param string $a JSON encoded report.
138     * @param string $b JSON encoded report.
139     * @return boolean Comparison result.
140     */
141    private static function sortReports($a, $b)
142    {
143        $a = json_decode($a, true);
144        $b = json_decode($b, true);
145
146        if ($a['value']['optional'] == $b['value']['optional']) {
147            return 0;
148        } else {
149            return ($a['value']['optional'] < $b['value']['optional']) ? -1 : 1;
150        }
151    }
152
153    protected function checkData()
154    {
155        $content = json_decode($this->getData()->getContent(), true);
156        if (!isset($content['type']) || empty($content['type'])) {
157            throw new InvalidArgumentException("Missing data: 'type' must be provided.");
158        } elseif ($content['type'] !== 'CheckPHPConfig') {
159            throw new InvalidArgumentException("Unexpected type: 'type' must be equal to 'CheckPHPConfig'.");
160        }
161
162
163        if (self::getRequestMethod() !== 'get') {
164            if (!isset($content['value']) || empty($content['value']) || count($content['value']) == 0) {
165                throw new InvalidArgumentException("Missing data: 'value' must be provided as a not empty array.");
166            } else {
167                $acceptedTypes = [
168                    'CheckPHPExtension',
169                    'CheckPHPINIValue',
170                    'CheckPHPRuntime',
171                    'CheckPHPDatabaseDriver',
172                    'CheckFileSystemComponent',
173                    'CheckCustom'
174                ];
175
176                foreach ($content['value'] as $config) {
177                    if (
178                        !isset($config['type'])
179                        || empty($config['type'])
180                        || !in_array($config['type'], $acceptedTypes)
181                    ) {
182                        throw new InvalidArgumentException("Missing data: configuration 'type' must provided.");
183                    } else {
184                        $className = 'tao_install_services_' . $config['type'] . 'Service';
185                        $data = new tao_install_services_Data(json_encode($config));
186                        call_user_func($className . '::checkData', $data);
187                    }
188                }
189            }
190        }
191    }
192
193    /**
194     * Returns a component stored in an array of array. The searched key is 'id'. If matched,
195     * the component instance is returned. Otherwise null.
196     *
197     * @param array $componentToData
198     * @param string $id
199     * @return common_configuration_Component
200     */
201    public static function getComponentById(array $componentToData, $id)
202    {
203        foreach ($componentToData as $ctd) {
204            if ($ctd['id'] == $id) {
205                return $ctd['component'];
206            }
207        }
208
209        return null;
210    }
211}