/** * Get the ComponentCollection corresponding to the distribution. It * the configuration checks to perform for all extensions involved in the * * @access public * @author Jerome Bogaerts, <*****@*****.**> * @param array $extensionIds * @return common_configuration_ComponentCollection */ public static function getConfigChecker($extensionIds) { $returnValue = new common_configuration_ComponentCollection(); $checkArray = array(); // resolve dependencies foreach (self::getRawChecks($extensionIds) as $c) { $checkArray[] = $c; $comp = common_configuration_ComponentFactory::buildFromArray($c); if (!empty($c['value']['id'])) { $componentArray[$c['value']['id']] = $comp; } $returnValue->addComponent($comp); if (!empty($c['value']['silent']) && $c['value']['silent'] == true) { $returnValue->silent($comp); } } // Deal with the dependencies. foreach ($checkArray as $config) { if (!empty($config['value']['dependsOn']) && is_array($config['value']['dependsOn'])) { foreach ($config['value']['dependsOn'] as $d) { // Find the component it depends on and tell the ComponentCollection. if (!empty($componentArray[$config['value']['id']]) && !empty($componentArray[$d])) { $returnValue->addDependency($componentArray[$config['value']['id']], $componentArray[$d]); } } } } return $returnValue; }
/** * Executes the main logic of the service. * @return tao_install_services_Data The result of the service execution. */ public function execute() { // contains an array of 'component', associated input 'data' // and service 'class'. $componentToData = array(); $content = json_decode($this->getData()->getContent(), true); if (self::getRequestMethod() == 'get') { // We extract the checks to perform from the manifests // depending on the distribution. $content['value'] = tao_install_utils_ChecksHelper::getRawChecks($content['extensions']); } // Deal with checks to be done. $collection = new common_configuration_ComponentCollection(); foreach ($content['value'] as $config) { $class = new ReflectionClass('tao_install_services_' . $config['type'] . 'Service'); $buildMethod = $class->getMethod('buildComponent'); $args = new tao_install_services_Data(json_encode($config)); $component = $buildMethod->invoke(null, $args); $collection->addComponent($component); if (!empty($config['value']['silent']) && is_bool($config['value']['silent'])) { $collection->silent($component); } $componentToData[] = array('component' => $component, 'id' => $config['value']['id'], 'data' => $args, 'class' => $class); } // Deal with the dependencies. foreach ($content['value'] as $config) { if (!empty($config['value']['dependsOn']) && is_array($config['value']['dependsOn'])) { foreach ($config['value']['dependsOn'] as $d) { // Find the component it depends on and tell the ComponentCollection. $dependent = self::getComponentById($componentToData, $config['value']['id']); $dependency = self::getComponentById($componentToData, $d); if (!empty($dependent) && !empty($dependency)) { $collection->addDependency($dependent, $dependency); } } } } // Deal with results to be sent to the client. $resultValue = array(); $reports = $collection->check(); foreach ($reports as $r) { $component = $r->getComponent(); // For the retrieved component, what was the associated data and class ? $associatedData = null; $class = null; foreach ($componentToData as $ctd) { if ($component == $ctd['component']) { $associatedData = $ctd['data']; $class = $ctd['class']; } } $buildMethod = $class->getMethod('buildResult'); $serviceResult = $buildMethod->invoke(null, $associatedData, $r, $component); $resultValue[] = $serviceResult->getContent(); } // Sort by 'optional'. usort($resultValue, array('tao_install_services_CheckPHPConfigService', 'sortReports')); $resultData = json_encode(array('type' => 'ReportCollection', 'value' => '{RETURN_VALUE}')); $resultData = str_replace('"{RETURN_VALUE}"', '[' . implode(',', $resultValue) . ']', $resultData); $this->setResult(new tao_install_services_Data($resultData)); }
public function testSimpleComponentCollection() { // Non acyclic simple test. $collection = new common_configuration_ComponentCollection(); $componentA = new common_configuration_Mock(common_configuration_Report::VALID, 'componentA'); $componentB = new common_configuration_Mock(common_configuration_Report::VALID, 'componentB'); $componentC = new common_configuration_Mock(common_configuration_Report::VALID, 'componentC'); $collection->addComponent($componentA); $collection->addComponent($componentB); $collection->addComponent($componentC); $collection->addDependency($componentC, $componentA); $collection->addDependency($componentB, $componentA); try { $reports = $collection->check(); $this->assertTrue(true); // The graph is acyclic. Perfect! $this->assertEquals(count($collection->getCheckedComponents()), 3); $this->assertEquals(count($collection->getUncheckedComponents()), 0); $this->assertEquals(count($reports), 3); // Make 'componentB' silent. $collection->silent($componentB); $reports = $collection->check(); $this->assertEquals(count($reports), 2); $this->assertEquals(count($collection->getCheckedComponents()), 3); // Make 'componentB' noisy again. $collection->noisy($componentB); $reports = $collection->check(); $this->assertEquals(count($reports), 3); // Now change some reports validity. $componentA->setExpectedStatus(common_configuration_Report::INVALID); $reports = $collection->check(); $this->assertTrue(true); // Acyclic graph, no CyclicDependencyException thrown. $this->assertEquals(count($reports), 1); $this->assertEquals($collection->getCheckedComponents(), array($componentA)); $this->assertEquals($collection->getUncheckedComponents(), array($componentB, $componentC)); // Add an additional independant component. $componentD = new common_configuration_Mock(common_configuration_Report::VALID, 'componentD'); $collection->addComponent($componentD); $reports = $collection->check(); $this->assertTrue(true); // Acyclic graph, no CyclicDependencyException thrown. $this->assertEquals(count($reports), 2); $this->assertEquals($collection->getCheckedComponents(), array($componentA, $componentD)); $this->assertEquals($collection->getUncheckedComponents(), array($componentB, $componentC)); // Make the whole components valid again. $componentA->setExpectedStatus(common_configuration_Report::VALID); $reports = $collection->check(); $this->assertTrue(true); // Acyclic graph, no CyclicDependencyException thrown. $this->assertEquals(count($reports), 4); $this->assertEquals($collection->getCheckedComponents(), array($componentA, $componentB, $componentC, $componentD)); $this->assertEquals($collection->getUncheckedComponents(), array()); try { // Make the graph cyclic. $collection->addDependency($componentA, $componentB); $collection->check(); $this->assertTrue(false, 'The graph should be cyclic.'); } catch (common_configuration_CyclicDependencyException $e) { $this->assertTrue(true); $this->assertEquals($collection->getReports(), array()); $this->assertEquals($collection->getCheckedComponents(), array()); $this->assertEquals($collection->getUncheckedComponents(), array($componentA, $componentB, $componentC, $componentD)); // Finally, we test a ComponentCollection reset. $collection->reset(); $this->assertEquals($collection->getReports(), array()); $this->assertEquals($collection->getCheckedComponents(), array()); $this->assertEquals($collection->getUncheckedComponents(), array()); $reports = $collection->check(); $this->assertEquals($reports, array()); $this->assertEquals($collection->getReports(), array()); $this->assertEquals($collection->getCheckedComponents(), array()); $this->assertEquals($collection->getUncheckedComponents(), array()); } } catch (common_configuration_CyclicDependencyException $e) { $this->assertTrue(false, 'The graph dependency formed by the ComponentCollection must be acyclic.'); } }