/** * @covers PersistableFilter */ public function testInstantiationAndExecute() { $constructorArg = PersistableFilter::tempGroup('class::lib.pkp.tests.classes.filter.TestClass1', 'class::lib.pkp.tests.classes.filter.TestClass2'); $testFilter = new PersistableFilter($constructorArg); // Test getters/setters that are not implicitly tested by other tests self::assertInstanceOf('FilterGroup', $testFilter->getFilterGroup()); $testFilter->setDisplayName('Some other display name'); $testFilter->setIsTemplate(1); self::assertTrue($testFilter->getIsTemplate()); self::assertEquals(0, $testFilter->getParentFilterId()); $testFilter->setParentFilterId(1); self::assertEquals(1, $testFilter->getParentFilterId()); // Test settings self::assertFalse($testFilter->hasSettings()); $testSetting = new EmailFilterSetting('testEmail', 'Test Email', 'Test Email is required'); $testSetting2 = new EmailFilterSetting('testEmail2', 'Test Email2', 'Test Email2 is required'); $testSetting2->setIsLocalized(true); $testFilter->addSetting($testSetting); $testFilter->addSetting($testSetting2); self::assertEquals(array('testEmail' => $testSetting, 'testEmail2' => $testSetting2), $testFilter->getSettings()); self::assertTrue($testFilter->hasSettings()); self::assertEquals(array('testEmail'), $testFilter->getSettingNames()); self::assertEquals(array('testEmail2'), $testFilter->getLocalizedSettingNames()); self::assertTrue($testFilter->hasSetting('testEmail')); self::assertEquals($testSetting, $testFilter->getSetting('testEmail')); // Test type validation. $typeDescriptionFactory = TypeDescriptionFactory::getInstance(); $inputTypeDescription = 'class::lib.pkp.tests.classes.filter.TestClass1'; $outputTypeDescription = 'class::lib.pkp.tests.classes.filter.TestClass2'; self::assertEquals($inputTypeDescription, $testFilter->getInputType()->getTypeDescription()); self::assertEquals($outputTypeDescription, $testFilter->getOutputType()->getTypeDescription()); }
/** * @covers Filter */ public function testInstantiationAndExecute() { $mockFilter = $this->getFilterMock(); // Test getters/setters that are not implicitly tested by other tests self::assertEquals('Mock_Filter_', substr($mockFilter->getDisplayName(), 0, 12)); $mockFilter->setDisplayName('Some other display name'); self::assertEquals('Some other display name', $mockFilter->getDisplayName()); $mockFilter->setSequence(5); self::assertEquals(5, $mockFilter->getSequence()); // Test errors $mockFilter->addError('some error message'); $mockFilter->addError('a second error message'); $expectedErrors = array('some error message', 'a second error message'); self::assertEquals($expectedErrors, $mockFilter->getErrors()); self::assertTrue($mockFilter->hasErrors()); $mockFilter->clearErrors(); self::assertEquals(array(), $mockFilter->getErrors()); // Test type validation. $typeDescriptionFactory = TypeDescriptionFactory::getInstance(); $inputTypeDescription = 'class::lib.pkp.tests.classes.filter.TestClass1'; $outputTypeDescription = 'class::lib.pkp.tests.classes.filter.TestClass2'; self::assertEquals($inputTypeDescription, $mockFilter->getInputType()->getTypeDescription()); self::assertEquals($outputTypeDescription, $mockFilter->getOutputType()->getTypeDescription()); // Test execution without runtime requirements $testInput = new TestClass1(); $testInput->testField = 'some filter input'; self::assertInstanceOf('TestClass2', $testOutput = $mockFilter->execute($testInput)); self::assertEquals($this->getTestOutput(), $testOutput); self::assertEquals($testInput, $mockFilter->getLastInput()); self::assertEquals($this->getTestOutput(), $mockFilter->getLastOutput()); // Test execution without runtime requirements // (We can safely use PHP 5.0.0 as a test here // because this is a PHPUnit requirement anyway.) $mockFilter = $this->getFilterMock(); $mockFilter->setData('phpVersionMin', '5.0.0'); $testOutput = $mockFilter->execute($testInput); $runtimeEnvironment = $mockFilter->getRuntimeEnvironment(); self::assertEquals('5.0.0', $runtimeEnvironment->getPhpVersionMin()); // Do the same again but this time set the runtime // environment via a RuntimeEnvironment object. $mockFilter = $this->getFilterMock(); $mockFilter->setRuntimeEnvironment($runtimeEnvironment); $testOutput = $mockFilter->execute($testInput); $runtimeEnvironment = $mockFilter->getRuntimeEnvironment(); self::assertEquals('5.0.0', $runtimeEnvironment->getPhpVersionMin()); self::assertEquals('5.0.0', $mockFilter->getData('phpVersionMin')); // Test unsupported input $unsupportedInput = new TestClass2(); self::assertNull($mockFilter->execute($unsupportedInput)); self::assertNull($mockFilter->getLastInput()); self::assertNull($mockFilter->getLastOutput()); // Test unsupported output $mockFilter = $this->getFilterMock('class::lib.pkp.tests.classes.filter.TestClass1'); self::assertNull($mockFilter->execute($testInput)); self::assertEquals($testInput, $mockFilter->getLastInput()); self::assertNull($mockFilter->getLastOutput()); }
/** * @covers TypeDescriptionFactory */ public function testInstantiateTypeDescription() { $typeDescriptionFactory = TypeDescriptionFactory::getInstance(); // Instantiate a primitive type $typeDescription = $typeDescriptionFactory->instantiateTypeDescription('primitive::string'); self::assertInstanceOf('PrimitiveTypeDescription', $typeDescription); self::assertTrue($typeDescription->isCompatible($object = 'some string')); self::assertFalse($typeDescription->isCompatible($object = 5)); // Instantiate a class type $typeDescription = $typeDescriptionFactory->instantiateTypeDescription('class::lib.pkp.tests.classes.filter.TestClass1'); self::assertInstanceOf('ClassTypeDescription', $typeDescription); $compatibleObject = new TestClass1(); $wrongObject = new TestClass2(); self::assertTrue($typeDescription->isCompatible($compatibleObject)); self::assertFalse($typeDescription->isCompatible($wrongObject)); // Test invalid descriptions self::assertNull($typeDescriptionFactory->instantiateTypeDescription('string')); self::assertNull($typeDescriptionFactory->instantiateTypeDescription('unknown-namespace::xyz')); }
/** * Set the input/output type of this filter group. * * @param $inputType TypeDescription|string * @param $outputType TypeDescription|string * * @see TypeDescriptionFactory::instantiateTypeDescription() for more details */ function setTransformationType(&$inputType, &$outputType) { $typeDescriptionFactory = TypeDescriptionFactory::getInstance(); // Instantiate the type descriptions if we got string input. if (!is_a($inputType, 'TypeDescription')) { assert(is_string($inputType)); $inputType = $typeDescriptionFactory->instantiateTypeDescription($inputType); } if (!is_a($outputType, 'TypeDescription')) { assert(is_string($outputType)); $outputType = $typeDescriptionFactory->instantiateTypeDescription($outputType); } $this->_inputType = $inputType; $this->_outputType = $outputType; }
/** * Set the input/output type of this filter instance. * * @param $inputType TypeDescription|string * @param $outputType TypeDescription|string * * @see TypeDescriptionFactory::instantiateTypeDescription() for more details * * NB: the input/output type combination must be one of those * returned by getSupportedTransformations(). */ function setTransformationType(&$inputType, &$outputType) { $typeDescriptionFactory =& TypeDescriptionFactory::getInstance(); // We need both, the input/output type as a string and // as a TypeDescription if (is_a($inputType, 'TypeDescription')) { $inputTypeString = $inputType->getTypeDescription(); } else { $inputTypeString = $inputType; $inputType =& $typeDescriptionFactory->instantiateTypeDescription($inputType); } if (is_a($outputType, 'TypeDescription')) { $outputTypeString = $outputType->getTypeDescription(); } else { $outputTypeString = $outputType; $outputType =& $typeDescriptionFactory->instantiateTypeDescription($outputType); } // Make sure that this transformation is valid if (!$this->isValidTransformation($inputTypeString, $outputTypeString)) { fatalError('Trying to set an invalid transformation type.'); } $this->_inputType =& $inputType; $this->_outputType =& $outputType; }
/** * Retrieve filter instances that support a given input and * output sample object. * * The selection of filters that are compatible with the * given input and output samples is based on their type * description. * * @param $inputSample mixed * @param $outputSample mixed * @param $contextId integer * @param $getTemplates boolean set true if you want filter templates * rather than actual transformations * @param $rehash boolean if true then the (costly) filter * hash operation will be repeated even if the filters have * been hashed before. * @return array all compatible filter instances (transformations). */ function &getCompatibleObjects($inputSample, $outputSample, $contextId = 0, $getTemplates = false, $rehash = false) { static $filterHash = array(); static $typeDescriptionFactory = null; static $typeDescriptionCache = array(); static $filterInstanceCache = array(); // Instantiate the type description factory if (is_null($typeDescriptionFactory)) { $typeDescriptionFactory =& TypeDescriptionFactory::getInstance(); } // 1) Hash all available transformations by input // and output type. $hashId = $contextId . '-' . ($getTemplates ? '1' : '0'); if (!isset($filterHash[$hashId]) || $rehash) { $result =& $this->retrieve('SELECT * FROM filters' . ' WHERE ' . ($getTemplates ? 'is_template = 1' : 'is_template = 0') . ' AND context_id in (0, ?) AND parent_filter_id = 0', (int) $contextId); foreach ($result->GetAssoc() as $filterRow) { $filterHash[$hashId][$filterRow['input_type']][$filterRow['output_type']][] = $filterRow; } // Set an empty array if no filters were found at all. if (!isset($filterHash[$hashId])) { $filterHash[$hashId] = array(); } } // 2) Check the input sample against all input types. $intermediateCandidates = array(); foreach ($filterHash[$hashId] as $inputType => $outputHash) { // Instantiate the type description if not yet done // before. if (!isset($typeDescriptionCache[$inputType])) { $typeDescriptionCache[$inputType] =& $typeDescriptionFactory->instantiateTypeDescription($inputType); } // 3) Whenever an input type matches, hash all filters // with this input type by output type. if ($typeDescriptionCache[$inputType]->checkType($inputSample)) { foreach ($outputHash as $outputType => $filterRows) { if (!isset($intermediateCandidates[$outputType])) { $intermediateCandidates[$outputType] = $filterRows; } else { $intermediateCandidates[$outputType] = array_merge($intermediateCandidates[$outputType], $filterRows); } } } } // 4) Check the output sample against all hashed output // types. $matchingFilterRows = array(); foreach ($intermediateCandidates as $outputType => $filterRows) { // Instantiate the type description if not yet done // before. if (!isset($typeDescriptionCache[$outputType])) { $typeDescriptionCache[$outputType] =& $typeDescriptionFactory->instantiateTypeDescription($outputType); } // 5) Whenever an output type matches, add all filters // with this output type to the result set. if ($typeDescriptionCache[$outputType]->checkType($outputSample)) { $matchingFilterRows = array_merge($matchingFilterRows, $filterRows); } } // 6) Instantiate and return all transformations in the // result set that comply with the current runtime // environment. $matchingFilters = array(); $runTimeRequirementNotMet = -1; foreach ($matchingFilterRows as $matchingFilterRow) { if (!isset($filterInstanceCache[$matchingFilterRow['filter_id']])) { $filterInstance =& $this->_fromRow($matchingFilterRow); if ($filterInstance->isCompatibleWithRuntimeEnvironment()) { $filterInstanceCache[$matchingFilterRow['filter_id']] =& $filterInstance; } else { $filterInstanceCache[$matchingFilterRow['filter_id']] = $runTimeRequirementNotMet; } unset($filterInstance); } if ($filterInstanceCache[$matchingFilterRow['filter_id']] !== $runTimeRequirementNotMet) { $matchingFilters[$matchingFilterRow['filter_id']] = $filterInstanceCache[$matchingFilterRow['filter_id']]; } } return $matchingFilters; }