From 8109b60cc28a0e62951d11f65eade7dc5f2a5db2 Mon Sep 17 00:00:00 2001 From: Pierre PLAZANET Date: Fri, 20 Jun 2014 11:53:37 +0200 Subject: [PATCH 01/33] Introducte composer updates --- composer.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 0c0697f7..a0e78ce1 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,9 @@ "name": "knplabs/friendly-contexts", "description": "Some BEHAT contexts", "autoload": { - "psr-0": { "Knp\\FriendlyContexts": "src/"} + "psr-0": + "Knp\\FriendlyContexts": "src/", + "Knp\\FriendlyExtension": "src/" }, "require": { "behat/behat": "~3.0", From 5c49b97d5be626d122b02f5eb3baef7e84a307ac Mon Sep 17 00:00:00 2001 From: Pierre PLAZANET Date: Fri, 20 Jun 2014 12:08:03 +0200 Subject: [PATCH 02/33] Fix composer --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index a0e78ce1..a4bedaba 100644 --- a/composer.json +++ b/composer.json @@ -2,9 +2,10 @@ "name": "knplabs/friendly-contexts", "description": "Some BEHAT contexts", "autoload": { - "psr-0": + "psr-0": { "Knp\\FriendlyContexts": "src/", "Knp\\FriendlyExtension": "src/" + } }, "require": { "behat/behat": "~3.0", From cda5accc0abd5ef7a3666fdd839f68d0aa04f2a3 Mon Sep 17 00:00:00 2001 From: Pierre PLAZANET Date: Wed, 25 Jun 2014 16:12:42 +0200 Subject: [PATCH 03/33] Add new namespace --- src/Knp/FriendlyExtension.php | 123 ++++++++++++++++++ .../Context/Helper/AsserterHelper.php | 89 +++++++++++++ .../Context/Helper/HelperInterface.php | 8 ++ .../Compiler/ApiUrlTransitionPass.php | 22 ++++ .../Compiler/FakerGuesserRegistrationPass.php | 26 ++++ .../FakerProviderRegistrationPass.php | 54 ++++++++ .../Compiler/KernelRegistrationPass.php | 45 +++++++ .../Compiler/ParameterBuildingPass.php | 41 ++++++ .../FriendlyExtension/Doctrine/Resolver.php | 84 ++++++++++++ .../Faker/Provider/Address.php | 30 +++++ .../FriendlyExtension/Faker/Provider/Base.php | 74 +++++++++++ .../Faker/Provider/DateTime.php | 20 +++ .../Faker/Provider/Internet.php | 21 +++ .../Faker/Provider/Person.php | 20 +++ .../Faker/Provider/PhoneNumber.php | 30 +++++ .../FriendlyExtension/Record/Collection.php | 114 ++++++++++++++++ .../Record/Collection/Bag.php | 41 ++++++ src/Knp/FriendlyExtension/Record/Record.php | 67 ++++++++++ .../Symfony/ServiceShifter.php | 27 ++++ .../Type/Guesser/AbstractGuesser.php | 37 ++++++ .../Type/Guesser/BigintGuesser.php | 25 ++++ .../Type/Guesser/BooleanGuesser.php | 54 ++++++++ .../Type/Guesser/DatetimeGuesser.php | 36 +++++ .../Type/Guesser/DecimalGuesser.php | 30 +++++ .../Type/Guesser/EntityGuesser.php | 54 ++++++++ .../Type/Guesser/GuesserInterface.php | 20 +++ .../Type/Guesser/IntGuesser.php | 30 +++++ .../Type/Guesser/SmallintGuesser.php | 25 ++++ .../Type/Guesser/StringGuesser.php | 43 ++++++ .../Type/GuesserRegistry.php | 28 ++++ .../FriendlyExtension/Utils/NameProposer.php | 46 +++++++ .../Utils/ObjectReflector.php | 45 +++++++ .../FriendlyExtension/Utils/TextFormater.php | 97 ++++++++++++++ src/Knp/FriendlyExtension/services/core.yml | 6 + src/Knp/FriendlyExtension/services/faker.yml | 46 +++++++ .../FriendlyExtension/services/guesser.yml | 44 +++++++ .../FriendlyExtension/services/services.yml | 1 + .../FriendlyExtension/services/symfony.yml | 18 +++ 38 files changed, 1621 insertions(+) create mode 100644 src/Knp/FriendlyExtension.php create mode 100644 src/Knp/FriendlyExtension/Context/Helper/AsserterHelper.php create mode 100644 src/Knp/FriendlyExtension/Context/Helper/HelperInterface.php create mode 100644 src/Knp/FriendlyExtension/DependencyInjection/Compiler/ApiUrlTransitionPass.php create mode 100644 src/Knp/FriendlyExtension/DependencyInjection/Compiler/FakerGuesserRegistrationPass.php create mode 100644 src/Knp/FriendlyExtension/DependencyInjection/Compiler/FakerProviderRegistrationPass.php create mode 100644 src/Knp/FriendlyExtension/DependencyInjection/Compiler/KernelRegistrationPass.php create mode 100644 src/Knp/FriendlyExtension/DependencyInjection/Compiler/ParameterBuildingPass.php create mode 100644 src/Knp/FriendlyExtension/Doctrine/Resolver.php create mode 100644 src/Knp/FriendlyExtension/Faker/Provider/Address.php create mode 100644 src/Knp/FriendlyExtension/Faker/Provider/Base.php create mode 100644 src/Knp/FriendlyExtension/Faker/Provider/DateTime.php create mode 100644 src/Knp/FriendlyExtension/Faker/Provider/Internet.php create mode 100644 src/Knp/FriendlyExtension/Faker/Provider/Person.php create mode 100644 src/Knp/FriendlyExtension/Faker/Provider/PhoneNumber.php create mode 100644 src/Knp/FriendlyExtension/Record/Collection.php create mode 100644 src/Knp/FriendlyExtension/Record/Collection/Bag.php create mode 100644 src/Knp/FriendlyExtension/Record/Record.php create mode 100644 src/Knp/FriendlyExtension/Symfony/ServiceShifter.php create mode 100644 src/Knp/FriendlyExtension/Type/Guesser/AbstractGuesser.php create mode 100644 src/Knp/FriendlyExtension/Type/Guesser/BigintGuesser.php create mode 100644 src/Knp/FriendlyExtension/Type/Guesser/BooleanGuesser.php create mode 100644 src/Knp/FriendlyExtension/Type/Guesser/DatetimeGuesser.php create mode 100644 src/Knp/FriendlyExtension/Type/Guesser/DecimalGuesser.php create mode 100644 src/Knp/FriendlyExtension/Type/Guesser/EntityGuesser.php create mode 100644 src/Knp/FriendlyExtension/Type/Guesser/GuesserInterface.php create mode 100644 src/Knp/FriendlyExtension/Type/Guesser/IntGuesser.php create mode 100644 src/Knp/FriendlyExtension/Type/Guesser/SmallintGuesser.php create mode 100644 src/Knp/FriendlyExtension/Type/Guesser/StringGuesser.php create mode 100644 src/Knp/FriendlyExtension/Type/GuesserRegistry.php create mode 100644 src/Knp/FriendlyExtension/Utils/NameProposer.php create mode 100644 src/Knp/FriendlyExtension/Utils/ObjectReflector.php create mode 100644 src/Knp/FriendlyExtension/Utils/TextFormater.php create mode 100644 src/Knp/FriendlyExtension/services/core.yml create mode 100644 src/Knp/FriendlyExtension/services/faker.yml create mode 100644 src/Knp/FriendlyExtension/services/guesser.yml create mode 100644 src/Knp/FriendlyExtension/services/services.yml create mode 100644 src/Knp/FriendlyExtension/services/symfony.yml diff --git a/src/Knp/FriendlyExtension.php b/src/Knp/FriendlyExtension.php new file mode 100644 index 00000000..775ac112 --- /dev/null +++ b/src/Knp/FriendlyExtension.php @@ -0,0 +1,123 @@ +children() + ->arrayNode('symfony_kernel') + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('bootstrap') + ->defaultValue('app/autoload.php') + ->end() + ->scalarNode('path') + ->defaultValue('app/AppKernel.php') + ->end() + ->scalarNode('class') + ->defaultValue('AppKernel') + ->end() + ->scalarNode('env') + ->defaultValue('test') + ->end() + ->booleanNode('debug') + ->defaultTrue() + ->end() + ->end() + ->end() + ->arrayNode('alice') + ->addDefaultsIfNotSet() + ->children() + ->arrayNode('fixtures') + ->prototype('scalar')->end() + ->end() + ->arrayNode('dependencies') + ->useAttributeAsKey('name') + ->prototype('array') + ->prototype('scalar')->end() + ->end() + ->end() + ->end() + ->end() + ->arrayNode('page') + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('namespace') + ->defaultValue('Page') + ->end() + ->end() + ->end() + ->arrayNode('api') + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('base_url') + ->defaultValue('') + ->end() + ->end() + ->end() + ->arrayNode('faker') + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('locale') + ->defaultValue(Factory::DEFAULT_LOCALE) + ->end() + ->end() + ->end() + ->scalarNode('smartTag') + ->defaultValue('smartStep') + ->end() + ->end() + ; + } + + public function load(ContainerBuilder $container, array $config) + { + $loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/FriendlyExtension/services')); + $loader->load('core.yml'); + $loader->load('faker.yml'); + $loader->load('guesser.yml'); + $loader->load('symfony.yml'); + + $container->setParameter('friendly.parameters', $config); + + $container->addCompilerPass(new ParameterBuildingPass); + $container->addCompilerPass(new KernelRegistrationPass); + $container->addCompilerPass(new FakerProviderRegistrationPass); + $container->addCompilerPass(new FakerGuesserRegistrationPass); + $container->addCompilerPass(new ApiUrlTransitionPass); + } + + public function process(ContainerBuilder $container) + { + foreach ($container->getServiceIds() as $id) { + echo $id; + echo "\n"; + } + } +} diff --git a/src/Knp/FriendlyExtension/Context/Helper/AsserterHelper.php b/src/Knp/FriendlyExtension/Context/Helper/AsserterHelper.php new file mode 100644 index 00000000..b605fad7 --- /dev/null +++ b/src/Knp/FriendlyExtension/Context/Helper/AsserterHelper.php @@ -0,0 +1,89 @@ +formater = $formater; + } + + public function getName() + { + return 'asserter'; + } + + public function assertArrayEquals(array $expected, array $real, $fullText = false) + { + $message = sprintf("The given array\r\n\r\n%s\r\nis not equals to expected\r\n\r\n%s", $this->explode($real), $this->explode($expected)); + + if (false === $fullText) { + return $this->assertEquals( + $expected, + $real, + $message + ); + } else { + return $this->assertEquals( + $this->explode($expected), + $this->explode($real), + $message + ); + } + } + + public function assertArrayContains(array $expected, array $real, $message = null) + { + $message = $message ?: sprintf("The given array\r\n\r\n%s\r\ndoes not contains the following rows\r\n\r\n%s", $this->explode($real), $this->explode($expected)); + + foreach ($expected as $key => $value) { + $this->assert(isset($real[$key]), $message); + + if (is_array($value)) { + $this->assert(is_array($real[$key]), $message); + $this->assertArrayContains($value, $real[$key], $message); + + continue; + } + + $value = is_string($value) ? trim($value) : $value; + $real[$key] = is_string($real[$key]) ? trim($real[$key]) : $real[$key]; + + $this->assert($value === $real[$key], $message); + } + } + + public function assertEquals($expected, $real, $message = "Failing to assert equals.") + { + return $this->assert($expected === $real, $message); + } + + public function assertNotEquals($expected, $real, $message = "Failing to assert not equals.") + { + return $this->assert($expected !== $real, $message); + } + + public function assert($result, $message = "Assert failure") + { + if (false === $result) { + throw new \Exception($message, 1); + } + + return true; + } + + protected function explode($value) + { + if (!is_array($value)) { + return (string) $value;; + } else { + return $this->formater->tableToString($value); + } + } +} diff --git a/src/Knp/FriendlyExtension/Context/Helper/HelperInterface.php b/src/Knp/FriendlyExtension/Context/Helper/HelperInterface.php new file mode 100644 index 00000000..6c7b94b0 --- /dev/null +++ b/src/Knp/FriendlyExtension/Context/Helper/HelperInterface.php @@ -0,0 +1,8 @@ +getParameter('friendly.api.base_url'); + + if (empty($url)) { + if ($container->hasParameter('mink.base_url')) { + $url = $container->getParameter('mink.base_url'); + } + } + + $container->setParameter('friendly.api.base_url', $url); + } +} diff --git a/src/Knp/FriendlyExtension/DependencyInjection/Compiler/FakerGuesserRegistrationPass.php b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/FakerGuesserRegistrationPass.php new file mode 100644 index 00000000..c251ba52 --- /dev/null +++ b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/FakerGuesserRegistrationPass.php @@ -0,0 +1,26 @@ +findTaggedServiceIds('friendly.type.guesser')); + $fakers = array_keys($container->findTaggedServiceIds('friendly.faker.provider')); + + $regitry = $container->getDefinition('friendly.type.guesser_registry'); + + foreach ($guessers as $guesser) { + $definition = $container->getDefinition($guesser); + foreach ($fakers as $faker) { + $definition->addMethodCall('addFaker', [ new Reference($faker) ]); + } + $regitry->addMethodCall('addGuesser', [ new Reference($guesser) ]); + } + } +} diff --git a/src/Knp/FriendlyExtension/DependencyInjection/Compiler/FakerProviderRegistrationPass.php b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/FakerProviderRegistrationPass.php new file mode 100644 index 00000000..d459b713 --- /dev/null +++ b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/FakerProviderRegistrationPass.php @@ -0,0 +1,54 @@ +findTaggedServiceIds('friendly.faker.provider')); + $generator = $container->get('friendly.faker.generator'); + + foreach ($generator->getProviders() as $provider) { + $identifier = sprintf('friendly.faker.provider.%s', strtolower((new \ReflectionClass($provider))->getShortName())); + $legacy = sprintf('%s.legacy', $identifier); + $container->setDefinition($legacy, $this->buildProviderDefinition($provider)); + + $definition = $this->buildBaseProviderDefinition(); + + foreach ($ids as $id) { + $child = $container->get($id); + + if ($child->supportsParent($provider)) { + $definition = $container->getDefinition($id); + } + } + + $definition->addMethodCall('setParent', [ new Reference($legacy) ]); + $definition->addTag('friendly.faker.provider'); + + $container->setDefinition($identifier, $definition); + } + } + + private function buildProviderDefinition(Base $provider) + { + return (new Definition()) + ->setClass(get_class($provider)) + ->addArgument(new Reference('friendly.faker.generator')) + ; + } + + private function buildBaseProviderDefinition() + { + return (new Definition()) + ->setClass('Knp\FriendlyExtension\Faker\Provider\Base') + ; + } +} diff --git a/src/Knp/FriendlyExtension/DependencyInjection/Compiler/KernelRegistrationPass.php b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/KernelRegistrationPass.php new file mode 100644 index 00000000..84b53f87 --- /dev/null +++ b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/KernelRegistrationPass.php @@ -0,0 +1,45 @@ +getParameter('paths.base'); + + $this->loadFileFromParameter($container, 'friendly.symfony_kernel.bootstrap'); + $this->loadFileFromParameter($container, 'friendly.symfony_kernel.path'); + + if (null !== $class = $this->getKernelClass($container)) { + $definition = new Definition($class); + $definition + ->addArgument($container->getParameter('friendly.symfony_kernel.env')) + ->addArgument($container->getParameter('friendly.symfony_kernel.debug')) + ; + $container->setDefinition('friendly.symfony.kernel', $definition); + } + } + + protected function loadFileFromParameter(ContainerBuilder $container, $parameter) + { + $base = $container->getParameter('paths.base'); + $param = $container->getParameter($parameter); + if (file_exists($file = $base.DIRECTORY_SEPARATOR.$param)) { + require_once($file); + } elseif (file_exists($param)) { + require_once($param); + } + } + + protected function getKernelClass(ContainerBuilder $container) + { + $class = $container->getParameter('friendly.symfony_kernel.class'); + + return class_exists($class) ? $class : null; + } +} diff --git a/src/Knp/FriendlyExtension/DependencyInjection/Compiler/ParameterBuildingPass.php b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/ParameterBuildingPass.php new file mode 100644 index 00000000..7422c45e --- /dev/null +++ b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/ParameterBuildingPass.php @@ -0,0 +1,41 @@ +buildParameters('friendly', $parameters, $container->getParameter('friendly.parameters')); + + foreach ($parameters as $key => $value) { + $container->setParameter($key, $value); + } + } + + protected function buildParameters($name, &$parameters, $config) + { + foreach ($config as $key => $element) { + if (is_array($element) && $this->arrayHasStringKeys($element)) { + $this->buildParameters(sprintf('%s.%s', $name, $key), $parameters, $element); + } + $parameters[sprintf('%s.%s', $name, $key)] = $element; + } + } + + protected function arrayHasStringKeys(array $array) + { + foreach ($array as $key => $value) { + if (is_string($key)) { + + return true; + } + } + + return false; + } +} diff --git a/src/Knp/FriendlyExtension/Doctrine/Resolver.php b/src/Knp/FriendlyExtension/Doctrine/Resolver.php new file mode 100644 index 00000000..7cdbff7c --- /dev/null +++ b/src/Knp/FriendlyExtension/Doctrine/Resolver.php @@ -0,0 +1,84 @@ +em = $em; + $this->reflector = $reflector; + $this->formater = $formater; + $this->proposer = $proposer; + } + + public function resolveEntity($name, $onlyOne = false) + { + $entities = array_filter( + $this->getAllEntities(), + function ($e) use ($name) { + return $this->proposer->match($name, $e->getShortName()); + } + ); + + if (true === $onlyOne && 1 > count($entities)) { + throw new \Exception(sprintf('Expected only one entity named "%s", "%s" found', $name, + implode('", "', + array_map( + function ($e) { return $e->getShortName(); }, + $entities + ), + ) + )); + } + + return $onlyOne + ? empty($entities) ? null : current($entities) + : $entities + ; + } + + public function resolveProperty($name, $property) + { + $entity = $this->resolveEntity($name, true); + + + } + + private function getAllEntities() + { + $metadata = $this->em->getMetadataFactory()->getAllMetadata(); + + return $this->reflector->getReflectionsFromMetadata($allMetadata); + } + + private function getMetadataFor($class, $property = null) + { + $metadata = $this->em->getMetadataFactory()->getMetadataFor($class); + + if (null === $property) { + + return $metadata; + } + + if (null !== $name = $this->resolveName($property, array_keys($metadata->fieldMappings))) { + + return $metadata->fieldMappings[$name]; + } + + if (null !== $name = $this->resolveName($property, array_keys($metadata->associationMappings))) { + + return $metadata->associationMappings[$name]; + } + } +} diff --git a/src/Knp/FriendlyExtension/Faker/Provider/Address.php b/src/Knp/FriendlyExtension/Faker/Provider/Address.php new file mode 100644 index 00000000..9adfd9dd --- /dev/null +++ b/src/Knp/FriendlyExtension/Faker/Provider/Address.php @@ -0,0 +1,30 @@ +parent->streetAddress(); + } + + public function postalcode() + { + return $this->parent->postcode(); + } + + public function zipcode() + { + return $this->parent->postcode(); + } + + public function supportsParent(FakerBase $parent) + { + return $parent instanceOf FakerAddress; + } +} diff --git a/src/Knp/FriendlyExtension/Faker/Provider/Base.php b/src/Knp/FriendlyExtension/Faker/Provider/Base.php new file mode 100644 index 00000000..fd2fb6fd --- /dev/null +++ b/src/Knp/FriendlyExtension/Faker/Provider/Base.php @@ -0,0 +1,74 @@ +generator->getProviders() as $provider) { + if ($this->supportsParent($provider)) { + $this->setParent($provider); + } + } + } + + public function getParent() + { + return $this->parent; + } + + public function setParent(FakerBase $parent) + { + $this->parent = $parent; + + return $this; + } + + public function supportsParent($parent) + { + return false; + } + + public function isFakable($property) + { + if (null !== $this->parent) { + if ($this->hasFakerMethod($this->parent, $property)) { + return true; + } + } + + return $this->hasFakerMethod($this, $property); + } + + public function fake($property, array $args = []) + { + $object = method_exists($this, $property) ? $this : null; + + if ((null !== $this->parent) && ($this->hasFakerMethod($this->parent, $property))) { + $object = $this->parent; + } + + $method = $this->getFakerMethod($object, $property); + + return $method->invokeArgs($method->isStatic() ? null : $object, $args); + } + + protected function hasFakerMethod($object, $method) + { + $rfl = new \ReflectionClass($object); + + return $rfl->hasMethod($method); + } + + protected function getFakerMethod($object, $method) + { + $rfl = new \ReflectionClass($object); + + return $rfl->getMethod($method); + } +} diff --git a/src/Knp/FriendlyExtension/Faker/Provider/DateTime.php b/src/Knp/FriendlyExtension/Faker/Provider/DateTime.php new file mode 100644 index 00000000..6324c93d --- /dev/null +++ b/src/Knp/FriendlyExtension/Faker/Provider/DateTime.php @@ -0,0 +1,20 @@ +parent->unixTime(); + } + + public function supportsParent(FakerBase $parent) + { + return $parent instanceOf FakerDateTime; + } +} diff --git a/src/Knp/FriendlyExtension/Faker/Provider/Internet.php b/src/Knp/FriendlyExtension/Faker/Provider/Internet.php new file mode 100644 index 00000000..ac7d33ff --- /dev/null +++ b/src/Knp/FriendlyExtension/Faker/Provider/Internet.php @@ -0,0 +1,21 @@ +parent->userName(); + } + + + public function supportsParent(FakerBase $parent) + { + return $parent instanceOf FakerInternet; + } +} diff --git a/src/Knp/FriendlyExtension/Faker/Provider/Person.php b/src/Knp/FriendlyExtension/Faker/Provider/Person.php new file mode 100644 index 00000000..952b0707 --- /dev/null +++ b/src/Knp/FriendlyExtension/Faker/Provider/Person.php @@ -0,0 +1,20 @@ +parent->name(); + } + + public function supportsParent(FakerBase $parent) + { + return $parent instanceOf FakerPerson; + } +} diff --git a/src/Knp/FriendlyExtension/Faker/Provider/PhoneNumber.php b/src/Knp/FriendlyExtension/Faker/Provider/PhoneNumber.php new file mode 100644 index 00000000..e167791f --- /dev/null +++ b/src/Knp/FriendlyExtension/Faker/Provider/PhoneNumber.php @@ -0,0 +1,30 @@ +parent->phoneNumber(); + } + + public function fax() + { + return $this->parent->phoneNumber(); + } + + public function mobile() + { + return $this->parent->phoneNumber(); + } + + public function supportsParent(FakerBase $parent) + { + return $parent instanceOf FakerPhoneNumber; + } +} diff --git a/src/Knp/FriendlyExtension/Record/Collection.php b/src/Knp/FriendlyExtension/Record/Collection.php new file mode 100644 index 00000000..b526856b --- /dev/null +++ b/src/Knp/FriendlyExtension/Record/Collection.php @@ -0,0 +1,114 @@ +reflector = $reflector; + $this->headers = []; + $this->records = []; + } + + public function support($entity) + { + if (null !== $this->referencial) { + $name = $this->referencial; + + return $this->reflector->isInstanceOf($entity, $name); + } + $this->setReferencial($entity); + + return true; + } + + public function getReferencial() + { + return $this->referencial; + } + + public function setReferencial($entity) + { + $this->referencial = is_object($entity) ? $this->reflector->getClassLongName($entity) : $entity; + + return $this; + } + + public function attach($entity, array $values = null) + { + $values = $values ?: $this->buildValues($entity); + $this->mergeHeaders(array_keys($values)); + + $record = new Record($this->reflector, $this); + $record->attach($entity, $values); + + $this->records[] = $record; + + return $record; + } + + public function search($value) + { + foreach ($this->records as $record) { + if ((string) $record === $value) { + return $record; + } + } + + foreach ($this->headers as $header) { + foreach ($this->records as $record) { + if (null !== $record->get($header) && $value === $record->get($header)) { + return $record; + } + } + } + } + + public function all() + { + return array_values($this->records); + } + + public function count() + { + return count($this->records); + } + + protected function mergeHeaders($headers) + { + foreach ($headers as $header) { + if (!in_array($header, $this->headers)) { + $this->headers[] = $header; + } + } + } + + protected function buildValues($entity) + { + $result = []; + $accessor = PropertyAccess::getPropertyAccessor(); + + foreach ($this->headers as $header) { + try { + $value = $accessor->setValue($entity, $header); + if (is_scalar($value)) { + $result[$header] = $value; + } + } catch (\Exception $ex) { + unset($ex); + } + } + + return $result; + } +} diff --git a/src/Knp/FriendlyExtension/Record/Collection/Bag.php b/src/Knp/FriendlyExtension/Record/Collection/Bag.php new file mode 100644 index 00000000..a549f70f --- /dev/null +++ b/src/Knp/FriendlyExtension/Record/Collection/Bag.php @@ -0,0 +1,41 @@ +reflector = $reflector; + } + + public function clear() + { + $this->collections = []; + } + + public function getCollection($entity) + { + foreach ($this->collections as $collection) { + if ($collection->support($entity)) { + return $collection; + } + } + + $new = new Collection($this->reflector); + $new->support($entity); + + return $this->collections[] = $new;; + } + + public function count() + { + return count($this->collections); + } +} diff --git a/src/Knp/FriendlyExtension/Record/Record.php b/src/Knp/FriendlyExtension/Record/Record.php new file mode 100644 index 00000000..50e8dc15 --- /dev/null +++ b/src/Knp/FriendlyExtension/Record/Record.php @@ -0,0 +1,67 @@ +reflector = $reflector; + $this->collection = $collection; + } + + public function __toString() + { + return (string) $this->entity; + } + + public function attach($entity, $values = []) + { + if (!$this->collection->support($entity)) { + throw new \InvalidArgumentException('Given entity is not supported by the collection'); + } + + $this->entity = $entity; + $this->values = $values; + } + + public function getEntity() + { + return $this->entity; + } + + public function all() + { + return $this->values; + } + + public function has($key) + { + return array_key_exists($key, $this->values); + } + + public function get($key) + { + if ($this->has($key)) { + return $this->values[$key]; + } + } + + public function equals($key, $value) + { + if ($this->has($key)) { + return $this->get($key) === $value; + } + + return false; + } +} diff --git a/src/Knp/FriendlyExtension/Symfony/ServiceShifter.php b/src/Knp/FriendlyExtension/Symfony/ServiceShifter.php new file mode 100644 index 00000000..43859435 --- /dev/null +++ b/src/Knp/FriendlyExtension/Symfony/ServiceShifter.php @@ -0,0 +1,27 @@ +kernel = $container->get('friendly.symfony.kernel', ContainerInterface::NULL_ON_INVALID_REFERENCE); + } + + public function get($id) + { + if (null === $this->kernel) { + + return null; + } + + return $this + ->kernel + ->getContainer() + ->get($id, ContainerInterface::NULL_ON_INVALID_REFERENCE) + ; + } +} diff --git a/src/Knp/FriendlyExtension/Type/Guesser/AbstractGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/AbstractGuesser.php new file mode 100644 index 00000000..8f802196 --- /dev/null +++ b/src/Knp/FriendlyExtension/Type/Guesser/AbstractGuesser.php @@ -0,0 +1,37 @@ +manager; + } + + public function setManager(GuesserRegistry $manager) + { + $this->manager = $manager; + + return $this; + } + + public function addFaker(Base $faker) + { + if (null !== $faker->getParent()) { + $this->fakers[] = $faker; + } + } + + protected function get($name) + { + return $this->getManager()->getContainer()->get($name); + } +} diff --git a/src/Knp/FriendlyExtension/Type/Guesser/BigintGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/BigintGuesser.php new file mode 100644 index 00000000..9b729806 --- /dev/null +++ b/src/Knp/FriendlyExtension/Type/Guesser/BigintGuesser.php @@ -0,0 +1,25 @@ + null ], $mapping); + + return $mapping['type'] === 'bigint'; + } + + public function fake(array $mapping) + { + return current($this->fakers)->fake('randomNumber'); + } + + public function getName() + { + return 'bigint'; + } +} diff --git a/src/Knp/FriendlyExtension/Type/Guesser/BooleanGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/BooleanGuesser.php new file mode 100644 index 00000000..09d4a1c3 --- /dev/null +++ b/src/Knp/FriendlyExtension/Type/Guesser/BooleanGuesser.php @@ -0,0 +1,54 @@ + null ], $mapping); + + return $mapping['type'] === 'boolean'; + } + + public function transform($str, array $mapping = null) + { + $str = strtolower($str); + + $formats = [ + 'active' => true, + 'activated' => true, + 'disabled' => false, + 'true' => true, + 'false' => false, + 'yes' => true, + 'no' => false, + '1' => true, + '0' => false, + ]; + + if (false === array_key_exists($str, $formats)) { + throw new \Exception( + sprintf( + '"%s" is not a supported format. Supported format : [%s].', + $str, + implode(', ', array_keys($formats)) + ) + ); + } + + return $formats[$str]; + } + + public function fake(array $mapping) + { + return true; + } + + public function getName() + { + return 'boolean'; + } +} diff --git a/src/Knp/FriendlyExtension/Type/Guesser/DatetimeGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/DatetimeGuesser.php new file mode 100644 index 00000000..194479b6 --- /dev/null +++ b/src/Knp/FriendlyExtension/Type/Guesser/DatetimeGuesser.php @@ -0,0 +1,36 @@ + null ], $mapping); + + return in_array($mapping['type'], ['datetime', 'date', 'time']); + } + + public function transform($str, array $mapping = null) + { + $time = strtotime($str); + + if (false === $time) { + throw new \Exception(sprintf('"%s" is not a supported date/time/datetime format. To know which formats are supported, please visit http://www.php.net/manual/en/datetime.formats.php', $str)); + } + + return \DateTime::createFromFormat('U', $time); + } + + public function fake(array $mapping) + { + return new \DateTime(); + } + + public function getName() + { + return 'datetime'; + } +} diff --git a/src/Knp/FriendlyExtension/Type/Guesser/DecimalGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/DecimalGuesser.php new file mode 100644 index 00000000..2c67f543 --- /dev/null +++ b/src/Knp/FriendlyExtension/Type/Guesser/DecimalGuesser.php @@ -0,0 +1,30 @@ + null ], $mapping); + + return in_array($mapping['type'], [ 'decimal', 'float' ]); + } + + public function transform($str, array $mapping = null) + { + return (float) $str; + } + + public function fake(array $mapping) + { + return current($this->fakers)->fake('randomFloat'); + } + + public function getName() + { + return 'decimal'; + } +} diff --git a/src/Knp/FriendlyExtension/Type/Guesser/EntityGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/EntityGuesser.php new file mode 100644 index 00000000..de987dee --- /dev/null +++ b/src/Knp/FriendlyExtension/Type/Guesser/EntityGuesser.php @@ -0,0 +1,54 @@ +bag = $bag; + } + + public function supports(array $mapping) + { + if (array_key_exists('targetEntity', $mapping)) { + + return $this->bag->getCollection($mapping['targetEntity'])->count() > 0; + } + + return false; + } + + public function transform($str, array $mapping) + { + $str = strlen((string) $str) ? $str : null; + + if (null !== $record = $this->bag->getCollection($mapping['targetEntity'])->search($str)) { + + return $record->getEntity(); + } + + return null; + } + + public function fake(array $mapping) + { + $collection = $this->bag->getCollection($mapping['targetEntity']); + + if (0 === $collection->count()) { + throw new \Exception(sprintf('There is no record for "%s"', $mapping['targetEntity'])); + } + + $records = array_values($collection->all()); + + return $records[array_rand($records)]->getEntity(); + } + + public function getName() + { + return 'entity'; + } +} diff --git a/src/Knp/FriendlyExtension/Type/Guesser/GuesserInterface.php b/src/Knp/FriendlyExtension/Type/Guesser/GuesserInterface.php new file mode 100644 index 00000000..1abda5a4 --- /dev/null +++ b/src/Knp/FriendlyExtension/Type/Guesser/GuesserInterface.php @@ -0,0 +1,20 @@ + null ], $mapping); + + return $mapping['type'] === 'integer'; + } + + public function transform($str, array $mapping = null) + { + return (int) round($str); + } + + public function fake(array $mapping) + { + return current($this->fakers)->fake('numberBetween', [0, 2000000000]); + } + + public function getName() + { + return 'int'; + } +} diff --git a/src/Knp/FriendlyExtension/Type/Guesser/SmallintGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/SmallintGuesser.php new file mode 100644 index 00000000..18b53d2d --- /dev/null +++ b/src/Knp/FriendlyExtension/Type/Guesser/SmallintGuesser.php @@ -0,0 +1,25 @@ + null ], $mapping); + + return $mapping['type'] === 'smallint'; + } + + public function fake(array $mapping) + { + return $this->faker->fake('numberBetween', [0, 32000]); + } + + public function getName() + { + return 'smallint'; + } +} diff --git a/src/Knp/FriendlyExtension/Type/Guesser/StringGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/StringGuesser.php new file mode 100644 index 00000000..410827b3 --- /dev/null +++ b/src/Knp/FriendlyExtension/Type/Guesser/StringGuesser.php @@ -0,0 +1,43 @@ + null ], $mapping); + + return in_array($mapping['type'], ['string', 'text']); + } + + public function transform($str, array $mapping = null) + { + return $str; + } + + public function fake(array $mapping) + { + $mapping = array_merge( + ['fieldName' => null, 'type' => null], + $mapping + ); + + $name = $mapping['fieldName']; + + foreach ($this->fakers as $faker) { + if ($faker->isFakable($name)) { + return $faker->fake($name); + } + } + + return $this->fake(['fieldName' => 'text' === $mapping['type'] ? 'paragraph' : 'word']); + } + + public function getName() + { + return 'string'; + } +} diff --git a/src/Knp/FriendlyExtension/Type/GuesserRegistry.php b/src/Knp/FriendlyExtension/Type/GuesserRegistry.php new file mode 100644 index 00000000..d14c9895 --- /dev/null +++ b/src/Knp/FriendlyExtension/Type/GuesserRegistry.php @@ -0,0 +1,28 @@ +setManager($this); + + array_unshift($this->guessers, $guesser); + } + + public function find($mapping) + { + foreach ($this->guessers as $g) { + if ($g->supports($mapping)) { + return $g; + } + } + + return false; + } +} diff --git a/src/Knp/FriendlyExtension/Utils/NameProposer.php b/src/Knp/FriendlyExtension/Utils/NameProposer.php new file mode 100644 index 00000000..be032b64 --- /dev/null +++ b/src/Knp/FriendlyExtension/Utils/NameProposer.php @@ -0,0 +1,46 @@ +formater = $formater; + } + + public function match($name, $other) + { + $proposals = $this->buildProposals($name); + + return in_array($other, $proposals); + } + + public function buildProposals($name, $pluralize = false) + { + $proposals = [ + $this->formater->toCamelCase($name), + $this->formater->toUnderscoreCase($name), + $this->formater->toSpaceCase($name), + ]; + + if (true === $pluralize) { + $proposals = array_merge( + array_map(function ($e) { return Inflector::singularize($e); }, $proposals), + array_map(function ($e) { return Inflector::pluralize($e); }, $proposals) + ); + } + + $proposals = array_merge( + array_map('strtoupper', $proposals), + array_map('strtolower', $proposals) + ); + + return array_unique($proposals); + } +} diff --git a/src/Knp/FriendlyExtension/Utils/ObjectReflector.php b/src/Knp/FriendlyExtension/Utils/ObjectReflector.php new file mode 100644 index 00000000..b240b97f --- /dev/null +++ b/src/Knp/FriendlyExtension/Utils/ObjectReflector.php @@ -0,0 +1,45 @@ +getReflectionClass($object)->getShortName(); + } + + public function getClassNamespace($object) + { + return $this->getReflectionClass($object)->getNamespaceName(); + } + + public function getClassLongName($object) + { + return sprintf( + "%s\\%s", + $this->getClassNamespace($object), + $this->getClassName($object) + ); + } + + public function isInstanceOf($object, $class) + { + return $object instanceof $class || $this->getClassLongName($object) === $class; + } + + public function getReflectionsFromMetadata($metadata) + { + return array_map( + function ($e) { + return $this->getReflectionClass($e->name); + }, + $metadata + ); + } +} diff --git a/src/Knp/FriendlyExtension/Utils/TextFormater.php b/src/Knp/FriendlyExtension/Utils/TextFormater.php new file mode 100644 index 00000000..dcb39436 --- /dev/null +++ b/src/Knp/FriendlyExtension/Utils/TextFormater.php @@ -0,0 +1,97 @@ + +getDimentions($array)) { + + return sprintf('|%s|', implode('|', array_map(function ($e) { return sprintf(' %s ', trim($e)); }, $array))); + } + + $sizes = array(); + foreach ($array as $row) { + foreach ($row as $index => $cell) { + if (empty($sizes[$index])) { + $sizes[$index] = 0; + } + $sizes[$index] = max(array($sizes[$index], mb_strlen(trim($cell), 'UTF-8'))); + } + } + + $lines = array(); + foreach ($array as $row) { + $cells = array(); + foreach ($row as $index => $cell) { + $cells[] = sprintf(' %s ', $this->mbStrPad(trim($cell), $sizes[$index])); + } + $lines[] = sprintf('|%s|', implode('|', $cells)); + } + + return implode("\n", $lines). "\n"; + } + + public function listToArray($list, $delimiters = [', ', ' and '], $parser = "#||#") + { + $list = str_replace('"', '', $list); + + foreach ($delimiters as $delimiter) { + $list = str_replace($delimiter, $parser, $list); + } + + if (!is_string($list)) { + throw new \Exception($this->var_dump($list)); + } + + $parts = explode($parser, $list); + + $parts = array_map('trim', $parts); + $parts = array_filter($parts, 'strlen'); + + return $parts; + } + + protected function getDimentions(array $array) + { + return $this->goDeeper($array, 0); + } + + protected function goDeeper(array $array, $deep) + { + $deep++; + foreach ($array as $elem) { + if (is_array($elem)) { + $deep = max([ $this->goDeeper($elem, $deep), $deep ]); + } + } + + return $deep; + } + + protected function mbStrPad($input, $pad_length, $pad_string = ' ', $pad_type = STR_PAD_RIGHT) + { + $diff = strlen($input) - mb_strlen($input, 'UTF8'); + + return str_pad($input, $pad_length + $diff, $pad_string, $pad_type); + } +} diff --git a/src/Knp/FriendlyExtension/services/core.yml b/src/Knp/FriendlyExtension/services/core.yml new file mode 100644 index 00000000..0fd5b39b --- /dev/null +++ b/src/Knp/FriendlyExtension/services/core.yml @@ -0,0 +1,6 @@ +services: + + friendly.doctrine.resolver: + class: Knp\FriendlyExtension\Doctrine\Resolver + arguments: + - @doctrine.orm.entity_manager diff --git a/src/Knp/FriendlyExtension/services/faker.yml b/src/Knp/FriendlyExtension/services/faker.yml new file mode 100644 index 00000000..593bce8c --- /dev/null +++ b/src/Knp/FriendlyExtension/services/faker.yml @@ -0,0 +1,46 @@ +services: + + friendly.faker.factory: + class: Faker\Factory + + friendly.faker.generator: + class: Faker\Generator + factory_service: friendly.faker.factory + factory_method: create + arguments: + - %friendly.faker.locale% + + friendly.faker.provider.address: + class: Knp\FriendlyExtension\Faker\Provider\Address + arguments: + - @friendly.faker.generator + tags: + - { name: friendly.faker.provider } + + friendly.faker.provider.datetime: + class: Knp\FriendlyExtension\Faker\Provider\DateTime + arguments: + - @friendly.faker.generator + tags: + - { name: friendly.faker.provider } + + friendly.faker.provider.internet: + class: Knp\FriendlyExtension\Faker\Provider\Internet + arguments: + - @friendly.faker.generator + tags: + - { name: friendly.faker.provider } + + friendly.faker.provider.person: + class: Knp\FriendlyExtension\Faker\Provider\Person + arguments: + - @friendly.faker.generator + tags: + - { name: friendly.faker.provider } + + friendly.faker.provider.phonenumber: + class: Knp\FriendlyExtension\Faker\Provider\PhoneNumber + arguments: + - @friendly.faker.generator + tags: + - { name: friendly.faker.provider } diff --git a/src/Knp/FriendlyExtension/services/guesser.yml b/src/Knp/FriendlyExtension/services/guesser.yml new file mode 100644 index 00000000..549eac29 --- /dev/null +++ b/src/Knp/FriendlyExtension/services/guesser.yml @@ -0,0 +1,44 @@ +services: + + friendly.type.guesser_registry: + class: Knp\FriendlyExtension\Type\GuesserRegistry + + friendly.type.guesser.bigint_guesser: + class: Knp\FriendlyExtension\Type\Guesser\BigintGuesser + tags: + - { name: friendly.type.guesser } + + friendly.type.guesser.boolean_guesser: + class: Knp\FriendlyExtension\Type\Guesser\BooleanGuesser + tags: + - { name: friendly.type.guesser } + + friendly.type.guesser.datetime_guesser: + class: Knp\FriendlyExtension\Type\Guesser\DatetimeGuesser + tags: + - { name: friendly.type.guesser } + + friendly.type.guesser.decimal_guesser: + class: Knp\FriendlyExtension\Type\Guesser\DecimalGuesser + tags: + - { name: friendly.type.guesser } + + friendly.type.guesser.entity_guesser: + class: Knp\FriendlyExtension\Type\Guesser\EntityGuesser + tags: + - { name: friendly.type.guesser } + + friendly.type.guesser.int_guesser: + class: Knp\FriendlyExtension\Type\Guesser\IntGuesser + tags: + - { name: friendly.type.guesser } + + friendly.type.guesser.smallint_guesser: + class: Knp\FriendlyExtension\Type\Guesser\SmallintGuesser + tags: + - { name: friendly.type.guesser } + + friendly.type.guesser.string_guesser: + class: Knp\FriendlyExtension\Type\Guesser\StringGuesser + tags: + - { name: friendly.type.guesser } diff --git a/src/Knp/FriendlyExtension/services/services.yml b/src/Knp/FriendlyExtension/services/services.yml new file mode 100644 index 00000000..2b87b625 --- /dev/null +++ b/src/Knp/FriendlyExtension/services/services.yml @@ -0,0 +1 @@ +services: ~ diff --git a/src/Knp/FriendlyExtension/services/symfony.yml b/src/Knp/FriendlyExtension/services/symfony.yml new file mode 100644 index 00000000..997028d4 --- /dev/null +++ b/src/Knp/FriendlyExtension/services/symfony.yml @@ -0,0 +1,18 @@ +services: + + friendly.symfony.service_shifter: + class: Knp\FriendlyExtension\Symfony\ServiceShifter + arguments: + - @service_container + + doctrine: + class: Doctrine\ORM\Registry + factoryService: friendly.symfony.service_shifter + factoryMethod: get + arguments: [ doctrine ] + + doctrine.orm.entity_manager: + class: Doctrine\ORM\RegistryInterface + factoryService: friendly.symfony.service_shifter + factoryMethod: get + arguments: [ doctrine.orm.entity_manager ] From ee907d13932b1636c698302d10305bd8ca2fdfc7 Mon Sep 17 00:00:00 2001 From: Pierre PLAZANET Date: Wed, 16 Jul 2014 11:34:50 +0200 Subject: [PATCH 04/33] WIP --- .gitignore | 0 .travis.yml | 0 LICENSE | 0 README.md | 0 behat.yml.dist | 0 composer.json | 6 +- devnull | 4 + doc/configuration.md | 0 doc/context-alice.md | 0 doc/context-api.md | 0 doc/context-entity.md | 0 doc/context-mink.md | 0 doc/context-page.md | 0 doc/context-table.md | 0 doc/feature-smartStep.md | 0 phpspec.yml | 1 - .../Builder/DeleteRequestBuilderSpec.php | 63 --------- .../Builder/GetRequestBuilderSpec.php | 39 ------ .../Builder/HeadRequestBuilderSpec.php | 41 ------ .../Builder/OptionsRequestBuilderSpec.php | 40 ------ .../Builder/PatchRequestBuilderSpec.php | 63 --------- .../Builder/PostRequestBuilderSpec.php | 42 ------ .../Builder/PutRequestBuilderSpec.php | 63 --------- .../Builder/RequestBuilderSpec.php | 95 ------------- .../Context/AliceContextSpec.php | 96 ------------- .../Context/ApiContextSpec.php | 19 --- .../Context/EntityContextSpec.php | 79 ----------- .../Initializer/FriendlyInitializerSpec.php | 34 ----- .../Context/MinkContextSpec.php | 14 -- .../Context/PageContextSpec.php | 19 --- .../Context/RawPageContextSpec.php | 61 --------- .../Context/TableContextSpec.php | 14 -- .../Compiler/ConfigPassSpec.php | 41 ------ .../Compiler/FakerProviderPassSpec.php | 43 ------ .../Compiler/FormatGuesserPassSpec.php | 59 -------- .../Compiler/KernelPassSpec.php | 14 -- .../Doctrine/EntityHydratorSpec.php | 25 ---- .../Doctrine/EntityResolverSpec.php | 69 ---------- spec/Knp/FriendlyContexts/ExtensionSpec.php | 14 -- .../Faker/Provider/AddressSpec.php | 42 ------ .../Faker/Provider/ColorSpec.php | 42 ------ .../Faker/Provider/CompanySpec.php | 42 ------ .../Faker/Provider/DateTimeSpec.php | 42 ------ .../Faker/Provider/FileSpec.php | 42 ------ .../Faker/Provider/InternetSpec.php | 42 ------ .../Faker/Provider/LoremSpec.php | 42 ------ .../Faker/Provider/MiscellaneousSpec.php | 42 ------ .../Faker/Provider/PaymentSpec.php | 42 ------ .../Faker/Provider/PersonSpec.php | 42 ------ .../Faker/Provider/PhoneNumberSpec.php | 42 ------ .../Faker/Provider/UserAgentSpec.php | 42 ------ .../Faker/Provider/UuidSpec.php | 42 ------ .../Guesser/BigintGuesserSpec.php | 53 ------- .../Guesser/BooleanGuesserSpec.php | 57 -------- .../Guesser/DatetimeGuesserSpec.php | 93 ------------- .../Guesser/DecimalGuesserSpec.php | 67 --------- .../Guesser/EntityGuesserSpec.php | 102 -------------- .../Guesser/GuesserManagerSpec.php | 77 ----------- .../Guesser/IntGuesserSpec.php | 53 ------- .../Guesser/SmallintGuesserSpec.php | 53 ------- .../Guesser/StringGuesserSpec.php | 52 ------- .../Http/Factory/OauthPluginFactorySpec.php | 19 --- .../Http/HttpContentTypeGuesserSpec.php | 32 ----- .../Http/Security/HttpBasicExtensionSpec.php | 51 ------- .../Http/Security/OauthExtensionSpec.php | 50 ------- .../Node/FeatureWalkerSpec.php | 55 -------- spec/Knp/FriendlyContexts/Page/PageSpec.php | 34 ----- .../Page/Resolver/PageClassResolverSpec.php | 57 -------- .../Reader/SmartReaderSpec.php | 24 ---- .../Record/Collection/BagSpec.php | 59 -------- .../Record/CollectionSpec.php | 83 ----------- .../FriendlyContexts/Record/RecordSpec.php | 114 ---------------- .../Reflection/ObjectReflectorSpec.php | 40 ------ .../FriendlyContexts/Utils/AsserterSpec.php | 95 ------------- .../Utils/TextFormaterSpec.php | 43 ------ .../Utils/UniqueCacheSpec.php | 31 ----- .../Utils/NameProposerSpec.php | 27 ++++ spec/Knp/FriendlyExtensionSpec.php | 14 ++ .../FriendlyContexts/Alice/Loader/Yaml.php | 0 .../Builder/AbstractRequestBuilder.php | 0 .../Builder/DeleteRequestBuilder.php | 0 .../Builder/GetRequestBuilder.php | 0 .../Builder/HeadRequestBuilder.php | 0 .../Builder/OptionsRequestBuilder.php | 0 .../Builder/PatchRequestBuilder.php | 0 .../Builder/PostRequestBuilder.php | 0 .../Builder/PutRequestBuilder.php | 0 .../Builder/RequestBuilder.php | 0 .../Builder/RequestBuilderInterface.php | 0 src/Knp/FriendlyContexts/Call/CallCenter.php | 0 .../FriendlyContexts/Context/AliceContext.php | 0 .../FriendlyContexts/Context/ApiContext.php | 0 src/Knp/FriendlyContexts/Context/Context.php | 0 .../Context/EntityContext.php | 0 .../Initializer/FriendlyInitializer.php | 0 .../FriendlyContexts/Context/MinkContext.php | 0 .../FriendlyContexts/Context/PageContext.php | 0 .../Context/RawMinkContext.php | 0 .../Context/RawPageContext.php | 0 .../FriendlyContexts/Context/TableContext.php | 0 .../Definition/DefinitionFinder.php | 0 .../Compiler/ApiUrlPass.php | 0 .../Compiler/ConfigPass.php | 0 .../Compiler/FakerProviderPass.php | 0 .../Compiler/FormatGuesserPass.php | 0 .../Compiler/KernelPass.php | 0 .../Dictionary/Backgroundable.php | 0 .../FriendlyContexts/Dictionary/Taggable.php | 0 .../Doctrine/EntityHydrator.php | 0 .../Doctrine/EntityResolver.php | 0 src/Knp/FriendlyContexts/Extension.php | 0 .../Faker/Provider/Address.php | 0 .../FriendlyContexts/Faker/Provider/Base.php | 0 .../FriendlyContexts/Faker/Provider/Color.php | 0 .../Faker/Provider/Company.php | 0 .../Faker/Provider/DateTime.php | 0 .../FriendlyContexts/Faker/Provider/File.php | 0 .../Faker/Provider/Internet.php | 0 .../FriendlyContexts/Faker/Provider/Lorem.php | 0 .../Faker/Provider/Miscellaneous.php | 0 .../Faker/Provider/Payment.php | 0 .../Faker/Provider/Person.php | 0 .../Faker/Provider/PhoneNumber.php | 0 .../Faker/Provider/UserAgent.php | 0 .../FriendlyContexts/Faker/Provider/Uuid.php | 0 .../Guesser/AbstractGuesser.php | 0 .../Guesser/BigintGuesser.php | 0 .../Guesser/BooleanGuesser.php | 0 .../Guesser/DatetimeGuesser.php | 0 .../Guesser/DecimalGuesser.php | 0 .../Guesser/EntityGuesser.php | 0 .../Guesser/GuesserInterface.php | 0 .../Guesser/GuesserManager.php | 0 .../FriendlyContexts/Guesser/IntGuesser.php | 0 .../Guesser/SmallintGuesser.php | 0 .../Guesser/StringGuesser.php | 0 .../Http/Factory/OauthPluginFactory.php | 0 .../Http/HttpContentTypeGuesser.php | 0 .../Http/Security/HttpBasicExtension.php | 0 .../Http/Security/OauthExtension.php | 0 .../Security/SecurityExtensionInterface.php | 0 .../FriendlyContexts/Node/FeatureWalker.php | 0 src/Knp/FriendlyContexts/Page/Page.php | 0 .../Page/Resolver/PageClassResolver.php | 0 .../FriendlyContexts/Reader/SmartReader.php | 0 .../FriendlyContexts/Record/Collection.php | 0 .../Record/Collection/Bag.php | 0 src/Knp/FriendlyContexts/Record/Record.php | 0 .../Reflection/ObjectReflector.php | 0 .../Request/RequestMethods.php | 0 src/Knp/FriendlyContexts/Utils/Asserter.php | 0 .../FriendlyContexts/Utils/TextFormater.php | 0 .../FriendlyContexts/Utils/UniqueCache.php | 0 src/Knp/FriendlyContexts/services/builder.yml | 0 src/Knp/FriendlyContexts/services/core.yml | 0 src/Knp/FriendlyContexts/services/fakers.yml | 0 .../FriendlyContexts/services/guessers.yml | 0 src/Knp/FriendlyExtension.php | 0 .../Context/Helper/AsserterHelper.php | 0 .../Context/Helper/DoctrineHelper.php | 44 ++++++ .../Context/Helper/EntityHelper.php | 20 +++ .../Context/Helper/HelperInterface.php | 0 .../Compiler/ApiUrlTransitionPass.php | 0 .../Compiler/FakerGuesserRegistrationPass.php | 0 .../FakerProviderRegistrationPass.php | 0 .../Compiler/KernelRegistrationPass.php | 0 .../Compiler/ParameterBuildingPass.php | 0 .../FriendlyExtension/Doctrine/Resolver.php | 0 src/Knp/FriendlyExtension/Entity/Hydrator.php | 129 ++++++++++++++++++ src/Knp/FriendlyExtension/Entity/Resolver.php | 93 +++++++++++++ .../Faker/Provider/Address.php | 0 .../FriendlyExtension/Faker/Provider/Base.php | 0 .../Faker/Provider/DateTime.php | 0 .../Faker/Provider/Internet.php | 0 .../Faker/Provider/Person.php | 0 .../Faker/Provider/PhoneNumber.php | 0 .../FriendlyExtension/Faker/UniqueCache.php | 55 ++++++++ .../FriendlyExtension/Record/Collection.php | 0 .../Record/Collection/Bag.php | 0 src/Knp/FriendlyExtension/Record/Record.php | 0 .../Symfony/ServiceShifter.php | 0 .../Type/Guesser/AbstractGuesser.php | 0 .../Type/Guesser/BigintGuesser.php | 0 .../Type/Guesser/BooleanGuesser.php | 0 .../Type/Guesser/DatetimeGuesser.php | 0 .../Type/Guesser/DecimalGuesser.php | 0 .../Type/Guesser/EntityGuesser.php | 0 .../Type/Guesser/GuesserInterface.php | 0 .../Type/Guesser/IntGuesser.php | 0 .../Type/Guesser/SmallintGuesser.php | 0 .../Type/Guesser/StringGuesser.php | 0 .../Type/GuesserRegistry.php | 0 .../FriendlyExtension/Utils/NameProposer.php | 6 +- .../Utils/ObjectReflector.php | 0 .../FriendlyExtension/Utils/TextFormater.php | 1 - src/Knp/FriendlyExtension/services/core.yml | 0 src/Knp/FriendlyExtension/services/faker.yml | 0 .../FriendlyExtension/services/guesser.yml | 0 .../FriendlyExtension/services/services.yml | 0 .../FriendlyExtension/services/symfony.yml | 0 200 files changed, 391 insertions(+), 2996 deletions(-) mode change 100644 => 100755 .gitignore mode change 100644 => 100755 .travis.yml mode change 100644 => 100755 LICENSE mode change 100644 => 100755 README.md mode change 100644 => 100755 behat.yml.dist mode change 100644 => 100755 composer.json create mode 100755 devnull mode change 100644 => 100755 doc/configuration.md mode change 100644 => 100755 doc/context-alice.md mode change 100644 => 100755 doc/context-api.md mode change 100644 => 100755 doc/context-entity.md mode change 100644 => 100755 doc/context-mink.md mode change 100644 => 100755 doc/context-page.md mode change 100644 => 100755 doc/context-table.md mode change 100644 => 100755 doc/feature-smartStep.md delete mode 100644 phpspec.yml delete mode 100644 spec/Knp/FriendlyContexts/Builder/DeleteRequestBuilderSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Builder/GetRequestBuilderSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Builder/HeadRequestBuilderSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Builder/OptionsRequestBuilderSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Builder/PatchRequestBuilderSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Builder/PostRequestBuilderSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Builder/PutRequestBuilderSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Builder/RequestBuilderSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Context/AliceContextSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Context/ApiContextSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Context/EntityContextSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Context/Initializer/FriendlyInitializerSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Context/MinkContextSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Context/PageContextSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Context/RawPageContextSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Context/TableContextSpec.php delete mode 100644 spec/Knp/FriendlyContexts/DependencyInjection/Compiler/ConfigPassSpec.php delete mode 100644 spec/Knp/FriendlyContexts/DependencyInjection/Compiler/FakerProviderPassSpec.php delete mode 100644 spec/Knp/FriendlyContexts/DependencyInjection/Compiler/FormatGuesserPassSpec.php delete mode 100644 spec/Knp/FriendlyContexts/DependencyInjection/Compiler/KernelPassSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Doctrine/EntityHydratorSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Doctrine/EntityResolverSpec.php delete mode 100644 spec/Knp/FriendlyContexts/ExtensionSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Faker/Provider/AddressSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Faker/Provider/ColorSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Faker/Provider/CompanySpec.php delete mode 100644 spec/Knp/FriendlyContexts/Faker/Provider/DateTimeSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Faker/Provider/FileSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Faker/Provider/InternetSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Faker/Provider/LoremSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Faker/Provider/MiscellaneousSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Faker/Provider/PaymentSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Faker/Provider/PersonSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Faker/Provider/PhoneNumberSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Faker/Provider/UserAgentSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Faker/Provider/UuidSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Guesser/BigintGuesserSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Guesser/BooleanGuesserSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Guesser/DatetimeGuesserSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Guesser/DecimalGuesserSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Guesser/EntityGuesserSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Guesser/GuesserManagerSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Guesser/IntGuesserSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Guesser/SmallintGuesserSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Guesser/StringGuesserSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Http/Factory/OauthPluginFactorySpec.php delete mode 100644 spec/Knp/FriendlyContexts/Http/HttpContentTypeGuesserSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Http/Security/HttpBasicExtensionSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Http/Security/OauthExtensionSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Node/FeatureWalkerSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Page/PageSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Page/Resolver/PageClassResolverSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Reader/SmartReaderSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Record/Collection/BagSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Record/CollectionSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Record/RecordSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Reflection/ObjectReflectorSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Utils/AsserterSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Utils/TextFormaterSpec.php delete mode 100644 spec/Knp/FriendlyContexts/Utils/UniqueCacheSpec.php create mode 100755 spec/Knp/FriendlyExtension/Utils/NameProposerSpec.php create mode 100755 spec/Knp/FriendlyExtensionSpec.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Alice/Loader/Yaml.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Builder/AbstractRequestBuilder.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Builder/DeleteRequestBuilder.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Builder/GetRequestBuilder.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Builder/HeadRequestBuilder.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Builder/OptionsRequestBuilder.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Builder/PatchRequestBuilder.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Builder/PostRequestBuilder.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Builder/PutRequestBuilder.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Builder/RequestBuilder.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Builder/RequestBuilderInterface.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Call/CallCenter.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Context/AliceContext.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Context/ApiContext.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Context/Context.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Context/EntityContext.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Context/Initializer/FriendlyInitializer.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Context/MinkContext.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Context/PageContext.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Context/RawMinkContext.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Context/RawPageContext.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Context/TableContext.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Definition/DefinitionFinder.php mode change 100644 => 100755 src/Knp/FriendlyContexts/DependencyInjection/Compiler/ApiUrlPass.php mode change 100644 => 100755 src/Knp/FriendlyContexts/DependencyInjection/Compiler/ConfigPass.php mode change 100644 => 100755 src/Knp/FriendlyContexts/DependencyInjection/Compiler/FakerProviderPass.php mode change 100644 => 100755 src/Knp/FriendlyContexts/DependencyInjection/Compiler/FormatGuesserPass.php mode change 100644 => 100755 src/Knp/FriendlyContexts/DependencyInjection/Compiler/KernelPass.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Dictionary/Backgroundable.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Dictionary/Taggable.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Doctrine/EntityHydrator.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Doctrine/EntityResolver.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Extension.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Faker/Provider/Address.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Faker/Provider/Base.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Faker/Provider/Color.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Faker/Provider/Company.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Faker/Provider/DateTime.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Faker/Provider/File.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Faker/Provider/Internet.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Faker/Provider/Lorem.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Faker/Provider/Miscellaneous.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Faker/Provider/Payment.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Faker/Provider/Person.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Faker/Provider/PhoneNumber.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Faker/Provider/UserAgent.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Faker/Provider/Uuid.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Guesser/AbstractGuesser.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Guesser/BigintGuesser.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Guesser/BooleanGuesser.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Guesser/DatetimeGuesser.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Guesser/DecimalGuesser.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Guesser/EntityGuesser.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Guesser/GuesserInterface.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Guesser/GuesserManager.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Guesser/IntGuesser.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Guesser/SmallintGuesser.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Guesser/StringGuesser.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Http/Factory/OauthPluginFactory.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Http/HttpContentTypeGuesser.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Http/Security/HttpBasicExtension.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Http/Security/OauthExtension.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Http/Security/SecurityExtensionInterface.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Node/FeatureWalker.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Page/Page.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Page/Resolver/PageClassResolver.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Reader/SmartReader.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Record/Collection.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Record/Collection/Bag.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Record/Record.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Reflection/ObjectReflector.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Request/RequestMethods.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Utils/Asserter.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Utils/TextFormater.php mode change 100644 => 100755 src/Knp/FriendlyContexts/Utils/UniqueCache.php mode change 100644 => 100755 src/Knp/FriendlyContexts/services/builder.yml mode change 100644 => 100755 src/Knp/FriendlyContexts/services/core.yml mode change 100644 => 100755 src/Knp/FriendlyContexts/services/fakers.yml mode change 100644 => 100755 src/Knp/FriendlyContexts/services/guessers.yml mode change 100644 => 100755 src/Knp/FriendlyExtension.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Context/Helper/AsserterHelper.php create mode 100755 src/Knp/FriendlyExtension/Context/Helper/DoctrineHelper.php create mode 100755 src/Knp/FriendlyExtension/Context/Helper/EntityHelper.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Context/Helper/HelperInterface.php mode change 100644 => 100755 src/Knp/FriendlyExtension/DependencyInjection/Compiler/ApiUrlTransitionPass.php mode change 100644 => 100755 src/Knp/FriendlyExtension/DependencyInjection/Compiler/FakerGuesserRegistrationPass.php mode change 100644 => 100755 src/Knp/FriendlyExtension/DependencyInjection/Compiler/FakerProviderRegistrationPass.php mode change 100644 => 100755 src/Knp/FriendlyExtension/DependencyInjection/Compiler/KernelRegistrationPass.php mode change 100644 => 100755 src/Knp/FriendlyExtension/DependencyInjection/Compiler/ParameterBuildingPass.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Doctrine/Resolver.php create mode 100755 src/Knp/FriendlyExtension/Entity/Hydrator.php create mode 100755 src/Knp/FriendlyExtension/Entity/Resolver.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Faker/Provider/Address.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Faker/Provider/Base.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Faker/Provider/DateTime.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Faker/Provider/Internet.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Faker/Provider/Person.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Faker/Provider/PhoneNumber.php create mode 100755 src/Knp/FriendlyExtension/Faker/UniqueCache.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Record/Collection.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Record/Collection/Bag.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Record/Record.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Symfony/ServiceShifter.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Type/Guesser/AbstractGuesser.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Type/Guesser/BigintGuesser.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Type/Guesser/BooleanGuesser.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Type/Guesser/DatetimeGuesser.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Type/Guesser/DecimalGuesser.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Type/Guesser/EntityGuesser.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Type/Guesser/GuesserInterface.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Type/Guesser/IntGuesser.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Type/Guesser/SmallintGuesser.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Type/Guesser/StringGuesser.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Type/GuesserRegistry.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Utils/NameProposer.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Utils/ObjectReflector.php mode change 100644 => 100755 src/Knp/FriendlyExtension/Utils/TextFormater.php mode change 100644 => 100755 src/Knp/FriendlyExtension/services/core.yml mode change 100644 => 100755 src/Knp/FriendlyExtension/services/faker.yml mode change 100644 => 100755 src/Knp/FriendlyExtension/services/guesser.yml mode change 100644 => 100755 src/Knp/FriendlyExtension/services/services.yml mode change 100644 => 100755 src/Knp/FriendlyExtension/services/symfony.yml diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/.travis.yml b/.travis.yml old mode 100644 new mode 100755 diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/behat.yml.dist b/behat.yml.dist old mode 100644 new mode 100755 diff --git a/composer.json b/composer.json old mode 100644 new mode 100755 index a4bedaba..755ef56e --- a/composer.json +++ b/composer.json @@ -3,7 +3,6 @@ "description": "Some BEHAT contexts", "autoload": { "psr-0": { - "Knp\\FriendlyContexts": "src/", "Knp\\FriendlyExtension": "src/" } }, @@ -18,9 +17,8 @@ "guzzle/guzzle": "~3.7" }, "require-dev": { - "phpspec/phpspec": "2.0.*@dev", - "doctrine/orm": "dev-master", - "knplabs/phpspec-welldone-extension": "dev-master" + "phpspec/phpspec": "~2.0.0", + "doctrine/orm": "dev-master" }, "license": "MIT", "authors": [ diff --git a/devnull b/devnull new file mode 100755 index 00000000..555639ce --- /dev/null +++ b/devnull @@ -0,0 +1,4 @@ +Lecture des listes de paquets… +Construction de l'arbre des dépendances… +Lecture des informations d'état… +0 mis à jour, 0 nouvellement installés, 0 à enlever et 0 non mis à jour. diff --git a/doc/configuration.md b/doc/configuration.md old mode 100644 new mode 100755 diff --git a/doc/context-alice.md b/doc/context-alice.md old mode 100644 new mode 100755 diff --git a/doc/context-api.md b/doc/context-api.md old mode 100644 new mode 100755 diff --git a/doc/context-entity.md b/doc/context-entity.md old mode 100644 new mode 100755 diff --git a/doc/context-mink.md b/doc/context-mink.md old mode 100644 new mode 100755 diff --git a/doc/context-page.md b/doc/context-page.md old mode 100644 new mode 100755 diff --git a/doc/context-table.md b/doc/context-table.md old mode 100644 new mode 100755 diff --git a/doc/feature-smartStep.md b/doc/feature-smartStep.md old mode 100644 new mode 100755 diff --git a/phpspec.yml b/phpspec.yml deleted file mode 100644 index 52de8f13..00000000 --- a/phpspec.yml +++ /dev/null @@ -1 +0,0 @@ -extensions: ~ diff --git a/spec/Knp/FriendlyContexts/Builder/DeleteRequestBuilderSpec.php b/spec/Knp/FriendlyContexts/Builder/DeleteRequestBuilderSpec.php deleted file mode 100644 index 7bbfdd22..00000000 --- a/spec/Knp/FriendlyContexts/Builder/DeleteRequestBuilderSpec.php +++ /dev/null @@ -1,63 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\Builder\DeleteRequestBuilder'); - } - - function it_is_a_request_builder() - { - $this->shouldHaveType('Knp\FriendlyContexts\Builder\RequestBuilderInterface'); - } - - function it_build_a_delete_request(ClientInterface $client, RequestInterface $request) - { - $client->delete( - '/resource?foo=bar', - ['some headers'], - 'body', - ['some options'] - )->shouldBeCalled(1)->willReturn($request); - - $this->setClient($client); - - $this->build( - '/resource', - ['foo' => 'bar'], - ['some headers'], - null, - 'body', - ['some options'] - )->shouldReturn($request); - } - - function it_format_body_to_a_valid_form_urlencod_request(ClientInterface $client, RequestInterface $request) - { - $client->delete( - '/resource?foo=bar', - ['Content-Type' => 'application/x-www-form-urlencoded'], - 'foo=bar&baz=plop', - ['some options'] - )->shouldBeCalled(1)->willReturn($request); - - $this->setClient($client); - - $this->build( - '/resource', - ['foo' => 'bar'], - null, - null, - ['foo' => 'bar', 'baz' => 'plop'], - ['some options'] - )->shouldReturn($request); - } -} diff --git a/spec/Knp/FriendlyContexts/Builder/GetRequestBuilderSpec.php b/spec/Knp/FriendlyContexts/Builder/GetRequestBuilderSpec.php deleted file mode 100644 index de6b32ea..00000000 --- a/spec/Knp/FriendlyContexts/Builder/GetRequestBuilderSpec.php +++ /dev/null @@ -1,39 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\Builder\GetRequestBuilder'); - } - - function it_is_a_request_builder() - { - $this->shouldHaveType('Knp\FriendlyContexts\Builder\RequestBuilderInterface'); - } - - function it_can_not_build_request_without_client() - { - $this->shouldThrow('RuntimeException')->duringBuild(); - } - - function it_build_a_get_request(ClientInterface $client, RequestInterface $request) - { - $client->get( - '/resource?foo=bar&baz=foo', - ['some headers'], - ['some options'] - )->shouldBeCalled(1)->willReturn($request); - - $this->setClient($client); - - $this->build('/resource', ['foo' => 'bar', 'baz' => 'foo'], ['some headers'], null, null, ['some options'])->shouldReturn($request); - } -} diff --git a/spec/Knp/FriendlyContexts/Builder/HeadRequestBuilderSpec.php b/spec/Knp/FriendlyContexts/Builder/HeadRequestBuilderSpec.php deleted file mode 100644 index 432ac6b0..00000000 --- a/spec/Knp/FriendlyContexts/Builder/HeadRequestBuilderSpec.php +++ /dev/null @@ -1,41 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\Builder\HeadRequestBuilder'); - } - - function it_is_a_builder() - { - $this->shouldHaveType('Knp\FriendlyContexts\Builder\RequestBuilderInterface'); - } - - function it_build_a_head_request(ClientInterface $client, RequestInterface $request) - { - $client->head( - '/resource?foo=bar', - ['some headers'], - ['some options'] - )->shouldBeCalled(1)->willReturn($request); - - $this->setClient($client); - - $this->build( - '/resource', - ['foo' => 'bar'], - ['some headers'], - null, - null, - ['some options'] - )->shouldReturn($request); - } -} diff --git a/spec/Knp/FriendlyContexts/Builder/OptionsRequestBuilderSpec.php b/spec/Knp/FriendlyContexts/Builder/OptionsRequestBuilderSpec.php deleted file mode 100644 index bbe919c5..00000000 --- a/spec/Knp/FriendlyContexts/Builder/OptionsRequestBuilderSpec.php +++ /dev/null @@ -1,40 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\Builder\OptionsRequestBuilder'); - } - - function it_is_a_builder() - { - $this->shouldHaveType('Knp\FriendlyContexts\Builder\RequestBuilderInterface'); - } - - function it_build_an_option_request(ClientInterface $client, RequestInterface $request) - { - $client->options( - '/resource?foo=bar', - ['some options'] - )->shouldBeCalled(1)->willReturn($request); - - $this->setClient($client); - - $this->build( - '/resource', - ['foo' => 'bar'], - null, - null, - null, - ['some options'] - )->shouldReturn($request); - } -} diff --git a/spec/Knp/FriendlyContexts/Builder/PatchRequestBuilderSpec.php b/spec/Knp/FriendlyContexts/Builder/PatchRequestBuilderSpec.php deleted file mode 100644 index a44976ad..00000000 --- a/spec/Knp/FriendlyContexts/Builder/PatchRequestBuilderSpec.php +++ /dev/null @@ -1,63 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\Builder\PatchRequestBuilder'); - } - - function it_is_a_request_builder() - { - $this->shouldHaveType('Knp\FriendlyContexts\Builder\RequestBuilderInterface'); - } - - function it_build_a_patch_request(ClientInterface $client, RequestInterface $request) - { - $client->patch( - '/resource?foo=bar', - ['some headers'], - 'body datas', - ['some options'] - )->shouldBeCalled(1)->willReturn($request); - - $this->setClient($client); - - $this->build( - '/resource', - ['foo' => 'bar'], - ['some headers'], - null, - 'body datas', - ['some options'] - )->shouldReturn($request); - } - - function it_format_the_request_to_a_valid_form_urlencode(ClientInterface $client, RequestInterface $request) - { - $client->patch( - '/resource', - ['Content-Type' => 'application/x-www-form-urlencoded'], - 'foo=bar&baz=plop', - ['some options'] - )->shouldBeCalled(1)->willReturn($request); - - $this->setClient($client); - - $this->build( - '/resource', - null, - null, - null, - ['foo' => 'bar', 'baz' => 'plop'], - ['some options'] - )->shouldReturn($request); - } -} diff --git a/spec/Knp/FriendlyContexts/Builder/PostRequestBuilderSpec.php b/spec/Knp/FriendlyContexts/Builder/PostRequestBuilderSpec.php deleted file mode 100644 index bab4ceee..00000000 --- a/spec/Knp/FriendlyContexts/Builder/PostRequestBuilderSpec.php +++ /dev/null @@ -1,42 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\Builder\PostRequestBuilder'); - } - - function it_is_request_builder() - { - $this->shouldHaveType('Knp\FriendlyContexts\Builder\RequestBuilderInterface'); - } - - function it_build_a_post_request(ClientInterface $client, RequestInterface $request) - { - $client->post( - '/resource?foo=bar', - ['some headers'], - ['data' => 'plop'], - ['some options'] - )->shouldBeCalled(1)->willReturn($request); - - $this->setClient($client); - - $this->build( - '/resource', - ['foo' => 'bar'], - ['some headers'], - ['data' => 'plop'], - null, - ['some options'] - )->shouldReturn($request); - } -} diff --git a/spec/Knp/FriendlyContexts/Builder/PutRequestBuilderSpec.php b/spec/Knp/FriendlyContexts/Builder/PutRequestBuilderSpec.php deleted file mode 100644 index f365db56..00000000 --- a/spec/Knp/FriendlyContexts/Builder/PutRequestBuilderSpec.php +++ /dev/null @@ -1,63 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\Builder\PutRequestBuilder'); - } - - function it_is_a_request_builder() - { - $this->shouldHaveType('Knp\FriendlyContexts\Builder\RequestBuilderInterface'); - } - - function it_build_a_put_request(ClientInterface $client, RequestInterface $request) - { - $client->put( - '/resource?foo=bar', - ['some headers'], - 'body datas', - ['some options'] - )->shouldBeCalled(1)->willReturn($request); - - $this->setClient($client); - - $this->build( - '/resource', - ['foo' => 'bar'], - ['some headers'], - null, - 'body datas', - ['some options'] - )->shouldReturn($request); - } - - function it_format_the_request_to_a_valid_form_urlencode(ClientInterface $client, RequestInterface $request) - { - $client->put( - '/resource', - ['Content-Type' => 'application/x-www-form-urlencoded'], - 'foo=bar&baz=plop', - ['some options'] - )->shouldBeCalled(1)->willReturn($request); - - $this->setClient($client); - - $this->build( - '/resource', - null, - null, - null, - ['foo' => 'bar', 'baz' => 'plop'], - ['some options'] - )->shouldReturn($request); - } -} diff --git a/spec/Knp/FriendlyContexts/Builder/RequestBuilderSpec.php b/spec/Knp/FriendlyContexts/Builder/RequestBuilderSpec.php deleted file mode 100644 index 81ae8d59..00000000 --- a/spec/Knp/FriendlyContexts/Builder/RequestBuilderSpec.php +++ /dev/null @@ -1,95 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\Builder\RequestBuilder'); - } - - function it_is_a_request_builder() - { - $this->shouldHaveType('Knp\FriendlyContexts\Builder\RequestBuilderInterface'); - } - - function it_attach_a_request_builder_to_valid_method(RequestBuilderInterface $builder) - { - $this->addRequestBuilder($builder, 'GET'); - - $this->shouldThrow('InvalidArgumentException')->duringAddRequestBuilder($builder, 'INVALID'); - - $this->shouldThrow('RuntimeException')->duringAddRequestBuilder($builder, 'GET'); - } - - function it_contains_a_valid_http_method() - { - $this->setMethod('get'); - - $this->getMethod()->shouldReturn('GET'); - - $this->shouldThrow('InvalidArgumentException')->duringSetMethod('Invalid'); - } - - function it_build_sub_request_builders_and_clean_the_builder( - Client $client, - RequestBuilderInterface $builder, - Request $request, - SecurityExtensionInterface $extension - ) - { - $this->setMethod('GET'); - $this->setUri('/some/resource'); - $this->setQueries(['a' => 'b']); - $this->setHeaders(['foo' => 'bar']); - $this->setPostBody(['baz' => 'bar']); - $this->setBody('body'); - $this->setCookies(['plop' => 'foo']); - $this->setOptions(['some options']); - $this->setCredentials([ - 'username' => 'john', - 'password' => 'johnpass' - ]); - $this->addSecurityExtension($extension); - - $builder->getClient()->shouldBeCalled()->willReturn($client); - - $extension->secureClient($client, $this)->shouldBeCalled(); - $extension->secureRequest($request, $this)->shouldBeCalled(); - - $builder->build( - 'some/resource', - ['a' => 'b'], - ['foo' => 'bar'], - ['baz' => 'bar'], - 'body', - ['some options'] - )->shouldBeCalled(1)->willReturn($request); - - $request->addCookie('plop', 'foo')->shouldBeCalled(1); - - $this->addRequestBuilder($builder, 'GET'); - - $this->build(); - - $this->getMethod()->shouldReturn(null); - $this->getUri()->shouldReturn(null); - $this->getQueries()->shouldReturn(null); - $this->getHeaders()->shouldReturn(null); - $this->getPostBody()->shouldReturn(null); - $this->getBody()->shouldReturn(null); - $this->getCookies()->shouldReturn(null); - $this->getOptions()->shouldReturn([]); - $this->getSecurityExtensions()->shouldReturn([]); - $this->getCredentials()->shouldReturn([]); - } -} diff --git a/spec/Knp/FriendlyContexts/Context/AliceContextSpec.php b/spec/Knp/FriendlyContexts/Context/AliceContextSpec.php deleted file mode 100644 index 8839cd56..00000000 --- a/spec/Knp/FriendlyContexts/Context/AliceContextSpec.php +++ /dev/null @@ -1,96 +0,0 @@ -getManager()->willReturn($manager); - $feature->getTags()->willReturn([ 'alice(Place)', 'admin' ]); - $scenario->getTags()->willReturn([ 'alice(User)' ]); - $event->getFeature()->willReturn($feature); - $event->getScenario()->willReturn($scenario); - $loader->load('user.yml')->willReturn([]); - $loader->load('product.yml')->willReturn([]); - $loader->load('place.yml')->willReturn([]); - $loader->getCache()->willReturn([]); - $loader->clearCache()->willReturn(null); - $fixtures = [ 'User' => 'user.yml', 'Product' => 'product.yml', 'Place' => 'place.yml' ]; - $config = [ 'alice' => [ 'fixtures' => $fixtures, 'dependencies' => [] ]]; - $container->has(Argument::any())->willReturn(true); - $container->hasParameter(Argument::any())->willReturn(true); - $container->get('friendly.alice.loader.yaml')->willReturn($loader); - $container->get('doctrine')->willReturn($doctrine); - $container->getParameter('friendly.alice.fixtures')->willReturn($fixtures); - $container->getParameter('friendly.alice.dependencies')->willReturn([]); - - $this->initialize($config, $container); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Context\AliceContext'); - } - - function it_should_load_specific_fixtures($event, $loader) - { - $loader->load('user.yml')->shouldBeCalled(); - $loader->load('place.yml')->shouldBeCalled(); - $loader->load('product.yml')->shouldNotBeCalled(); - - $this->loadAlice($event); - } - - function it_should_load_all_fixtures($loader, $event, $scenario) - { - $scenario->getTags()->willReturn([ 'alice(*)' ]); - - $loader->load('user.yml')->shouldBeCalled(); - $loader->load('place.yml')->shouldBeCalled(); - $loader->load('product.yml')->shouldBeCalled(); - - $this->loadAlice($event); - } - - function it_should_resolve_deps($container, $loader, $event, $scenario) - { - $scenario->getTags()->willReturn([]); - - $loader->load('user.yml')->shouldBeCalled(); - $loader->load('place.yml')->shouldBeCalled(); - $loader->load('product.yml')->shouldNotBeCalled(); - - $deps = [ 'Place' => [ 'User' ] ]; - $container->getParameter('friendly.alice.dependencies')->willReturn($deps); - - $this->loadAlice($event); - } - - function it_should_not_loop_infinitly($container, $loader, $event, $scenario) - { - - $scenario->getTags()->willReturn([]); - - $loader->load('user.yml')->shouldBeCalled(); - $loader->load('place.yml')->shouldBeCalled(); - $loader->load('product.yml')->shouldNotBeCalled(); - - $deps = [ 'Place' => [ 'User' ], 'User' => [ 'Place' ] ]; - $container->getParameter('friendly.alice.dependencies')->willReturn($deps); - - $this->loadAlice($event); - } -} diff --git a/spec/Knp/FriendlyContexts/Context/ApiContextSpec.php b/spec/Knp/FriendlyContexts/Context/ApiContextSpec.php deleted file mode 100644 index 958c89f3..00000000 --- a/spec/Knp/FriendlyContexts/Context/ApiContextSpec.php +++ /dev/null @@ -1,19 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\Context\ApiContext'); - } - - function it_is_a_context() - { - $this->shouldHaveType('Knp\FriendlyContexts\Context\Context'); - } -} diff --git a/spec/Knp/FriendlyContexts/Context/EntityContextSpec.php b/spec/Knp/FriendlyContexts/Context/EntityContextSpec.php deleted file mode 100644 index ff8b758a..00000000 --- a/spec/Knp/FriendlyContexts/Context/EntityContextSpec.php +++ /dev/null @@ -1,79 +0,0 @@ -getManager()->willReturn($manager); - $manager->getRepository(Argument::any())->willReturn($repository); - $repository->createQueryBuilder(Argument::any())->willReturn($queryBuilder); - $queryBuilder->getQuery()->willReturn($query); - $queryBuilder->resetDQLParts()->willReturn($queryBuilder); - $queryBuilder->select('o')->willReturn($queryBuilder); - $queryBuilder->from(Argument::cetera())->willReturn($queryBuilder); - $query->getResult()->willReturn([$entity1, $entity2, $entity3]); - $resolver->resolve($manager, 'entities', Argument::cetera())->willReturn([$reflectionClass]); - $bag->getCollection(Argument::any())->willReturn($collection); - $collection->all()->willReturn([$record1, $record2]); - $collection->attach(Argument::cetera())->willReturn(null); - $record1->getEntity()->willReturn($entity1); - $record2->getEntity()->willReturn($entity2); - - $container->has(Argument::any())->willReturn(true); - $container->get('doctrine')->willReturn($doctrine); - $container->get('friendly.entity.resolver')->willReturn($resolver); - $container->get('friendly.entity.resolver')->willReturn($resolver); - $container->get('friendly.record.bag')->willReturn($bag); - $container->get('friendly.asserter')->willReturn(new Asserter(new TextFormater)); - $container->hasParameter('friendly.entities.namespaces')->willReturn(true); - $container->getParameter('friendly.entities.namespaces')->willReturn([]); - - $this->initialize([], $container); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Context\EntityContext'); - } - - function it_should_assert_a_deletion() - { - $this->entitiesShouldHaveBeen('no', 'entities', 'deleted')->shouldReturn(null); - $this->shouldThrow(new \Exception('2 entities should have been deleted, 0 actually', 1))->duringEntitiesShouldHaveBeen('2', 'entities', 'deleted'); - } - - function it_should_assert_a_creation($collection, $entity3) - { - $collection->attach('e1')->shouldNotBeCalled(); - $collection->attach('e2')->shouldNotBeCalled(); - $collection->attach('e3')->shouldBeCalled(); - - $this->entitiesShouldHaveBeen('1', 'entities', 'created')->shouldReturn(null); - $this->shouldThrow(new \Exception('0 entities should have been created, 1 actually', 1))->duringEntitiesShouldHaveBeen('no', 'entities', 'created'); - } -} diff --git a/spec/Knp/FriendlyContexts/Context/Initializer/FriendlyInitializerSpec.php b/spec/Knp/FriendlyContexts/Context/Initializer/FriendlyInitializerSpec.php deleted file mode 100644 index f12764db..00000000 --- a/spec/Knp/FriendlyContexts/Context/Initializer/FriendlyInitializerSpec.php +++ /dev/null @@ -1,34 +0,0 @@ -beConstructedWith([], $container); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Context\Initializer\FriendlyInitializer'); - } - - function it_should_supports_contexts($context1) - { - $this->supports($context1)->shouldReturn(true); - } - - function it_should_not_supports_non_contexts($constext2) - { - $this->supports($constext2)->shouldReturn(false); - } -} diff --git a/spec/Knp/FriendlyContexts/Context/MinkContextSpec.php b/spec/Knp/FriendlyContexts/Context/MinkContextSpec.php deleted file mode 100644 index 47cb5d48..00000000 --- a/spec/Knp/FriendlyContexts/Context/MinkContextSpec.php +++ /dev/null @@ -1,14 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\Context\MinkContext'); - } -} diff --git a/spec/Knp/FriendlyContexts/Context/PageContextSpec.php b/spec/Knp/FriendlyContexts/Context/PageContextSpec.php deleted file mode 100644 index 264a221f..00000000 --- a/spec/Knp/FriendlyContexts/Context/PageContextSpec.php +++ /dev/null @@ -1,19 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\Context\PageContext'); - } - - function it_is_a_raw_page_context() - { - $this->shouldHaveType('Knp\FriendlyContexts\Context\RawPageContext'); - } -} diff --git a/spec/Knp/FriendlyContexts/Context/RawPageContextSpec.php b/spec/Knp/FriendlyContexts/Context/RawPageContextSpec.php deleted file mode 100644 index 82662e34..00000000 --- a/spec/Knp/FriendlyContexts/Context/RawPageContextSpec.php +++ /dev/null @@ -1,61 +0,0 @@ -get('friendly.page.resolver')->willReturn($pageResolver); - $container->has('friendly.page.resolver')->willReturn(true); - - $this->initialize([ - 'page' => [ - 'namespace' => 'Page\Namespace' - ] - ], $container); - - $mink->getSession(Argument::cetera())->willReturn($session); - - $this->setMink($mink); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Context\RawPageContext'); - } - - function it_is_a_mink_context() - { - $this->shouldHaveType('Behat\MinkExtension\Context\MinkAwareContext'); - } - - /** - * @param Knp\FriendlyContexts\Page\Page $page - */ - function it_retrieve_page($container, $pageResolver, $session, $page) - { - $container->get('friendly.page.resolver')->shouldBeCalled(1); - $pageResolver - ->create($session, 'Page\Namespace\SomePage') - ->shouldBeCalled(1) - ->willReturn($page) - ; - $pageResolver - ->resolveName('some') - ->shouldBeCalled(1) - ->willReturn('Page\Namespace\SomePage') - ; - - $this->getPage('some')->shouldReturn($page); - } -} diff --git a/spec/Knp/FriendlyContexts/Context/TableContextSpec.php b/spec/Knp/FriendlyContexts/Context/TableContextSpec.php deleted file mode 100644 index 91676be3..00000000 --- a/spec/Knp/FriendlyContexts/Context/TableContextSpec.php +++ /dev/null @@ -1,14 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\Context\TableContext'); - } -} diff --git a/spec/Knp/FriendlyContexts/DependencyInjection/Compiler/ConfigPassSpec.php b/spec/Knp/FriendlyContexts/DependencyInjection/Compiler/ConfigPassSpec.php deleted file mode 100644 index ff82ef3d..00000000 --- a/spec/Knp/FriendlyContexts/DependencyInjection/Compiler/ConfigPassSpec.php +++ /dev/null @@ -1,41 +0,0 @@ -setParameter(Argument::cetera())->willReturn(null); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\DependencyInjection\Compiler\ConfigPass'); - } - - function it_should_load_all_parameters($container) - { - $config = [ - 'p1' => 'test', - 'p2' => [ - 'p3' => 'toto', - 'p4' => 'tata', - ], - ]; - $container->getParameter('friendly.parameters')->willReturn($config); - - $container->setParameter('friendly.p1', 'test')->shouldBeCalled(); - $container->setParameter('friendly.p2', [ 'p3' => 'toto', 'p4' => 'tata'])->shouldBeCalled(); - $container->setParameter('friendly.p2.p3', 'toto')->shouldBeCalled(); - $container->setParameter('friendly.p2.p4', 'tata')->shouldBeCalled(); - - $this->process($container); - } -} diff --git a/spec/Knp/FriendlyContexts/DependencyInjection/Compiler/FakerProviderPassSpec.php b/spec/Knp/FriendlyContexts/DependencyInjection/Compiler/FakerProviderPassSpec.php deleted file mode 100644 index fc0d3281..00000000 --- a/spec/Knp/FriendlyContexts/DependencyInjection/Compiler/FakerProviderPassSpec.php +++ /dev/null @@ -1,43 +0,0 @@ - null, - 'friendly.faker.provider.int' => null, - 'friendly.faker.provider.boolean' => null, - ]; - - $container->findTaggedServiceIds('friendly.faker.provider')->willReturn($services); - $container->getDefinition('friendly.faker.provider.string')->willReturn($string); - $container->getDefinition('friendly.faker.provider.int')->willReturn($int); - $container->getDefinition('friendly.faker.provider.boolean')->willReturn($boolean); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\DependencyInjection\Compiler\FakerProviderPass'); - } - - function it_should_initialize_providers($container, $string, $int, $boolean) - { - $this->process($container)->shouldReturn(null); - - $string->addMethodCall('initialise')->shouldBeCalled(); - $int->addMethodCall('initialise')->shouldBeCalled(); - $boolean->addMethodCall('initialise')->shouldBeCalled(); - } -} diff --git a/spec/Knp/FriendlyContexts/DependencyInjection/Compiler/FormatGuesserPassSpec.php b/spec/Knp/FriendlyContexts/DependencyInjection/Compiler/FormatGuesserPassSpec.php deleted file mode 100644 index 19aadc7a..00000000 --- a/spec/Knp/FriendlyContexts/DependencyInjection/Compiler/FormatGuesserPassSpec.php +++ /dev/null @@ -1,59 +0,0 @@ - null, - 'friendly.guesser.int' => null, - 'friendly.guesser.boolean' => null, - ]; - - $stringFaker = [ - 'friendly.faker.provider.address' => null, - 'friendly.faker.provider.person' => null, - 'friendly.faker.provider.internet' => null, - ]; - - $intFaker = [ - 'friendly.faker.provider.payment' => null, - ]; - - $container->findTaggedServiceIds('friendly.format.guesser')->willReturn($services); - $container->findTaggedServiceIds('friendly.guesser.string.faker')->willReturn($stringFaker); - $container->findTaggedServiceIds('friendly.guesser.int.faker')->willReturn($intFaker); - $container->findTaggedServiceIds('friendly.guesser.boolean.faker')->willReturn([]); - $container->getDefinition('friendly.guesser.manager')->willReturn($manager); - $container->getDefinition('friendly.guesser.string')->willReturn($string); - $container->getDefinition('friendly.guesser.int')->willReturn($int); - $container->getDefinition('friendly.guesser.boolean')->willReturn($boolean); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\DependencyInjection\Compiler\FormatGuesserPass'); - } - - function it_should_initialize_providers($container, $manager, $string, $int, $boolean) - { - $manager->addMethodCall('addGuesser', Argument::any())->shouldBeCalled(); - $string->addMethodCall('addFaker', Argument::any())->shouldBeCalled(); - $int->addMethodCall('addFaker', Argument::any())->shouldBeCalled(); - $boolean->addMethodCall('addFaker', Argument::any())->shouldNotBeCalled(); - - $this->process($container)->shouldReturn(null); - } -} diff --git a/spec/Knp/FriendlyContexts/DependencyInjection/Compiler/KernelPassSpec.php b/spec/Knp/FriendlyContexts/DependencyInjection/Compiler/KernelPassSpec.php deleted file mode 100644 index 29dc68d5..00000000 --- a/spec/Knp/FriendlyContexts/DependencyInjection/Compiler/KernelPassSpec.php +++ /dev/null @@ -1,14 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\DependencyInjection\Compiler\KernelPass'); - } -} diff --git a/spec/Knp/FriendlyContexts/Doctrine/EntityHydratorSpec.php b/spec/Knp/FriendlyContexts/Doctrine/EntityHydratorSpec.php deleted file mode 100644 index e902c2be..00000000 --- a/spec/Knp/FriendlyContexts/Doctrine/EntityHydratorSpec.php +++ /dev/null @@ -1,25 +0,0 @@ -beConstructedWith($formater, $manager, $resolver, $uniqueCache); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Doctrine\EntityHydrator'); - } -} diff --git a/spec/Knp/FriendlyContexts/Doctrine/EntityResolverSpec.php b/spec/Knp/FriendlyContexts/Doctrine/EntityResolverSpec.php deleted file mode 100644 index 57969453..00000000 --- a/spec/Knp/FriendlyContexts/Doctrine/EntityResolverSpec.php +++ /dev/null @@ -1,69 +0,0 @@ -getShortName()->willReturn('User'); - $class1->getNamespaceName()->willReturn('N1/Namespace'); - $class2->getShortName()->willReturn('User'); - $class2->getNamespaceName()->willReturn('N2/Namespace'); - $class3->getShortName()->willReturn('Users'); - $class3->getNamespaceName()->willReturn('N1/Namespace'); - $class4->getShortName()->willReturn('Company'); - $class4->getNamespaceName()->willReturn('N1/Namespace'); - - $em->getMetadataFactory()->willReturn($factory); - $factory->getAllMetadata()->willReturn([]); - $reflector->getReflectionsFromMetadata(Argument::any())->willReturn([$class1, $class2, $class3, $class4]); - - $this->beConstructedWith($reflector, $formater); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Doctrine\EntityResolver'); - } - - function it_should_provide_one_value_for_a_singular_name() - { - $this->entityNameProposal('the name')->shouldReturn(['thename', 'thenames']); - } - - function it_should_provide_two_values_for_a_plural_name() - { - $this->entityNameProposal('the names')->shouldReturn(['thename', 'thenames']); - } - - function it_should_provide_three_values_for_a_ies_name() - { - $this->entityNameProposal('the categories')->shouldReturn(['thecategory', 'thecategories']); - } - - function it_should_return_multiple_class($em, \ReflectionClass $class1, \ReflectionClass $class2, \ReflectionClass $class3, \ReflectionClass $class4) - { - $this->resolve($em, 'user', '')->shouldReturn([$class1, $class2, $class3]); - $this->resolve($em, 'companies', '')->shouldReturn([$class4]); - } - - function it_should_return_class_when_namespace_is_specified($em, \ReflectionClass $class1, \ReflectionClass $class2, \ReflectionClass $class3) - { - $this->resolve($em, 'user', 'N1')->shouldreturn([$class1, $class3]); - $this->resolve($em, 'user', 'N2')->shouldreturn([$class2]); - } -} diff --git a/spec/Knp/FriendlyContexts/ExtensionSpec.php b/spec/Knp/FriendlyContexts/ExtensionSpec.php deleted file mode 100644 index 991346d6..00000000 --- a/spec/Knp/FriendlyContexts/ExtensionSpec.php +++ /dev/null @@ -1,14 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\Extension'); - } -} diff --git a/spec/Knp/FriendlyContexts/Faker/Provider/AddressSpec.php b/spec/Knp/FriendlyContexts/Faker/Provider/AddressSpec.php deleted file mode 100644 index 628bb271..00000000 --- a/spec/Knp/FriendlyContexts/Faker/Provider/AddressSpec.php +++ /dev/null @@ -1,42 +0,0 @@ -beConstructedWith($generator); - $this->setParent($address); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Faker\Provider\Address'); - } - - function it_should_return_parent_provider($address) - { - $this->getParent()->shouldReturn($address); - } - - function it_should_supports_Address_original_provider($address) - { - $this->supportsParent($address)->shouldReturn(true); - } - - /** - * @param Faker\Provider\Person $person - **/ - function it_should_not_supports_non_Address_original_provider($person) - { - $this->supportsParent($person)->shouldReturn(false); - } -} diff --git a/spec/Knp/FriendlyContexts/Faker/Provider/ColorSpec.php b/spec/Knp/FriendlyContexts/Faker/Provider/ColorSpec.php deleted file mode 100644 index 2be2c9d2..00000000 --- a/spec/Knp/FriendlyContexts/Faker/Provider/ColorSpec.php +++ /dev/null @@ -1,42 +0,0 @@ -beConstructedWith($generator); - $this->setParent($color); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Faker\Provider\Color'); - } - - function it_should_return_parent_provider($color) - { - $this->getParent()->shouldReturn($color); - } - - function it_should_supports_Color_original_provider($color) - { - $this->supportsParent($color)->shouldReturn(true); - } - - /** - * @param Faker\Provider\Person $person - **/ - function it_should_not_supports_non_Color_original_provider($person) - { - $this->supportsParent($person)->shouldReturn(false); - } -} diff --git a/spec/Knp/FriendlyContexts/Faker/Provider/CompanySpec.php b/spec/Knp/FriendlyContexts/Faker/Provider/CompanySpec.php deleted file mode 100644 index 1465dee3..00000000 --- a/spec/Knp/FriendlyContexts/Faker/Provider/CompanySpec.php +++ /dev/null @@ -1,42 +0,0 @@ -beConstructedWith($generator); - $this->setParent($company); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Faker\Provider\Company'); - } - - function it_should_return_parent_provider($company) - { - $this->getParent()->shouldReturn($company); - } - - function it_should_supports_Company_original_provider($company) - { - $this->supportsParent($company)->shouldReturn(true); - } - - /** - * @param Faker\Provider\Person $person - **/ - function it_should_not_supports_non_Company_original_provider($person) - { - $this->supportsParent($person)->shouldReturn(false); - } -} diff --git a/spec/Knp/FriendlyContexts/Faker/Provider/DateTimeSpec.php b/spec/Knp/FriendlyContexts/Faker/Provider/DateTimeSpec.php deleted file mode 100644 index 4751e621..00000000 --- a/spec/Knp/FriendlyContexts/Faker/Provider/DateTimeSpec.php +++ /dev/null @@ -1,42 +0,0 @@ -beConstructedWith($generator); - $this->setParent($datetime); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Faker\Provider\DateTime'); - } - - function it_should_return_parent_provider($datetime) - { - $this->getParent()->shouldReturn($datetime); - } - - function it_should_supports_DateTime_original_provider($datetime) - { - $this->supportsParent($datetime)->shouldReturn(true); - } - - /** - * @param Faker\Provider\Person $person - **/ - function it_should_not_supports_non_DateTime_original_provider($person) - { - $this->supportsParent($person)->shouldReturn(false); - } -} diff --git a/spec/Knp/FriendlyContexts/Faker/Provider/FileSpec.php b/spec/Knp/FriendlyContexts/Faker/Provider/FileSpec.php deleted file mode 100644 index fe077341..00000000 --- a/spec/Knp/FriendlyContexts/Faker/Provider/FileSpec.php +++ /dev/null @@ -1,42 +0,0 @@ -beConstructedWith($generator); - $this->setParent($file); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Faker\Provider\File'); - } - - function it_should_return_parent_provider($file) - { - $this->getParent()->shouldReturn($file); - } - - function it_should_supports_File_original_provider($file) - { - $this->supportsParent($file)->shouldReturn(true); - } - - /** - * @param Faker\Provider\Person $person - **/ - function it_should_not_supports_non_File_original_provider($person) - { - $this->supportsParent($person)->shouldReturn(false); - } -} diff --git a/spec/Knp/FriendlyContexts/Faker/Provider/InternetSpec.php b/spec/Knp/FriendlyContexts/Faker/Provider/InternetSpec.php deleted file mode 100644 index a48a984e..00000000 --- a/spec/Knp/FriendlyContexts/Faker/Provider/InternetSpec.php +++ /dev/null @@ -1,42 +0,0 @@ -beConstructedWith($generator); - $this->setParent($internet); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Faker\Provider\Internet'); - } - - function it_should_return_parent_provider($internet) - { - $this->getParent()->shouldReturn($internet); - } - - function it_should_supports_Internet_original_provider($internet) - { - $this->supportsParent($internet)->shouldReturn(true); - } - - /** - * @param Faker\Provider\Person $person - **/ - function it_should_not_supports_non_Internet_original_provider($person) - { - $this->supportsParent($person)->shouldReturn(false); - } -} diff --git a/spec/Knp/FriendlyContexts/Faker/Provider/LoremSpec.php b/spec/Knp/FriendlyContexts/Faker/Provider/LoremSpec.php deleted file mode 100644 index 7ccee14e..00000000 --- a/spec/Knp/FriendlyContexts/Faker/Provider/LoremSpec.php +++ /dev/null @@ -1,42 +0,0 @@ -beConstructedWith($generator); - $this->setParent($lorem); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Faker\Provider\Lorem'); - } - - function it_should_return_parent_provider($lorem) - { - $this->getParent()->shouldReturn($lorem); - } - - function it_should_supports_Lorem_original_provider($lorem) - { - $this->supportsParent($lorem)->shouldReturn(true); - } - - /** - * @param Faker\Provider\Person $person - **/ - function it_should_not_supports_non_Lorem_original_provider($person) - { - $this->supportsParent($person)->shouldReturn(false); - } -} diff --git a/spec/Knp/FriendlyContexts/Faker/Provider/MiscellaneousSpec.php b/spec/Knp/FriendlyContexts/Faker/Provider/MiscellaneousSpec.php deleted file mode 100644 index 26c34e2b..00000000 --- a/spec/Knp/FriendlyContexts/Faker/Provider/MiscellaneousSpec.php +++ /dev/null @@ -1,42 +0,0 @@ -beConstructedWith($generator); - $this->setParent($miscellaneous); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Faker\Provider\Miscellaneous'); - } - - function it_should_return_parent_provider($miscellaneous) - { - $this->getParent()->shouldReturn($miscellaneous); - } - - function it_should_supports_Miscellaneous_original_provider($miscellaneous) - { - $this->supportsParent($miscellaneous)->shouldReturn(true); - } - - /** - * @param Faker\Provider\Person $person - **/ - function it_should_not_supports_non_Miscellaneous_original_provider($person) - { - $this->supportsParent($person)->shouldReturn(false); - } -} diff --git a/spec/Knp/FriendlyContexts/Faker/Provider/PaymentSpec.php b/spec/Knp/FriendlyContexts/Faker/Provider/PaymentSpec.php deleted file mode 100644 index 105ca1d2..00000000 --- a/spec/Knp/FriendlyContexts/Faker/Provider/PaymentSpec.php +++ /dev/null @@ -1,42 +0,0 @@ -beConstructedWith($generator); - $this->setParent($payment); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Faker\Provider\Payment'); - } - - function it_should_return_parent_provider($payment) - { - $this->getParent()->shouldReturn($payment); - } - - function it_should_supports_Payment_original_provider($payment) - { - $this->supportsParent($payment)->shouldReturn(true); - } - - /** - * @param Faker\Provider\Person $person - **/ - function it_should_not_supports_non_Payment_original_provider($person) - { - $this->supportsParent($person)->shouldReturn(false); - } -} diff --git a/spec/Knp/FriendlyContexts/Faker/Provider/PersonSpec.php b/spec/Knp/FriendlyContexts/Faker/Provider/PersonSpec.php deleted file mode 100644 index 33f2f775..00000000 --- a/spec/Knp/FriendlyContexts/Faker/Provider/PersonSpec.php +++ /dev/null @@ -1,42 +0,0 @@ -beConstructedWith($generator); - $this->setParent($person); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Faker\Provider\Person'); - } - - function it_should_return_parent_provider($person) - { - $this->getParent()->shouldReturn($person); - } - - function it_should_supports_Person_original_provider($person) - { - $this->supportsParent($person)->shouldReturn(true); - } - - /** - * @param Faker\Provider\Uuid $uid - **/ - function it_should_not_supports_non_Person_original_provider($uuid) - { - $this->supportsParent($uuid)->shouldReturn(false); - } -} diff --git a/spec/Knp/FriendlyContexts/Faker/Provider/PhoneNumberSpec.php b/spec/Knp/FriendlyContexts/Faker/Provider/PhoneNumberSpec.php deleted file mode 100644 index f9d85b56..00000000 --- a/spec/Knp/FriendlyContexts/Faker/Provider/PhoneNumberSpec.php +++ /dev/null @@ -1,42 +0,0 @@ -beConstructedWith($generator); - $this->setParent($phonenumber); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Faker\Provider\PhoneNumber'); - } - - function it_should_return_parent_provider($phonenumber) - { - $this->getParent()->shouldReturn($phonenumber); - } - - function it_should_supports_PhoneNumber_original_provider($phonenumber) - { - $this->supportsParent($phonenumber)->shouldReturn(true); - } - - /** - * @param Faker\Provider\Person $person - **/ - function it_should_not_supports_non_PhoneNumber_original_provider($person) - { - $this->supportsParent($person)->shouldReturn(false); - } -} diff --git a/spec/Knp/FriendlyContexts/Faker/Provider/UserAgentSpec.php b/spec/Knp/FriendlyContexts/Faker/Provider/UserAgentSpec.php deleted file mode 100644 index e8afbc6a..00000000 --- a/spec/Knp/FriendlyContexts/Faker/Provider/UserAgentSpec.php +++ /dev/null @@ -1,42 +0,0 @@ -beConstructedWith($generator); - $this->setParent($useragent); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Faker\Provider\UserAgent'); - } - - function it_should_return_parent_provider($useragent) - { - $this->getParent()->shouldReturn($useragent); - } - - function it_should_supports_UserAgent_original_provider($useragent) - { - $this->supportsParent($useragent)->shouldReturn(true); - } - - /** - * @param Faker\Provider\Person $person - **/ - function it_should_not_supports_non_UserAgent_original_provider($person) - { - $this->supportsParent($person)->shouldReturn(false); - } -} diff --git a/spec/Knp/FriendlyContexts/Faker/Provider/UuidSpec.php b/spec/Knp/FriendlyContexts/Faker/Provider/UuidSpec.php deleted file mode 100644 index f994fb52..00000000 --- a/spec/Knp/FriendlyContexts/Faker/Provider/UuidSpec.php +++ /dev/null @@ -1,42 +0,0 @@ -beConstructedWith($generator); - $this->setParent($uuid); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Faker\Provider\Uuid'); - } - - function it_should_return_parent_provider($uuid) - { - $this->getParent()->shouldReturn($uuid); - } - - function it_should_supports_Uuid_original_provider($uuid) - { - $this->supportsParent($uuid)->shouldReturn(true); - } - - /** - * @param Faker\Provider\Person $person - **/ - function it_should_not_supports_non_Uuid_original_provider($person) - { - $this->supportsParent($person)->shouldReturn(false); - } -} diff --git a/spec/Knp/FriendlyContexts/Guesser/BigintGuesserSpec.php b/spec/Knp/FriendlyContexts/Guesser/BigintGuesserSpec.php deleted file mode 100644 index 4c9ed7a6..00000000 --- a/spec/Knp/FriendlyContexts/Guesser/BigintGuesserSpec.php +++ /dev/null @@ -1,53 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\Guesser\BigintGuesser'); - } - - function it_should_support_smallint_mapping() - { - $mapping = [ - 'fieldName' => "number", - 'type' => "bigint", - 'scale' => 0, - 'length' => null, - 'unique' => false, - 'nullable' => false, - 'precision' => 0, - 'columnName' => "number", - ]; - - $this->supports($mapping)->shouldReturn(true); - } - - function it_should_support_other_mapping() - { - $mapping = [ - 'fieldName' => "created_at", - 'type' => "datetime", - 'scale' => 0, - 'length' => null, - 'unique' => false, - 'nullable' => false, - 'precision' => 0, - 'columnName' => "created_at", - ]; - - $this->supports($mapping)->shouldReturn(false); - } - - function it_should_transform_string_to_int() - { - $this->transform("2")->shouldReturn(2); - $this->transform("2.6")->shouldReturn(3); - $this->transform(" ")->shouldReturn(0); - } -} diff --git a/spec/Knp/FriendlyContexts/Guesser/BooleanGuesserSpec.php b/spec/Knp/FriendlyContexts/Guesser/BooleanGuesserSpec.php deleted file mode 100644 index 674bf0b1..00000000 --- a/spec/Knp/FriendlyContexts/Guesser/BooleanGuesserSpec.php +++ /dev/null @@ -1,57 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\Guesser\BooleanGuesser'); - $this->shouldHaveType('Knp\FriendlyContexts\Guesser\GuesserInterface'); - } - - function it_should_support_boolean_mapping_metadata() - { - $mapping = [ - 'fieldName' => "active", - 'type' => "boolean", - 'scale' => 0, - 'length' => null, - 'unique' => false, - 'nullable' => false, - 'precision' => 0, - 'columnName' => "active", - ]; - - $this->supports($mapping)->shouldReturn(true); - } - - function it_should_not_support_non_boolean_mapping_metadata() - { - $mapping = [ - 'fieldName' => "created_by", - 'type' => "string", - 'scale' => 0, - 'length' => null, - 'unique' => false, - 'nullable' => false, - 'precision' => 0, - 'columnName' => "created_by", - ]; - - $this->supports($mapping)->shouldReturn(false); - } - - function it_should_generate_a_boolean_from_a_string() - { - $this->transform('true')->shouldReturn(true); - $this->transform('no')->shouldReturn(false); - } - - function it_should_fail_to_create_a_boolean_from_a_wrong_string() - { - $this->shouldThrow(new \Exception('"test" is not a supported format. Supported format : [active, activated, disabled, true, false, yes, no, 1, 0].'))->duringTransform('TEST'); - } -} diff --git a/spec/Knp/FriendlyContexts/Guesser/DatetimeGuesserSpec.php b/spec/Knp/FriendlyContexts/Guesser/DatetimeGuesserSpec.php deleted file mode 100644 index fb662d6c..00000000 --- a/spec/Knp/FriendlyContexts/Guesser/DatetimeGuesserSpec.php +++ /dev/null @@ -1,93 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\Guesser\DatetimeGuesser'); - $this->shouldHaveType('Knp\FriendlyContexts\Guesser\GuesserInterface'); - } - - function it_should_support_datetime_mapping_metadata() - { - $mapping = [ - 'fieldName' => "created_at", - 'type' => "datetime", - 'scale' => 0, - 'length' => null, - 'unique' => false, - 'nullable' => false, - 'precision' => 0, - 'columnName' => "created_at", - ]; - - $this->supports($mapping)->shouldReturn(true); - } - - function it_should_support_date_mapping_metadata() - { - $mapping = [ - 'fieldName' => "created_at", - 'type' => "date", - 'scale' => 0, - 'length' => null, - 'unique' => false, - 'nullable' => false, - 'precision' => 0, - 'columnName' => "created_at", - ]; - - $this->supports($mapping)->shouldReturn(true); - } - - function it_should_support_time_mapping_metadata() - { - $mapping = [ - 'fieldName' => "created_at", - 'type' => "time", - 'scale' => 0, - 'length' => null, - 'unique' => false, - 'nullable' => false, - 'precision' => 0, - 'columnName' => "created_at", - ]; - - $this->supports($mapping)->shouldReturn(true); - } - - function it_should_not_support_non_datetime_mapping_metadata() - { - $mapping = [ - 'fieldName' => "created_by", - 'type' => "string", - 'scale' => 0, - 'length' => null, - 'unique' => false, - 'nullable' => false, - 'precision' => 0, - 'columnName' => "created_by", - ]; - - $this->supports($mapping)->shouldReturn(false); - } - - function it_should_generate_a_datetime_from_a_string() - { - $this->transform('now')->shouldHaveType("DateTime"); - $this->transform('today')->shouldHaveType("DateTime"); - $this->transform('+1 day')->shouldHaveType("DateTime"); - $this->transform('2013-10-01')->shouldHaveType("DateTime"); - $this->transform('2013-10-01 12:00')->shouldHaveType("DateTime"); - $this->transform('01-02-2010')->shouldHaveType("DateTime"); - } - - function it_should_fail_to_create_a_datetime_from_a_wrong_string() - { - $this->shouldThrow(new \Exception('"TEST" is not a supported date/time/datetime format. To know which formats are supported, please visit http://www.php.net/manual/en/datetime.formats.php'))->duringTransform('TEST'); - } -} diff --git a/spec/Knp/FriendlyContexts/Guesser/DecimalGuesserSpec.php b/spec/Knp/FriendlyContexts/Guesser/DecimalGuesserSpec.php deleted file mode 100644 index 213fca7c..00000000 --- a/spec/Knp/FriendlyContexts/Guesser/DecimalGuesserSpec.php +++ /dev/null @@ -1,67 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\Guesser\DecimalGuesser'); - } - - function it_should_transform_a_string_to_float() - { - $this->transform('12.21')->shouldReturn(12.21); - } - - function it_should_supports_decimal_mapping() - { - $mapping = [ - 'fieldName' => "pricing", - 'type' => "decimal", - 'scale' => 0, - 'length' => null, - 'unique' => false, - 'nullable' => false, - 'precision' => 0, - 'columnName' => "pricing", - ]; - - $this->supports($mapping)->shouldReturn(true); - } - - function it_should_supports_float_mapping() - { - $mapping = [ - 'fieldName' => "pricing", - 'type' => "float", - 'scale' => 0, - 'length' => null, - 'unique' => false, - 'nullable' => false, - 'precision' => 0, - 'columnName' => "pricing", - ]; - - $this->supports($mapping)->shouldReturn(true); - } - - function it_should_not_supports_other_mapping() - { - $mapping = [ - 'fieldName' => "pricing", - 'type' => "int", - 'scale' => 0, - 'length' => null, - 'unique' => false, - 'nullable' => false, - 'precision' => 0, - 'columnName' => "pricing", - ]; - - $this->supports($mapping)->shouldReturn(false); - } -} diff --git a/spec/Knp/FriendlyContexts/Guesser/EntityGuesserSpec.php b/spec/Knp/FriendlyContexts/Guesser/EntityGuesserSpec.php deleted file mode 100644 index 24c9202c..00000000 --- a/spec/Knp/FriendlyContexts/Guesser/EntityGuesserSpec.php +++ /dev/null @@ -1,102 +0,0 @@ -beConstructedWith($bag); - - $bag->getCollection("App\Entity\User")->willReturn($collection); - $record->getEntity()->willReturn($entity); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Guesser\EntityGuesser'); - } - - function it_should_supports_known_entity($bag, $collection) - { - $mapping = [ - 'fieldName' => "created_by", - 'unique' => false, - 'nullable' => false, - 'columnName' => "created_by", - 'targetEntity' => "App\Entity\User", - ]; - - $bag->getCollection("App\Entity\User")->willReturn($collection); - $collection->count()->willReturn(1); - - $this->supports($mapping)->shouldReturn(true); - } - - function it_should_not_supports_known_entity_but_there_is_no_record($collection) - { - $mapping = [ - 'fieldName' => "created_by", - 'unique' => false, - 'nullable' => false, - 'columnName' => "created_by", - 'targetEntity' => "App\Entity\User", - ]; - - $collection->count()->willReturn(0); - - $this->supports($mapping)->shouldReturn(false); - } - - function it_should_not_supports_if_mapping_unsupported() - { - $mapping = [ - 'fieldName' => "created_at", - 'type' => "datetime", - 'scale' => 0, - 'length' => null, - 'unique' => false, - 'nullable' => false, - 'precision' => 0, - 'columnName' => "created_at", - ]; - - $this->supports($mapping)->shouldReturn(false); - } - - function it_should_transform_a_string_to_a_record($collection, $record, $entity) - { - $mapping = [ - 'fieldName' => "created_by", - 'unique' => false, - 'nullable' => false, - 'columnName' => "created_by", - 'targetEntity' => "App\Entity\User", - ]; - - $collection->search('user1')->willReturn($record); - - $this->transform('user1', $mapping)->shouldReturn($entity); - } - - function it_should_return_null_when_transformation_inpossible() - { - $mapping = [ - 'fieldName' => "created_by", - 'unique' => false, - 'nullable' => false, - 'columnName' => "created_by", - 'targetEntity' => "App\Entity\User", - ]; - - $this->transform('user2', $mapping)->shouldReturn(null); - } -} diff --git a/spec/Knp/FriendlyContexts/Guesser/GuesserManagerSpec.php b/spec/Knp/FriendlyContexts/Guesser/GuesserManagerSpec.php deleted file mode 100644 index f7d651e7..00000000 --- a/spec/Knp/FriendlyContexts/Guesser/GuesserManagerSpec.php +++ /dev/null @@ -1,77 +0,0 @@ -supports(Argument::any())->willReturn(false); - $guesser->setManager($this)->willReturn(null); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Guesser\GuesserManager'); - } - - function it_should_return_false_when_no_guesser_supports_the_mapping() - - { - $mapping = [ - 'fieldName' => "active", - 'type' => "invalid", - 'scale' => 0, - 'length' => null, - 'unique' => false, - 'nullable' => false, - 'precision' => 0, - 'columnName' => "active", - ]; - - $this->find($mapping)->shouldReturn(false); - } - - function it_should_add_and_return_a_new_guesser($guesser) - { - $mapping = [ - 'fieldName' => "active", - 'type' => "the_type", - 'scale' => 0, - 'length' => null, - 'unique' => false, - 'nullable' => false, - 'precision' => 0, - 'columnName' => "active", - ]; - - $guesser->supports($mapping)->willReturn(true); - - $this->find($mapping)->shouldReturn(false); - $this->addGuesser($guesser); - $this->find($mapping)->shouldReturn($guesser); - } - - function it_should_return_false_when_there_is_no_guesser() - { - $mapping = [ - 'fieldName' => "active", - 'type' => "the_type", - 'scale' => 0, - 'length' => null, - 'unique' => false, - 'nullable' => false, - 'precision' => 0, - 'columnName' => "active", - ]; - - $this->find($mapping)->shouldReturn(false); - } -} diff --git a/spec/Knp/FriendlyContexts/Guesser/IntGuesserSpec.php b/spec/Knp/FriendlyContexts/Guesser/IntGuesserSpec.php deleted file mode 100644 index 46395e42..00000000 --- a/spec/Knp/FriendlyContexts/Guesser/IntGuesserSpec.php +++ /dev/null @@ -1,53 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\Guesser\IntGuesser'); - } - - function it_should_support_smallint_mapping() - { - $mapping = [ - 'fieldName' => "number", - 'type' => "integer", - 'scale' => 0, - 'length' => null, - 'unique' => false, - 'nullable' => false, - 'precision' => 0, - 'columnName' => "number", - ]; - - $this->supports($mapping)->shouldReturn(true); - } - - function it_should_support_other_mapping() - { - $mapping = [ - 'fieldName' => "created_at", - 'type' => "datetime", - 'scale' => 0, - 'length' => null, - 'unique' => false, - 'nullable' => false, - 'precision' => 0, - 'columnName' => "created_at", - ]; - - $this->supports($mapping)->shouldReturn(false); - } - - function it_should_transform_string_to_int() - { - $this->transform("2")->shouldReturn(2); - $this->transform("2.6")->shouldReturn(3); - $this->transform(" ")->shouldReturn(0); - } -} diff --git a/spec/Knp/FriendlyContexts/Guesser/SmallintGuesserSpec.php b/spec/Knp/FriendlyContexts/Guesser/SmallintGuesserSpec.php deleted file mode 100644 index 7a51f72a..00000000 --- a/spec/Knp/FriendlyContexts/Guesser/SmallintGuesserSpec.php +++ /dev/null @@ -1,53 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\Guesser\SmallintGuesser'); - } - - function it_should_support_smallint_mapping() - { - $mapping = [ - 'fieldName' => "number", - 'type' => "smallint", - 'scale' => 0, - 'length' => null, - 'unique' => false, - 'nullable' => false, - 'precision' => 0, - 'columnName' => "number", - ]; - - $this->supports($mapping)->shouldReturn(true); - } - - function it_should_support_other_mapping() - { - $mapping = [ - 'fieldName' => "created_at", - 'type' => "datetime", - 'scale' => 0, - 'length' => null, - 'unique' => false, - 'nullable' => false, - 'precision' => 0, - 'columnName' => "created_at", - ]; - - $this->supports($mapping)->shouldReturn(false); - } - - function it_should_transform_string_to_int() - { - $this->transform("2")->shouldReturn(2); - $this->transform("2.6")->shouldReturn(3); - $this->transform(" ")->shouldReturn(0); - } -} diff --git a/spec/Knp/FriendlyContexts/Guesser/StringGuesserSpec.php b/spec/Knp/FriendlyContexts/Guesser/StringGuesserSpec.php deleted file mode 100644 index 9d597eb7..00000000 --- a/spec/Knp/FriendlyContexts/Guesser/StringGuesserSpec.php +++ /dev/null @@ -1,52 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\Guesser\StringGuesser'); - $this->shouldHaveType('Knp\FriendlyContexts\Guesser\GuesserInterface'); - } - - function it_should_supports_string_mapping_metadata() - { - $mapping = [ - 'fieldName' => "name", - 'type' => "string", - 'scale' => 0, - 'length' => null, - 'unique' => false, - 'nullable' => false, - 'precision' => 0, - 'columnName' => "name", - ]; - - $this->supports($mapping)->shouldReturn(true); - } - - function it_should_supports_text_mapping_metadata() - { - $mapping = [ - 'fieldName' => "conten", - 'type' => "text", - 'scale' => 0, - 'length' => null, - 'unique' => false, - 'nullable' => false, - 'precision' => 0, - 'columnName' => "content", - ]; - - $this->supports($mapping)->shouldReturn(true); - } - - function it_shoult_not_transform_string_entry() - { - $this->transform('test')->shouldReturn('test'); - } -} diff --git a/spec/Knp/FriendlyContexts/Http/Factory/OauthPluginFactorySpec.php b/spec/Knp/FriendlyContexts/Http/Factory/OauthPluginFactorySpec.php deleted file mode 100644 index 861e133e..00000000 --- a/spec/Knp/FriendlyContexts/Http/Factory/OauthPluginFactorySpec.php +++ /dev/null @@ -1,19 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\Http\Factory\OauthPluginFactory'); - } - - function it_create_an_oauth_plugin() - { - $this->create(['some datas'])->shouldHaveType('Guzzle\Plugin\Oauth\OauthPlugin'); - } -} diff --git a/spec/Knp/FriendlyContexts/Http/HttpContentTypeGuesserSpec.php b/spec/Knp/FriendlyContexts/Http/HttpContentTypeGuesserSpec.php deleted file mode 100644 index 16a1b3b4..00000000 --- a/spec/Knp/FriendlyContexts/Http/HttpContentTypeGuesserSpec.php +++ /dev/null @@ -1,32 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\Http\HttpContentTypeGuesser'); - } - - function it_guess_a_short_content_type() - { - $this->guess('json')->shouldReturn(['application/json']); - $this->guess('xml')->shouldReturn(['application/xml', 'text/xml']); - $this->guess('html')->shouldReturn(['application/xhtml+xml', 'text/html']); - } - - function it_test_is_a_short_type_exists() - { - $this->exists('plop')->shouldReturn(false); - $this->exists('wave')->shouldReturn(true); - } - - function it_throw_an_error_on_non_existent_short_type_guessing() - { - $this->shouldThrow('InvalidArgumentException')->duringGuess('plop'); - } -} diff --git a/spec/Knp/FriendlyContexts/Http/Security/HttpBasicExtensionSpec.php b/spec/Knp/FriendlyContexts/Http/Security/HttpBasicExtensionSpec.php deleted file mode 100644 index 3147e7c1..00000000 --- a/spec/Knp/FriendlyContexts/Http/Security/HttpBasicExtensionSpec.php +++ /dev/null @@ -1,51 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\Http\Security\HttpBasicExtension'); - } - - function it_is_a_security_extension() - { - $this->shouldHaveType('Knp\FriendlyContexts\Http\Security\SecurityExtensionInterface'); - } - - function it_failed_if_we_dont_precised_valid_credentials(Request $request, RequestBuilder $builder) - { - $this->shouldThrow('RuntimeException')->duringSecureRequest($request, $builder); - - $builder->getCredentials()->shouldBeCalled()->willReturn([ - 'bad_one' => 'some values', - 'other_bad_one' => 'some other values' - ]); - - $this->shouldThrow('RuntimeException')->duringSecureRequest($request, $builder); - } - - function it_set_up_request_basic_authentication(Request $request, RequestBuilder $builder) - { - $request->setAuth('username', 'password')->shouldBeCalled(1); - - $builder->getCredentials()->shouldBeCalled()->willReturn([ - 'username' => 'username', - 'password' => 'password' - ]); - - $this->secureRequest($request, $builder); - } - - function it_does_nothing_when_we_called_secure_client(Client $client, RequestBuilder $builder) - { - $this->secureClient($client, $builder)->shouldReturn(null); - } -} diff --git a/spec/Knp/FriendlyContexts/Http/Security/OauthExtensionSpec.php b/spec/Knp/FriendlyContexts/Http/Security/OauthExtensionSpec.php deleted file mode 100644 index eb86cc2d..00000000 --- a/spec/Knp/FriendlyContexts/Http/Security/OauthExtensionSpec.php +++ /dev/null @@ -1,50 +0,0 @@ -beConstructedWith($factory); - $factory->create(Argument::cetera())->willReturn($plugin); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Http\Security\OauthExtension'); - } - - function it_is_a_security_extension() - { - $this->shouldHaveType('Knp\FriendlyContexts\Http\Security\SecurityExtensionInterface'); - } - - function it_does_not_secure_the_request(Request $request, RequestBuilder $builder) - { - $this->secureRequest($request, $builder)->shouldReturn(null); - } - - function it_set_up_a_client_oauth_plugin_subscriber(Client $client, RequestBuilder $builder, $factory, $plugin) - { - $builder->getCredentials()->willReturn([ - 'some builder credentials' - ]); - - $factory->create([ - 'some builder credentials' - ])->shouldBeCalled()->willReturn($plugin); - - $client->addSubscriber($plugin)->shouldBeCalled(); - - $this->secureClient($client, $builder); - } -} diff --git a/spec/Knp/FriendlyContexts/Node/FeatureWalkerSpec.php b/spec/Knp/FriendlyContexts/Node/FeatureWalkerSpec.php deleted file mode 100644 index 89cf08ea..00000000 --- a/spec/Knp/FriendlyContexts/Node/FeatureWalkerSpec.php +++ /dev/null @@ -1,55 +0,0 @@ -beConstructedWith($gherkin, 'paths'); - - $gherkin->load('paths')->willReturn([$feature1, $feature2]); - $feature1->getScenarios()->willReturn([$scenario1, $scenario3]); - $feature2->getScenarios()->willReturn([$scenario2]); - $scenario1->getTitle()->willReturn('Scenario1'); - $scenario2->getTitle()->willReturn('Scenario2'); - $scenario3->getTitle()->willReturn('Scenario3'); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Node\FeatureWalker'); - } - - function it_should_return_scenario_by_name($scenario1, $scenario3) - { - $this->getScenarioByName('Scenario1')->shouldReturn($scenario1); - $this->getScenarioByName('Scenario3')->shouldReturn($scenario3); - } - - function it_should_return_unkown_scenario() - { - $this->getScenarioByName('Scenario4')->shouldReturn(null); - } - - function it_should_return_all_scenario($scenario1, $scenario2, $scenario3) - { - $this->getScenarios()->shouldReturn([$scenario1, $scenario3, $scenario2]); - } - - function it_should_return_all_features($feature1, $feature2) - { - $this->getFeatures()->shouldReturn([$feature1, $feature2]); - } -} diff --git a/spec/Knp/FriendlyContexts/Page/PageSpec.php b/spec/Knp/FriendlyContexts/Page/PageSpec.php deleted file mode 100644 index e960c061..00000000 --- a/spec/Knp/FriendlyContexts/Page/PageSpec.php +++ /dev/null @@ -1,34 +0,0 @@ -beConstructedWith($session); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Page\Page'); - } - - function it_is_a_document_element() - { - $this->shouldHaveType('Behat\Mink\Element\DocumentElement'); - } - - function it_contains_the_page_path() - { - $this->path = 'foo/bar'; - - $this->getPath()->shouldReturn('foo/bar'); - } -} diff --git a/spec/Knp/FriendlyContexts/Page/Resolver/PageClassResolverSpec.php b/spec/Knp/FriendlyContexts/Page/Resolver/PageClassResolverSpec.php deleted file mode 100644 index eaf95dff..00000000 --- a/spec/Knp/FriendlyContexts/Page/Resolver/PageClassResolverSpec.php +++ /dev/null @@ -1,57 +0,0 @@ -beConstructedWith('Page\Namespace'); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Page\Resolver\PageClassResolver'); - } - - function it_test_if_a_class_exists() - { - $this->exists('Behat\Mink\Mink')->shouldReturn(true); - $this->exists('Invalid\Class')->shouldReturn(false); - } - - /** - * @param Behat\Mink\Session $session - */ - function it_throw_an_exception_when_create_a_non_existent_page($session) - { - $this->shouldThrow('InvalidArgumentException')->duringCreate($session, 'Invalid\Class'); - } - - /** - * @param Behat\Mink\Session $session - */ - function it_throw_an_exception_when_create_an_invalid_page($session) - { - $this->shouldThrow('InvalidArgumentException')->duringCreate($session, 'Knp\FriendlyContexts\Page\Resolver\PageClassResolver'); - } - - /** - * @param Behat\Mink\Session $session - */ - function it_create_a_page_object($session) - { - $this - ->create($session, 'Knp\FriendlyContexts\Page\Page') - ->shouldHaveType('Knp\FriendlyContexts\Page\Page') - ; - } - - function it_resolve_a_page_class_name() - { - $this->resolveName('some name')->shouldReturn('Page\Namespace\SomeNamePage'); - } -} diff --git a/spec/Knp/FriendlyContexts/Reader/SmartReaderSpec.php b/spec/Knp/FriendlyContexts/Reader/SmartReaderSpec.php deleted file mode 100644 index 5d95d67f..00000000 --- a/spec/Knp/FriendlyContexts/Reader/SmartReaderSpec.php +++ /dev/null @@ -1,24 +0,0 @@ -beConstructedWith($gherkin, $registry, $locator, $definitionFinder, $callCenter, 'smartStep'); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Reader\SmartReader'); - } -} diff --git a/spec/Knp/FriendlyContexts/Record/Collection/BagSpec.php b/spec/Knp/FriendlyContexts/Record/Collection/BagSpec.php deleted file mode 100644 index 4c43fa18..00000000 --- a/spec/Knp/FriendlyContexts/Record/Collection/BagSpec.php +++ /dev/null @@ -1,59 +0,0 @@ -getClassName($rightObject)->willReturn('TheClass'); - $reflector->getClassNamespace($rightObject)->willReturn('The\\Name\\Space'); - $reflector->getClassLongName($rightObject)->willReturn('The\\Name\\Space\\TheClass'); - $reflector->isInstanceOf($rightObject, 'The\\Name\\Space\\TheClass')->willReturn(true); - $reflector->isInstanceOf($rightObject, 'The\\Other\\Name\\Space\\TheOtherClass')->willReturn(false); - - $reflector->getClassName($wrongObject)->willReturn('TheOtherClass'); - $reflector->getClassNamespace($wrongObject)->willReturn('The\\Other\\Name\\Space'); - $reflector->getClassLongName($wrongObject)->willReturn('The\\Other\\Name\\Space\\TheOtherClass'); - $reflector->isInstanceOf($wrongObject, 'The\\Name\\Space\\TheClass')->willReturn(false); - $reflector->isInstanceOf($wrongObject, 'The\\Other\\Name\\Space\\TheOtherClass')->willReturn(true); - - $this->beConstructedWith($reflector); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Record\Collection\Bag'); - } - - function it_should_create_empty_collection(\StdClass $rightObject) - { - $this->getCollection($rightObject)->shouldHaveType('Knp\FriendlyContexts\Record\Collection'); - $this->count()->shouldReturn(1); - } - - function it_should_return_the_same_collection_for_the_same_object_type(\StdClass $rightObject) - { - $this->getCollection($rightObject)->shouldHaveType('Knp\FriendlyContexts\Record\Collection'); - $this->getCollection($rightObject)->shouldHaveType('Knp\FriendlyContexts\Record\Collection'); - $this->count()->shouldReturn(1); - } - - function it_should_create_two_collections_for_tow_differents_object_types(\StdClass $rightObject, \StdClass $wrongObject) - { - $this->getCollection($rightObject)->shouldHaveType('Knp\FriendlyContexts\Record\Collection'); - $this->getCollection($wrongObject)->shouldHaveType('Knp\FriendlyContexts\Record\Collection'); - $this->count()->shouldReturn(2); - } -} diff --git a/spec/Knp/FriendlyContexts/Record/CollectionSpec.php b/spec/Knp/FriendlyContexts/Record/CollectionSpec.php deleted file mode 100644 index 230e6f29..00000000 --- a/spec/Knp/FriendlyContexts/Record/CollectionSpec.php +++ /dev/null @@ -1,83 +0,0 @@ -getClassName($rightObject)->willReturn('TheClass'); - $reflector->getClassNamespace($rightObject)->willReturn('The\\Name\\Space'); - $reflector->getClassLongName($rightObject)->willReturn('The\\Name\\Space\\TheClass'); - $reflector->isInstanceOf($rightObject, 'The\\Name\\Space\\TheClass')->willReturn(true); - - $reflector->getClassName($wrongObject)->willReturn('TheOtherClass'); - $reflector->getClassNamespace($wrongObject)->willReturn('The\\Other\\Name\\Space'); - $reflector->getClassLongName($wrongObject)->willReturn('The\\Other\\Name\\Space\\TheOtherClass'); - $reflector->isInstanceOf($wrongObject, 'The\\Name\\Space\\TheClass')->willReturn(false); - - $this->beConstructedWith($reflector); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Record\Collection'); - } - - function it_should_support_entity_if_not_initialized(\StdClass $rightObject) - { - $this->support($rightObject)->shouldReturn(true); - $this->getReferencial()->shouldReturn('The\Name\Space\TheClass'); - } - - function it_should_set_the_referencial_from_string() - { - $str = "The\\Name\\Space\Of\\The\\Class"; - - $this->setReferencial($str)->shouldReturn($this); - $this->getReferencial()->shouldReturn($str); - } - - function it_should_set_the_referencial_from_entity(\StdClass $rightObject) - { - $this->setReferencial($rightObject)->shouldReturn($this); - $this->getReferencial()->shouldReturn('The\Name\Space\TheClass'); - } - - function it_should_support_entity_when_corresponding_to_string(\StdClass $rightObject) - { - $str = "The\\Name\\Space\\TheClass"; - - $this->setReferencial($str)->shouldReturn($this); - $this->support($rightObject)->shouldReturn(true); - } - - function it_should_support_entity_when_corresponding_to_object(\StdClass $rightObject) - { - $this->setReferencial($rightObject)->shouldReturn($this); - $this->support($rightObject)->shouldReturn(true); - } - - function it_should_not_support_entity_when_not_corresponding_to_string(\StdClass $wrongObject) - { - $str = "The\\Name\\Space\\TheClass"; - - $this->setReferencial($str)->shouldReturn($this); - $this->support($wrongObject)->shouldReturn(false); - } - - function it_should_not_support_entity_when_not_corresponding_to_object(\StdClass $rightObject, \StdClass $wrongObject) - { - $this->setReferencial($rightObject)->shouldReturn($this); - $this->support($wrongObject)->shouldReturn(false); - } -} diff --git a/spec/Knp/FriendlyContexts/Record/RecordSpec.php b/spec/Knp/FriendlyContexts/Record/RecordSpec.php deleted file mode 100644 index b414b7e3..00000000 --- a/spec/Knp/FriendlyContexts/Record/RecordSpec.php +++ /dev/null @@ -1,114 +0,0 @@ -getClassName($rightObject)->willReturn('TheClass'); - $reflector->getClassNamespace($rightObject)->willReturn('The\\Name\\Space'); - - $reflector->getClassName($wrongObject)->willReturn('TheOtherClass'); - $reflector->getClassNamespace($wrongObject)->willReturn('The\\Other\\Name\\Space'); - - $collection->support($rightObject)->willReturn(true); - $collection->support($wrongObject)->willReturn(false); - - $this->beConstructedWith($reflector, $collection); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Record\Record'); - } - - function it_should_attach_an_object_if_supported(\StdClass $rightObject) - { - $this->attach($rightObject)->shouldReturn(null); - $this->getEntity()->shouldReturn($rightObject); - } - - function it_should_throw_an_exception_if_entity_not_supported(\StdClass $wrongObject) - { - $this->shouldThrow(new \InvalidArgumentException('Given entity is not supported by the collection'))->duringAttach($wrongObject); - $this->getEntity()->shouldReturn(null); - } - - function it_should_attach_an_entity_with_raw_values(\StdClass $rightObject) - { - $values = [ 'name' => 'MyName', 'id' => 'MyId' ]; - - $this->attach($rightObject, $values)->shouldReturn(null); - $this->all()->shouldReturn($values); - } - - function it_should_return_true_if_record_has_raw_value(\StdClass $rightObject) - { - $values = [ 'name' => 'MyName', 'id' => 'MyId' ]; - - $this->attach($rightObject, $values)->shouldReturn(null); - $this->has('name')->shouldReturn(true); - } - - function it_should_return_false_if_record_dont_has_raw_value(\StdClass $rightObject) - { - $values = [ 'name' => 'MyName', 'id' => 'MyId' ]; - - $this->attach($rightObject, $values)->shouldReturn(null); - $this->has('price')->shouldReturn(false); - } - - function it_should_return_guessed_element_if_record_has_raw_value(\StdClass $rightObject) - { - $values = [ 'name' => 'MyName', 'id' => 'MyId' ]; - - $this->attach($rightObject, $values)->shouldReturn(null); - $this->get('name')->shouldReturn('MyName'); - $this->get('id')->shouldReturn('MyId'); - } - - function it_should_return_null_if_record_dont_has_raw_value(\StdClass $rightObject) - { - $values = [ 'name' => 'MyName', 'id' => 'MyId' ]; - - $this->attach($rightObject, $values)->shouldReturn(null); - $this->get('name')->shouldReturn('MyName'); - $this->get('id')->shouldReturn('MyId'); - } - - function it_should_return_true_if_given_raw_field_exists_and_value_is_equals(\StdClass $rightObject) - { - $values = [ 'name' => 'MyName', 'id' => 'MyId' ]; - - $this->attach($rightObject, $values)->shouldReturn(null); - $this->equals('name', 'MyName')->shouldReturn(true); - } - - function it_should_return_false_if_given_raw_field_exists_and_value_not_is_equals(\StdClass $rightObject) - { - $values = [ 'name' => 'MyName', 'id' => 'MyId' ]; - - $this->attach($rightObject, $values)->shouldReturn(null); - $this->equals('name', 'MyFirstName')->shouldReturn(false); - } - - function it_should_return_false_if_given_raw_field_dont_exists(\StdClass $rightObject) - { - $values = [ 'name' => 'MyName', 'id' => 'MyId' ]; - - $this->attach($rightObject, $values)->shouldReturn(null); - $this->equals('firstname', 'MyName')->shouldReturn(false); - } -} diff --git a/spec/Knp/FriendlyContexts/Reflection/ObjectReflectorSpec.php b/spec/Knp/FriendlyContexts/Reflection/ObjectReflectorSpec.php deleted file mode 100644 index 9dc2b185..00000000 --- a/spec/Knp/FriendlyContexts/Reflection/ObjectReflectorSpec.php +++ /dev/null @@ -1,40 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\Reflection\ObjectReflector'); - } - - function it_should_return_the_object_reflection_class(\StdClass $object) - { - $this->getReflectionClass($object)->shouldHaveType('ReflectionClass'); - } - - function it_should_return_object_class_name(\StdClass $object) - { - $this->getClassName($object)->shouldBeString(); - } - - function it_should_return_object_class_namespace(\StdClass $object) - { - $this->getClassNamespace($object)->shouldBeString(); - } - - function it_should_return_object_class_long_name(\StdClass $object) - { - $this->getClassLongName($object)->shouldBeString(); - } -} diff --git a/spec/Knp/FriendlyContexts/Utils/AsserterSpec.php b/spec/Knp/FriendlyContexts/Utils/AsserterSpec.php deleted file mode 100644 index e519bfda..00000000 --- a/spec/Knp/FriendlyContexts/Utils/AsserterSpec.php +++ /dev/null @@ -1,95 +0,0 @@ -beConstructedWith(new TextFormater); - } - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyContexts\Utils\Asserter'); - } - - function it_should_assert_if_equals() - { - $object = new \StdClass; - - $this->assertEquals(true, true)->shouldReturn(true); - $this->assertEquals(0, 0)->shouldReturn(true); - $this->assertEquals(1000, 1000)->shouldReturn(true); - $this->assertEquals('string', "string")->shouldReturn(true); - $this->assertEquals(null, null)->shouldReturn(true); - $this->assertEquals($object, $object)->shouldReturn(true); - $this->assertEquals([ 0, 1, 2, 3 ], [ 0, 1, 2, 3 ])->shouldReturn(true); - } - - function it_should_throw_and_exception_when_can_t_assert() - { - $this->shouldThrow(new \Exception("Failing to assert equals.", 1))->duringAssertEquals(true, false); - $this->shouldThrow(new \Exception("Failing to assert equals.", 1))->duringAssertEquals(0, 1); - $this->shouldThrow(new \Exception("Failing to assert equals.", 1))->duringAssertEquals("string", "STRING"); - $this->shouldThrow(new \Exception("Failing to assert equals.", 1))->duringAssertEquals(0, "0"); - $this->shouldThrow(new \Exception("Failing to assert equals.", 1))->duringAssertEquals(new \StdClass, new \StdClass); - } - - function it_should_display_the_array_when_display_the_error() - { - $expected = "The given array\r\n\r\n| 10 | test | 1 |\r\nis not equals to expected\r\n\r\n| 10 | text | |"; - - $this->shouldThrow(new \Exception($expected, 1))->duringAssertArrayEquals([ 10, 'text', false ], [ 10, 'test', true ]); - } - - function it_assert_that_an_array_contains_an_other() - { - $expected = "The given array\r\n\r\n| 10 | test | 1 |\r\ndoes not contains the following rows\r\n\r\n| 10 | text | |"; - - $this->shouldThrow(new \Exception($expected, 1))->duringAssertArrayContains([ 10, 'text', false ], [ 10, 'test', true ]); - } - - function it_detect_array_into_table() - { - $real = [ - [ 1, 2, 3, 4 ], - [ 'a', 'b', 'c', 'd' ], - [ 'd', 'b', 'a', 'b' ], - [ 1, 2, 3, 4 ], - ]; - - $expected = [ - [ 'b', 'a' ], - [ 2, 3 ], - ]; - - $this->assertArrayContains($expected, $real)->shouldReturn(true); - - $expected = [ - [ 2, 3 ], - [ 'b', 'c' ], - ]; - - $this->assertArrayContains($expected, $real)->shouldReturn(true); - } - - function it_throw_when_array_doesnt_contains() - { - $real = [ - [ 1, 2, 3, 4 ], - [ 'a', 'b', 'c', 'd' ], - [ 'd', 'b', 'a', 'b' ], - [ 1, 2, 3, 4 ], - ]; - - $expected = [ - [ 1, 2 ], - [ 'a', 'd' ], - ]; - - $this->shouldThrow()->duringAssertArrayContains($expected, $real); - } -} diff --git a/spec/Knp/FriendlyContexts/Utils/TextFormaterSpec.php b/spec/Knp/FriendlyContexts/Utils/TextFormaterSpec.php deleted file mode 100644 index 04c4c3c5..00000000 --- a/spec/Knp/FriendlyContexts/Utils/TextFormaterSpec.php +++ /dev/null @@ -1,43 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\Utils\TextFormater'); - } - - function it_should_camel_case_string() - { - $this->toCamelCase('the first string')->shouldReturn('TheFirstString'); - $this->toCamelCase('string')->shouldReturn('String'); - } - - function it_should_underscore_string() - { - $this->toUnderscoreCase('the first string')->shouldReturn('the_first_string'); - $this->toUnderscoreCase('string')->shouldReturn('string'); - } - - function it_should_build_array() - { - $this->tableToString([ 'test', 'tata', 'toto' ])->shouldReturn('| test | tata | toto |'); - } - - function it_should_build_table() - { - $table = [ - [ 'test', 'tata', 'toto' ], - [ '0', '123456789', 'azertyuiop' ], - [ '987654321', '0', '12345' ], - ]; - - $return = "| test | tata | toto |\n| 0 | 123456789 | azertyuiop |\n| 987654321 | 0 | 12345 |\n"; - - $this->tableToString($table)->shouldReturn($return); - } -} diff --git a/spec/Knp/FriendlyContexts/Utils/UniqueCacheSpec.php b/spec/Knp/FriendlyContexts/Utils/UniqueCacheSpec.php deleted file mode 100644 index 086a279d..00000000 --- a/spec/Knp/FriendlyContexts/Utils/UniqueCacheSpec.php +++ /dev/null @@ -1,31 +0,0 @@ -shouldHaveType('Knp\FriendlyContexts\Utils\UniqueCache'); - } - - function its_generate_should_generate_a_new_unique_value() - { - $this->generate('Class', 'property', function () { - return 'test'; - }); - - $this->exists('Class', 'property', 'test')->shouldReturn(true); - - $cache = null; - $this->generate('Class', 'property', function () use (&$cache) { - $cache = rand(); - return $cache; - }); - - $this->exists('Class', 'property', $cache)->shouldReturn(true); - } -} diff --git a/spec/Knp/FriendlyExtension/Utils/NameProposerSpec.php b/spec/Knp/FriendlyExtension/Utils/NameProposerSpec.php new file mode 100755 index 00000000..09d1391e --- /dev/null +++ b/spec/Knp/FriendlyExtension/Utils/NameProposerSpec.php @@ -0,0 +1,27 @@ +beConstructedWith($formater); + } + + function it_is_initializable() + { + $this->shouldHaveType('Knp\FriendlyExtension\Utils\NameProposer'); + } + + function it_propose_a_set_of_names() + { + $this->buildProposals('the_test')->shoulwReturn([ + + ]); + } +} diff --git a/spec/Knp/FriendlyExtensionSpec.php b/spec/Knp/FriendlyExtensionSpec.php new file mode 100755 index 00000000..5b3681b3 --- /dev/null +++ b/spec/Knp/FriendlyExtensionSpec.php @@ -0,0 +1,14 @@ +shouldHaveType('Knp\FriendlyExtension'); + } +} diff --git a/src/Knp/FriendlyContexts/Alice/Loader/Yaml.php b/src/Knp/FriendlyContexts/Alice/Loader/Yaml.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Builder/AbstractRequestBuilder.php b/src/Knp/FriendlyContexts/Builder/AbstractRequestBuilder.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Builder/DeleteRequestBuilder.php b/src/Knp/FriendlyContexts/Builder/DeleteRequestBuilder.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Builder/GetRequestBuilder.php b/src/Knp/FriendlyContexts/Builder/GetRequestBuilder.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Builder/HeadRequestBuilder.php b/src/Knp/FriendlyContexts/Builder/HeadRequestBuilder.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Builder/OptionsRequestBuilder.php b/src/Knp/FriendlyContexts/Builder/OptionsRequestBuilder.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Builder/PatchRequestBuilder.php b/src/Knp/FriendlyContexts/Builder/PatchRequestBuilder.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Builder/PostRequestBuilder.php b/src/Knp/FriendlyContexts/Builder/PostRequestBuilder.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Builder/PutRequestBuilder.php b/src/Knp/FriendlyContexts/Builder/PutRequestBuilder.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Builder/RequestBuilder.php b/src/Knp/FriendlyContexts/Builder/RequestBuilder.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Builder/RequestBuilderInterface.php b/src/Knp/FriendlyContexts/Builder/RequestBuilderInterface.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Call/CallCenter.php b/src/Knp/FriendlyContexts/Call/CallCenter.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Context/AliceContext.php b/src/Knp/FriendlyContexts/Context/AliceContext.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Context/ApiContext.php b/src/Knp/FriendlyContexts/Context/ApiContext.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Context/Context.php b/src/Knp/FriendlyContexts/Context/Context.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Context/EntityContext.php b/src/Knp/FriendlyContexts/Context/EntityContext.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Context/Initializer/FriendlyInitializer.php b/src/Knp/FriendlyContexts/Context/Initializer/FriendlyInitializer.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Context/MinkContext.php b/src/Knp/FriendlyContexts/Context/MinkContext.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Context/PageContext.php b/src/Knp/FriendlyContexts/Context/PageContext.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Context/RawMinkContext.php b/src/Knp/FriendlyContexts/Context/RawMinkContext.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Context/RawPageContext.php b/src/Knp/FriendlyContexts/Context/RawPageContext.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Context/TableContext.php b/src/Knp/FriendlyContexts/Context/TableContext.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Definition/DefinitionFinder.php b/src/Knp/FriendlyContexts/Definition/DefinitionFinder.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/DependencyInjection/Compiler/ApiUrlPass.php b/src/Knp/FriendlyContexts/DependencyInjection/Compiler/ApiUrlPass.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/DependencyInjection/Compiler/ConfigPass.php b/src/Knp/FriendlyContexts/DependencyInjection/Compiler/ConfigPass.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/DependencyInjection/Compiler/FakerProviderPass.php b/src/Knp/FriendlyContexts/DependencyInjection/Compiler/FakerProviderPass.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/DependencyInjection/Compiler/FormatGuesserPass.php b/src/Knp/FriendlyContexts/DependencyInjection/Compiler/FormatGuesserPass.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/DependencyInjection/Compiler/KernelPass.php b/src/Knp/FriendlyContexts/DependencyInjection/Compiler/KernelPass.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Dictionary/Backgroundable.php b/src/Knp/FriendlyContexts/Dictionary/Backgroundable.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Dictionary/Taggable.php b/src/Knp/FriendlyContexts/Dictionary/Taggable.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Doctrine/EntityHydrator.php b/src/Knp/FriendlyContexts/Doctrine/EntityHydrator.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Doctrine/EntityResolver.php b/src/Knp/FriendlyContexts/Doctrine/EntityResolver.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Extension.php b/src/Knp/FriendlyContexts/Extension.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Faker/Provider/Address.php b/src/Knp/FriendlyContexts/Faker/Provider/Address.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Faker/Provider/Base.php b/src/Knp/FriendlyContexts/Faker/Provider/Base.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Faker/Provider/Color.php b/src/Knp/FriendlyContexts/Faker/Provider/Color.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Faker/Provider/Company.php b/src/Knp/FriendlyContexts/Faker/Provider/Company.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Faker/Provider/DateTime.php b/src/Knp/FriendlyContexts/Faker/Provider/DateTime.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Faker/Provider/File.php b/src/Knp/FriendlyContexts/Faker/Provider/File.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Faker/Provider/Internet.php b/src/Knp/FriendlyContexts/Faker/Provider/Internet.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Faker/Provider/Lorem.php b/src/Knp/FriendlyContexts/Faker/Provider/Lorem.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Faker/Provider/Miscellaneous.php b/src/Knp/FriendlyContexts/Faker/Provider/Miscellaneous.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Faker/Provider/Payment.php b/src/Knp/FriendlyContexts/Faker/Provider/Payment.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Faker/Provider/Person.php b/src/Knp/FriendlyContexts/Faker/Provider/Person.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Faker/Provider/PhoneNumber.php b/src/Knp/FriendlyContexts/Faker/Provider/PhoneNumber.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Faker/Provider/UserAgent.php b/src/Knp/FriendlyContexts/Faker/Provider/UserAgent.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Faker/Provider/Uuid.php b/src/Knp/FriendlyContexts/Faker/Provider/Uuid.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Guesser/AbstractGuesser.php b/src/Knp/FriendlyContexts/Guesser/AbstractGuesser.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Guesser/BigintGuesser.php b/src/Knp/FriendlyContexts/Guesser/BigintGuesser.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Guesser/BooleanGuesser.php b/src/Knp/FriendlyContexts/Guesser/BooleanGuesser.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Guesser/DatetimeGuesser.php b/src/Knp/FriendlyContexts/Guesser/DatetimeGuesser.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Guesser/DecimalGuesser.php b/src/Knp/FriendlyContexts/Guesser/DecimalGuesser.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Guesser/EntityGuesser.php b/src/Knp/FriendlyContexts/Guesser/EntityGuesser.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Guesser/GuesserInterface.php b/src/Knp/FriendlyContexts/Guesser/GuesserInterface.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Guesser/GuesserManager.php b/src/Knp/FriendlyContexts/Guesser/GuesserManager.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Guesser/IntGuesser.php b/src/Knp/FriendlyContexts/Guesser/IntGuesser.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Guesser/SmallintGuesser.php b/src/Knp/FriendlyContexts/Guesser/SmallintGuesser.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Guesser/StringGuesser.php b/src/Knp/FriendlyContexts/Guesser/StringGuesser.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Http/Factory/OauthPluginFactory.php b/src/Knp/FriendlyContexts/Http/Factory/OauthPluginFactory.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Http/HttpContentTypeGuesser.php b/src/Knp/FriendlyContexts/Http/HttpContentTypeGuesser.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Http/Security/HttpBasicExtension.php b/src/Knp/FriendlyContexts/Http/Security/HttpBasicExtension.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Http/Security/OauthExtension.php b/src/Knp/FriendlyContexts/Http/Security/OauthExtension.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Http/Security/SecurityExtensionInterface.php b/src/Knp/FriendlyContexts/Http/Security/SecurityExtensionInterface.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Node/FeatureWalker.php b/src/Knp/FriendlyContexts/Node/FeatureWalker.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Page/Page.php b/src/Knp/FriendlyContexts/Page/Page.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Page/Resolver/PageClassResolver.php b/src/Knp/FriendlyContexts/Page/Resolver/PageClassResolver.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Reader/SmartReader.php b/src/Knp/FriendlyContexts/Reader/SmartReader.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Record/Collection.php b/src/Knp/FriendlyContexts/Record/Collection.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Record/Collection/Bag.php b/src/Knp/FriendlyContexts/Record/Collection/Bag.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Record/Record.php b/src/Knp/FriendlyContexts/Record/Record.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Reflection/ObjectReflector.php b/src/Knp/FriendlyContexts/Reflection/ObjectReflector.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Request/RequestMethods.php b/src/Knp/FriendlyContexts/Request/RequestMethods.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Utils/Asserter.php b/src/Knp/FriendlyContexts/Utils/Asserter.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Utils/TextFormater.php b/src/Knp/FriendlyContexts/Utils/TextFormater.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/Utils/UniqueCache.php b/src/Knp/FriendlyContexts/Utils/UniqueCache.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/services/builder.yml b/src/Knp/FriendlyContexts/services/builder.yml old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/services/core.yml b/src/Knp/FriendlyContexts/services/core.yml old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/services/fakers.yml b/src/Knp/FriendlyContexts/services/fakers.yml old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyContexts/services/guessers.yml b/src/Knp/FriendlyContexts/services/guessers.yml old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension.php b/src/Knp/FriendlyExtension.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/Context/Helper/AsserterHelper.php b/src/Knp/FriendlyExtension/Context/Helper/AsserterHelper.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/Context/Helper/DoctrineHelper.php b/src/Knp/FriendlyExtension/Context/Helper/DoctrineHelper.php new file mode 100755 index 00000000..b0512a03 --- /dev/null +++ b/src/Knp/FriendlyExtension/Context/Helper/DoctrineHelper.php @@ -0,0 +1,44 @@ +em = $em; + } + + public function getName() + { + return 'doctrine'; + } + + /** + * Reset the schema, clear the entity manager + * + * @return void + */ + public function reset() + { + $metadata = $this + ->em + ->getMetadataFactory() + ->getAllMetadata() + ; + + if (!empty($metadata)) { + $tool = new SchemaTool($this->em); + $tool->dropSchema($metadata); + $tool->createSchema($metadata); + } + + $this->em->clear(); + } +} diff --git a/src/Knp/FriendlyExtension/Context/Helper/EntityHelper.php b/src/Knp/FriendlyExtension/Context/Helper/EntityHelper.php new file mode 100755 index 00000000..88047305 --- /dev/null +++ b/src/Knp/FriendlyExtension/Context/Helper/EntityHelper.php @@ -0,0 +1,20 @@ +em = $em; + $this->hydrator = $hydrator; + $this->bag = $bag; + } +} diff --git a/src/Knp/FriendlyExtension/Context/Helper/HelperInterface.php b/src/Knp/FriendlyExtension/Context/Helper/HelperInterface.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/DependencyInjection/Compiler/ApiUrlTransitionPass.php b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/ApiUrlTransitionPass.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/DependencyInjection/Compiler/FakerGuesserRegistrationPass.php b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/FakerGuesserRegistrationPass.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/DependencyInjection/Compiler/FakerProviderRegistrationPass.php b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/FakerProviderRegistrationPass.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/DependencyInjection/Compiler/KernelRegistrationPass.php b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/KernelRegistrationPass.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/DependencyInjection/Compiler/ParameterBuildingPass.php b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/ParameterBuildingPass.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/Doctrine/Resolver.php b/src/Knp/FriendlyExtension/Doctrine/Resolver.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/Entity/Hydrator.php b/src/Knp/FriendlyExtension/Entity/Hydrator.php new file mode 100755 index 00000000..dde178ac --- /dev/null +++ b/src/Knp/FriendlyExtension/Entity/Hydrator.php @@ -0,0 +1,129 @@ +em = $em; + $this->formater = $formater; + $this->guessers = $guessers; + $this->resolver = $resolver; + $this->cache = $cache; + } + + public function hydrate(ObjectManager $em, $entity, $values) + { + foreach ($values as $property => $value) { + if (false !== $mapping = $this->resolver->getMetadataFromProperty($em, $entity, $property)) { + $this->formatFromMapping($mapping, $property, $value); + } + + try { + PropertyAccess::getPropertyAccessor() + ->setValue( + $entity, + $this->formater->toCamelCase($property), + $value + ) + ; + } catch (\Exception $e) { + if (!($value instanceof ArrayCollection)) { + throw $e; + } + + PropertyAccess::getPropertyAccessor() + ->setValue( + $entity, + $this->formater->toCamelCase($property), + $value->toArray() + ) + ; + } + } + + return $this; + } + + public function completeRequired(ObjectManager $em, $entity) + { + $this->completeFields($em, $entity); + } + + public function completeFields(ObjectManager $em, $entity) + { + $accessor = PropertyAccess::getPropertyAccessor(); + + $metadata = $this->resolver->getMetadataFromObject($em, $entity); + + foreach ($metadata->getColumnNames() as $columnName) { + $property = $metadata->getFieldName($columnName); + if (false === $metadata->isNullable($property) && null === $accessor->getValue($entity, $property)) { + try { + $accessor->setValue( + $entity, + $property, + $this->complete($metadata->getFieldMapping($property), $metadata->getName()) + ); + } catch (\Exception $ex) { + unset($ex); + } + } + } + + return $this; + } + + protected function complete($mapping, $className) + { + if (false === $guesser = $this->guesserManager->find($mapping)) { + throw new \Exception(sprintf('There is no fake solution for "%s" typed fields', $mapping['type'])); + } + + if (true === $mapping['unique']) { + return $this->cache->generate($className, $mapping['fieldName'], function () use ($guesser, $mapping) { + return $guesser->fake($mapping); + }); + } + + return $guesser->fake($mapping); + } + + protected function format($mapping, $value) + { + if (false === $guesser = $this->guesserManager->find($mapping)) { + + return $value; + } + + return $guesser->transform($value, $mapping); + } + + protected function formatFromMapping(array $mapping, &$property, &$value) + { + $property = $mapping['fieldName']; + $collectionRelation = in_array($mapping['type'], [ClassMetadata::ONE_TO_MANY, ClassMetadata::MANY_TO_MANY]); + $arrayRelation = $mapping['type'] === 'array'; + + if ($collectionRelation || $arrayRelation) { + $result = array_map( + function ($e) use ($mapping) { + return $this->format($mapping, $e); + }, + $this->formater->listToArray($value) + ); + + $value = $collectionRelation ? new ArrayCollection($result) : $result; + } else { + $value = $this->format($mapping, $value); + } + } +} diff --git a/src/Knp/FriendlyExtension/Entity/Resolver.php b/src/Knp/FriendlyExtension/Entity/Resolver.php new file mode 100755 index 00000000..57d930a2 --- /dev/null +++ b/src/Knp/FriendlyExtension/Entity/Resolver.php @@ -0,0 +1,93 @@ +em = $em; + $this->reflector = $reflector; + $this->formater = $formater; + $this->nameProposer = $nameProposer; + } + + public function resolveClassName($name, $namespaces = '') + { + $results = []; + + $namespaces = is_array($namespaces) ? $namespaces : [ $namespaces ]; + + foreach ($namespaces as $namespace) { + $results = $this->getClassesFromName($name, $namespace, $results); + } + + return (0 < count($results)) ? $results : null; + } + + public function getClassesFromName($name, $namespace, array $results = []) + { + $metadata = $this->em->getMetadataFactory()->getAllMetadata(); + $classes = $this->reflector->getReflectionsFromMetadata($metadata); + + return array_merge( + $result, + array_filter( + $classes, + function ($e) use ($name) { + return $this->nameProposer->match($e->getShortName($name)); + } + ) + ); + } + + + public function getObjectMetadata($object) + { + return $this + ->em + ->getMetadataFactory() + ->getMetadataFor(is_object($object) ? get_class($object) : (string)$object) + ; + } + + public function getPropertyMetadata($object, $property) + { + $metadata = $this->getObjectMetadata($object); + + if (null !== $map = $this->getExtractPropertyMetadata($metadata->fieldMappings, $property)) { + return $map; + } + + if (null !== $map = $this->getExtractPropertyMetadata($metadata->associationMappings, $property)) { + return $map; + } + } + + protected function getExtractPropertyMetadata($metadata, $property) + { + $property = trim($property); + + foreach ($metadata as $id => $mapping) { + if ($this->nameProposer->match($property, $id)) { + + return $mapping; + } + } + } +} diff --git a/src/Knp/FriendlyExtension/Faker/Provider/Address.php b/src/Knp/FriendlyExtension/Faker/Provider/Address.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/Faker/Provider/Base.php b/src/Knp/FriendlyExtension/Faker/Provider/Base.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/Faker/Provider/DateTime.php b/src/Knp/FriendlyExtension/Faker/Provider/DateTime.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/Faker/Provider/Internet.php b/src/Knp/FriendlyExtension/Faker/Provider/Internet.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/Faker/Provider/Person.php b/src/Knp/FriendlyExtension/Faker/Provider/Person.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/Faker/Provider/PhoneNumber.php b/src/Knp/FriendlyExtension/Faker/Provider/PhoneNumber.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/Faker/UniqueCache.php b/src/Knp/FriendlyExtension/Faker/UniqueCache.php new file mode 100755 index 00000000..f1074b90 --- /dev/null +++ b/src/Knp/FriendlyExtension/Faker/UniqueCache.php @@ -0,0 +1,55 @@ +cache[$className])) { + return false; + } + + if (!is_array($this->cache[$className]) || !isset($this->cache[$className][$field])) { + return false; + } + + if (!is_array($this->cache[$className][$field])) { + return false; + } + + foreach ($this->cache[$className][$field] as $cacheValue) { + if ($value === $cacheValue) { + return true; + } + } + + return false; + } + + public function generate($className, $field, $callback) + { + do { + $value = $callback(); + } while ($this->exists($className, $field, $value)); + + if (!isset($this->cache[$className])) { + $this->cache[$className] = []; + } + + if (!isset($this->cache[$className][$field])) { + $this->cache[$className][$field] = []; + } + + $this->cache[$className][$field][] = $value; + + return $value; + } + + public function clear() + { + $this->cache = []; + } +} diff --git a/src/Knp/FriendlyExtension/Record/Collection.php b/src/Knp/FriendlyExtension/Record/Collection.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/Record/Collection/Bag.php b/src/Knp/FriendlyExtension/Record/Collection/Bag.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/Record/Record.php b/src/Knp/FriendlyExtension/Record/Record.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/Symfony/ServiceShifter.php b/src/Knp/FriendlyExtension/Symfony/ServiceShifter.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/Type/Guesser/AbstractGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/AbstractGuesser.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/Type/Guesser/BigintGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/BigintGuesser.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/Type/Guesser/BooleanGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/BooleanGuesser.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/Type/Guesser/DatetimeGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/DatetimeGuesser.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/Type/Guesser/DecimalGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/DecimalGuesser.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/Type/Guesser/EntityGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/EntityGuesser.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/Type/Guesser/GuesserInterface.php b/src/Knp/FriendlyExtension/Type/Guesser/GuesserInterface.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/Type/Guesser/IntGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/IntGuesser.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/Type/Guesser/SmallintGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/SmallintGuesser.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/Type/Guesser/StringGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/StringGuesser.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/Type/GuesserRegistry.php b/src/Knp/FriendlyExtension/Type/GuesserRegistry.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/Utils/NameProposer.php b/src/Knp/FriendlyExtension/Utils/NameProposer.php old mode 100644 new mode 100755 index be032b64..150a1341 --- a/src/Knp/FriendlyExtension/Utils/NameProposer.php +++ b/src/Knp/FriendlyExtension/Utils/NameProposer.php @@ -3,7 +3,7 @@ namespace Knp\FriendlyExtension\Utils; use Doctrine\Common\Inflector\Inflector; -use Knp\FriendlyContexts\Utils\TextFormater; +use Knp\FriendlyExtension\Utils\TextFormater; class NameProposer { @@ -14,9 +14,9 @@ public function __construct(TextFormater $formater) $this->formater = $formater; } - public function match($name, $other) + public function match($subject, $expected, $pluralize = false) { - $proposals = $this->buildProposals($name); + $proposals = $this->buildProposals($name, $pluralize); return in_array($other, $proposals); } diff --git a/src/Knp/FriendlyExtension/Utils/ObjectReflector.php b/src/Knp/FriendlyExtension/Utils/ObjectReflector.php old mode 100644 new mode 100755 diff --git a/src/Knp/FriendlyExtension/Utils/TextFormater.php b/src/Knp/FriendlyExtension/Utils/TextFormater.php old mode 100644 new mode 100755 index dcb39436..4503fca2 --- a/src/Knp/FriendlyExtension/Utils/TextFormater.php +++ b/src/Knp/FriendlyExtension/Utils/TextFormater.php @@ -1,4 +1,3 @@ - Date: Wed, 16 Jul 2014 14:23:14 +0200 Subject: [PATCH 05/33] WIP --- .../Context/Helper/DoctrineHelper.php | 32 +++++++++- .../Context/Helper/EntityHelper.php | 17 ++++++ .../FriendlyExtension/Doctrine/Resolver.php | 60 +++++++++---------- 3 files changed, 77 insertions(+), 32 deletions(-) diff --git a/src/Knp/FriendlyExtension/Context/Helper/DoctrineHelper.php b/src/Knp/FriendlyExtension/Context/Helper/DoctrineHelper.php index b0512a03..82c6dd08 100755 --- a/src/Knp/FriendlyExtension/Context/Helper/DoctrineHelper.php +++ b/src/Knp/FriendlyExtension/Context/Helper/DoctrineHelper.php @@ -5,14 +5,17 @@ use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Tools\SchemaTool; use Knp\FriendlyExtension\Context\Helper\HelperInterface; +use Knp\FriendlyExtension\Doctrine\Resolver; class DoctrineHelper implements HelperInterface { private $em; + private $resolver; - public function __construct(EntityManagerInterface $em) + public function __construct(EntityManagerInterface $em, Resolver $resolver) { - $this->em = $em; + $this->em = $em; + $this->resolver = $resolver; } public function getName() @@ -20,6 +23,31 @@ public function getName() return 'doctrine'; } + public function getClass($name) + { + + } + + public function refresh($entity) + { + $this->em->refresh($entity); + } + + public function remove($entity) + { + $this->em->remove($entity); + } + + public function persist($entity) + { + $this->em->persist($entity); + } + + public function flush($entity = null) + { + $this->em->flush($entity); + } + /** * Reset the schema, clear the entity manager * diff --git a/src/Knp/FriendlyExtension/Context/Helper/EntityHelper.php b/src/Knp/FriendlyExtension/Context/Helper/EntityHelper.php index 88047305..3aaba07b 100755 --- a/src/Knp/FriendlyExtension/Context/Helper/EntityHelper.php +++ b/src/Knp/FriendlyExtension/Context/Helper/EntityHelper.php @@ -17,4 +17,21 @@ public function __construct(EntityManagerInterface $em, Hydrator $hydrator, Bag $this->hydrator = $hydrator; $this->bag = $bag; } + + public function getName() + { + return 'doctrine'; + } + + public function createNew($name) + { + $class = $this->doctrineHelper->getClass($name); + + $entity = (new \ReflectionClass($class))->newInstanceWithoutConstructor(); + } + + public function hydrate($entity, array $values) + { + + } } diff --git a/src/Knp/FriendlyExtension/Doctrine/Resolver.php b/src/Knp/FriendlyExtension/Doctrine/Resolver.php index 7cdbff7c..4334802a 100755 --- a/src/Knp/FriendlyExtension/Doctrine/Resolver.php +++ b/src/Knp/FriendlyExtension/Doctrine/Resolver.php @@ -24,22 +24,21 @@ public function __construct(EntityManagerInterface $em, ObjectReflector $reflect public function resolveEntity($name, $onlyOne = false) { - $entities = array_filter( - $this->getAllEntities(), - function ($e) use ($name) { - return $this->proposer->match($name, $e->getShortName()); + $results = []; + + foreach ($this->getMetadata() as $metadata) { + if ($this->proposer->match($name, $this->reflector->getClassShortName($metadata->name))) { + $results[] = $this->reflector->getClassLongName($metadata->name); } - ); - - if (true === $onlyOne && 1 > count($entities)) { - throw new \Exception(sprintf('Expected only one entity named "%s", "%s" found', $name, - implode('", "', - array_map( - function ($e) { return $e->getShortName(); }, - $entities - ), - ) - )); + } + + if (true === $onlyOne && 1 > count($results)) { + $message = sprintf( + 'Expected only one entity named "%s", "%s" found', + $name, + implode('", "', $results) + ); + throw new \Exception($message); } return $onlyOne @@ -48,21 +47,7 @@ function ($e) { return $e->getShortName(); }, ; } - public function resolveProperty($name, $property) - { - $entity = $this->resolveEntity($name, true); - - - } - - private function getAllEntities() - { - $metadata = $this->em->getMetadataFactory()->getAllMetadata(); - - return $this->reflector->getReflectionsFromMetadata($allMetadata); - } - - private function getMetadataFor($class, $property = null) + public function getMetadataFor($class, $property = null) { $metadata = $this->em->getMetadataFactory()->getMetadataFor($class); @@ -81,4 +66,19 @@ private function getMetadataFor($class, $property = null) return $metadata->associationMappings[$name]; } } + + public function getMetadata() + { + return $this->em->getMetadataFactory()->getAllMetadata(); + } + + private function resolveName($name, $names) + { + foreach ($names as $property) { + if ($this->proposer->match($name, $property)) { + + return $property; + } + } + } } From 65c2b4bcaa266a16387045cf56b19294b3221c36 Mon Sep 17 00:00:00 2001 From: Pierre PLAZANET Date: Fri, 18 Jul 2014 18:16:58 +0200 Subject: [PATCH 06/33] WIP --- .../Utils/NameProposerSpec.php | 51 +++++++++- src/Knp/FriendlyExtension.php | 9 +- src/Knp/FriendlyExtension/Context/Context.php | 21 ++++ .../Context/ContextInterface.php | 11 +++ .../Context/EntityContext.php | 26 +++++ .../Context/Helper/AbstractHelper.php | 20 ++++ .../Context/Helper/AsserterHelper.php | 8 +- .../Context/Helper/DoctrineHelper.php | 30 ++++-- .../Context/Helper/EntityHelper.php | 95 +++++++++++++++++-- .../Context/Helper/HelperInterface.php | 4 + .../Context/Helper/Registry.php | 28 ++++++ .../Initializer/FriendlyInitializer.php | 31 ++++++ .../ContextHelperRegistrationPass.php | 20 ++++ .../FakerProviderRegistrationPass.php | 1 + .../Compiler/SymfonyServicePass.php | 28 ++++++ .../FriendlyExtension/Doctrine/Resolver.php | 15 ++- src/Knp/FriendlyExtension/Entity/Hydrator.php | 5 - .../Type/Guesser/AbstractGuesser.php | 19 ---- .../Type/Guesser/ArrayGuesser.php | 59 ++++++++++++ .../Type/Guesser/BigintGuesser.php | 16 +++- .../Type/Guesser/BooleanGuesser.php | 2 +- .../Type/Guesser/CollectionGuesser.php | 42 ++++++++ .../Type/Guesser/DatetimeGuesser.php | 2 +- .../Type/Guesser/DecimalGuesser.php | 2 +- .../Type/Guesser/EntityGuesser.php | 2 +- .../Type/Guesser/GuesserInterface.php | 4 - .../Type/Guesser/IntGuesser.php | 2 +- .../Type/Guesser/SmallintGuesser.php | 15 ++- .../Type/Guesser/StringGuesser.php | 2 +- .../Type/GuesserRegistry.php | 4 +- .../FriendlyExtension/Utils/NameProposer.php | 11 ++- .../FriendlyExtension/Utils/ObjectWrapper.php | 13 +++ .../FriendlyExtension/Utils/TextFormater.php | 4 +- .../FriendlyExtension/services/context.yml | 36 +++++++ src/Knp/FriendlyExtension/services/core.yml | 22 +++++ .../FriendlyExtension/services/guesser.yml | 6 ++ .../FriendlyExtension/services/symfony.yml | 19 ++-- 37 files changed, 599 insertions(+), 86 deletions(-) create mode 100644 src/Knp/FriendlyExtension/Context/Context.php create mode 100644 src/Knp/FriendlyExtension/Context/ContextInterface.php create mode 100644 src/Knp/FriendlyExtension/Context/EntityContext.php create mode 100644 src/Knp/FriendlyExtension/Context/Helper/AbstractHelper.php create mode 100644 src/Knp/FriendlyExtension/Context/Helper/Registry.php create mode 100644 src/Knp/FriendlyExtension/Context/Initializer/FriendlyInitializer.php create mode 100644 src/Knp/FriendlyExtension/DependencyInjection/Compiler/ContextHelperRegistrationPass.php create mode 100644 src/Knp/FriendlyExtension/DependencyInjection/Compiler/SymfonyServicePass.php create mode 100644 src/Knp/FriendlyExtension/Type/Guesser/ArrayGuesser.php create mode 100644 src/Knp/FriendlyExtension/Type/Guesser/CollectionGuesser.php create mode 100644 src/Knp/FriendlyExtension/Utils/ObjectWrapper.php create mode 100644 src/Knp/FriendlyExtension/services/context.yml diff --git a/spec/Knp/FriendlyExtension/Utils/NameProposerSpec.php b/spec/Knp/FriendlyExtension/Utils/NameProposerSpec.php index 09d1391e..d1afe60e 100755 --- a/spec/Knp/FriendlyExtension/Utils/NameProposerSpec.php +++ b/spec/Knp/FriendlyExtension/Utils/NameProposerSpec.php @@ -8,9 +8,9 @@ class NameProposerSpec extends ObjectBehavior { - function let(TextFormater $formater) + function let() { - $this->beConstructedWith($formater); + $this->beConstructedWith(new TextFormater); } function it_is_initializable() @@ -18,10 +18,53 @@ function it_is_initializable() $this->shouldHaveType('Knp\FriendlyExtension\Utils\NameProposer'); } - function it_propose_a_set_of_names() + function it_build_proposals() { - $this->buildProposals('the_test')->shoulwReturn([ + $this->buildProposals('Product')->shouldReturn([ + 'PRODUCT', + 'Product', + 'product', + ]); + } + + function it_build_proposals_with_plurials() + { + $this->buildProposals('Product', true)->shouldReturn([ + 'PRODUCT', + 'PRODUCTS', + 'Product', + 'Products', + 'product', + 'products', + ]); + } + function it_build_proposals_from_complex_string() + { + $this->buildProposals('Order item', true)->shouldReturn([ + "ORDER ITEM", + "ORDER ITEMS", + "ORDERITEM", + "ORDERITEMS", + "ORDER_ITEM", + "ORDER_ITEMS", + "Order item", + "Order items", + "order item", + "order items", + "orderItem", + "orderItems", + "order_item", + "order_items", + "orderitem", + "orderitems", ]); } + + function it_should_detect_matches() + { + $this->match('product', 'Product')->shouldReturn(true); + $this->match('product item', 'ProductItem')->shouldReturn(true); + $this->match('product items', 'ProductItem', true)->shouldReturn(true); + } } diff --git a/src/Knp/FriendlyExtension.php b/src/Knp/FriendlyExtension.php index 775ac112..f6567c8c 100755 --- a/src/Knp/FriendlyExtension.php +++ b/src/Knp/FriendlyExtension.php @@ -6,10 +6,12 @@ use Behat\Testwork\ServiceContainer\ExtensionManager; use Faker\Factory; use Knp\FriendlyExtension\DependencyInjection\Compiler\ApiUrlTransitionPass; +use Knp\FriendlyExtension\DependencyInjection\Compiler\ContextHelperRegistrationPass; use Knp\FriendlyExtension\DependencyInjection\Compiler\FakerGuesserRegistrationPass; use Knp\FriendlyExtension\DependencyInjection\Compiler\FakerProviderRegistrationPass; use Knp\FriendlyExtension\DependencyInjection\Compiler\KernelRegistrationPass; use Knp\FriendlyExtension\DependencyInjection\Compiler\ParameterBuildingPass; +use Knp\FriendlyExtension\DependencyInjection\Compiler\SymfonyServicePass; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -99,6 +101,7 @@ public function configure(ArrayNodeDefinition $builder) public function load(ContainerBuilder $container, array $config) { $loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/FriendlyExtension/services')); + $loader->load('context.yml'); $loader->load('core.yml'); $loader->load('faker.yml'); $loader->load('guesser.yml'); @@ -111,13 +114,11 @@ public function load(ContainerBuilder $container, array $config) $container->addCompilerPass(new FakerProviderRegistrationPass); $container->addCompilerPass(new FakerGuesserRegistrationPass); $container->addCompilerPass(new ApiUrlTransitionPass); + $container->addCompilerPass(new ContextHelperRegistrationPass); + $container->addCompilerPass(new SymfonyServicePass); } public function process(ContainerBuilder $container) { - foreach ($container->getServiceIds() as $id) { - echo $id; - echo "\n"; - } } } diff --git a/src/Knp/FriendlyExtension/Context/Context.php b/src/Knp/FriendlyExtension/Context/Context.php new file mode 100644 index 00000000..07ce20de --- /dev/null +++ b/src/Knp/FriendlyExtension/Context/Context.php @@ -0,0 +1,21 @@ +registry = $registry; + } + + protected function get($name) + { + return $this->registry->get($name); + } +} diff --git a/src/Knp/FriendlyExtension/Context/ContextInterface.php b/src/Knp/FriendlyExtension/Context/ContextInterface.php new file mode 100644 index 00000000..b13dbe32 --- /dev/null +++ b/src/Knp/FriendlyExtension/Context/ContextInterface.php @@ -0,0 +1,11 @@ +getColumnsHash(); + + foreach ($data as $values) { + $entity = $this->get('entity')->createNew($name); + $this->get('entity')->hydrate($entity, $values); + $this->get('entity')->complete($entity); + $this->get('doctrine')->persist($entity); + } + + $this->get('doctrine')->flush(); + } +} diff --git a/src/Knp/FriendlyExtension/Context/Helper/AbstractHelper.php b/src/Knp/FriendlyExtension/Context/Helper/AbstractHelper.php new file mode 100644 index 00000000..606692c6 --- /dev/null +++ b/src/Knp/FriendlyExtension/Context/Helper/AbstractHelper.php @@ -0,0 +1,20 @@ +registry = $registry; + } + + public function get($name) + { + return $this->registry->get($name); + } +} diff --git a/src/Knp/FriendlyExtension/Context/Helper/AsserterHelper.php b/src/Knp/FriendlyExtension/Context/Helper/AsserterHelper.php index b605fad7..dcf7e5d0 100755 --- a/src/Knp/FriendlyExtension/Context/Helper/AsserterHelper.php +++ b/src/Knp/FriendlyExtension/Context/Helper/AsserterHelper.php @@ -2,10 +2,10 @@ namespace Knp\FriendlyExtension\Context\Helper; -use Knp\FriendlyExtension\Context\Helper\HelperInterface; +use Knp\FriendlyExtension\Context\Helper\AbstractHelper; use Knp\FriendlyExtension\Utils\TextFormater; -class AsserterHelper implements HelperInterface +class AsserterHelper extends AbstractHelper { protected $formater; @@ -19,6 +19,10 @@ public function getName() return 'asserter'; } + public function clear() + { + } + public function assertArrayEquals(array $expected, array $real, $fullText = false) { $message = sprintf("The given array\r\n\r\n%s\r\nis not equals to expected\r\n\r\n%s", $this->explode($real), $this->explode($expected)); diff --git a/src/Knp/FriendlyExtension/Context/Helper/DoctrineHelper.php b/src/Knp/FriendlyExtension/Context/Helper/DoctrineHelper.php index 82c6dd08..1f1dd44b 100755 --- a/src/Knp/FriendlyExtension/Context/Helper/DoctrineHelper.php +++ b/src/Knp/FriendlyExtension/Context/Helper/DoctrineHelper.php @@ -4,10 +4,10 @@ use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Tools\SchemaTool; -use Knp\FriendlyExtension\Context\Helper\HelperInterface; +use Knp\FriendlyExtension\Context\Helper\AbstractHelper; use Knp\FriendlyExtension\Doctrine\Resolver; -class DoctrineHelper implements HelperInterface +class DoctrineHelper extends AbstractHelper { private $em; private $resolver; @@ -25,7 +25,25 @@ public function getName() public function getClass($name) { + return class_exists($name) + ? $name + : $this->resolver->resolveEntity($name, true) + ; + } + public function getRepository($name) + { + return $this->em->getRepository($this->getClass($name)); + } + + public function all($name) + { + return $this + ->getRepository($name) + ->createQueryBuilder('o') + ->getQuery() + ->getResult() + ; } public function refresh($entity) @@ -48,11 +66,6 @@ public function flush($entity = null) $this->em->flush($entity); } - /** - * Reset the schema, clear the entity manager - * - * @return void - */ public function reset() { $metadata = $this @@ -66,7 +79,10 @@ public function reset() $tool->dropSchema($metadata); $tool->createSchema($metadata); } + } + public function clear() + { $this->em->clear(); } } diff --git a/src/Knp/FriendlyExtension/Context/Helper/EntityHelper.php b/src/Knp/FriendlyExtension/Context/Helper/EntityHelper.php index 3aaba07b..7f354577 100755 --- a/src/Knp/FriendlyExtension/Context/Helper/EntityHelper.php +++ b/src/Knp/FriendlyExtension/Context/Helper/EntityHelper.php @@ -3,35 +3,110 @@ namespace Knp\FriendlyExtension\Context\Helper; use Doctrine\ORM\EntityManagerInterface; -use Knp\FriendlyExtension\Context\Helper\HelperInterface; -use Knp\FriendlyExtension\Entity\Hydrator; +use Knp\FriendlyExtension\Context\Helper\AbstractHelper; +use Knp\FriendlyExtension\Doctrine\Resolver; +use Knp\FriendlyExtension\Faker\UniqueCache; use Knp\FriendlyExtension\Record\Collection\Bag; +use Knp\FriendlyExtension\Type\GuesserRegistry; +use Symfony\Component\PropertyAccess\PropertyAccess; -class EntityHelper implements HelperInterface +class EntityHelper extends AbstractHelper { private $bag; - public function __construct(EntityManagerInterface $em, Hydrator $hydrator, Bag $bag) + public function __construct(Resolver $resolver, Bag $bag, UniqueCache $cache, GuesserRegistry $registry) { - $this->em = $em; - $this->hydrator = $hydrator; - $this->bag = $bag; + $this->resolver = $resolver; + $this->bag = $bag; + $this->cache = $cache; + $this->registry = $registry; } public function getName() { - return 'doctrine'; + return 'entity'; + } + + public function clear() + { + $this->cache->clear(); + $this->bag->clear(); } public function createNew($name) { - $class = $this->doctrineHelper->getClass($name); + $class = $this->get('doctrine')->getClass($name); - $entity = (new \ReflectionClass($class))->newInstanceWithoutConstructor(); + return (new \ReflectionClass($class))->newInstanceWithoutConstructor(); } public function hydrate($entity, array $values) { + foreach ($values as $property => $value) { + $mapping = $this->resolver->getMetadataFor($entity, $property); + + PropertyAccess::getPropertyAccessor() + ->setValue( + $entity, + $mapping['fieldName'], + $this->format($mapping, $value) + ) + ; + } + } + + public function complete($entity) + { + $metadata = array_merge( + $this->resolver->getMetadataFor($entity)->fieldMappings, + $this->resolver->getMetadataFor($entity)->associationMappings + ); + $accessor = PropertyAccess::getPropertyAccessor(); + + foreach ($metadata as $property => $mapping) { + if (false === $metadata->isNullable($property) && null === $accessor->getValue($entity, $property)) { + $accessor ->setValue( + $entity, + $mapping['fieldName'], + $this->fake($mapping) + ); + } + } + } + + public function getDiff($name) + { + $class = $this->get('doctrine')->getClass($name); + $existing = $this->get('doctrine')->all($class); + $collection = $this->bag->getCollection($class); + $registered = array_map(function ($e) { return $e->getEntity(); }, $collection->all()); + + return [ + 'created' => array_diff($existing, $registered), + 'deleted' => array_diff($registered, $existing), + ]; + } + + private function format(array $mapping, $value) + { + if (false === $guesser = $this->registry->find($mapping)) { + + return $value; + } + + return $guesser->transform($value, $mapping); + } + + private function fake($mapping) + { + if (false === $guesser = $this->registry->find($mapping)) { + throw new \Exception(sprintf('There is no fake solution for "%s" typed fields', $mapping['type'])); + } + if (true === $mapping['unique']) { + return $this->cache->generate($className, $mapping['fieldName'], function () use ($guesser, $mapping) { + return $guesser->fake($mapping); + }); + } } } diff --git a/src/Knp/FriendlyExtension/Context/Helper/HelperInterface.php b/src/Knp/FriendlyExtension/Context/Helper/HelperInterface.php index 6c7b94b0..19c7729e 100755 --- a/src/Knp/FriendlyExtension/Context/Helper/HelperInterface.php +++ b/src/Knp/FriendlyExtension/Context/Helper/HelperInterface.php @@ -2,7 +2,11 @@ namespace Knp\FriendlyExtension\Context\Helper; +use Knp\FriendlyExtension\Context\Helper\Registry; + interface HelperInterface { + public function setRegistry(Registry $registry); public function getName(); + public function clear(); } diff --git a/src/Knp/FriendlyExtension/Context/Helper/Registry.php b/src/Knp/FriendlyExtension/Context/Helper/Registry.php new file mode 100644 index 00000000..52836c1e --- /dev/null +++ b/src/Knp/FriendlyExtension/Context/Helper/Registry.php @@ -0,0 +1,28 @@ +helpers[] = $helper; + $helper->setRegistry($this); + } + + public function get($name) + { + foreach ($this->helpers as $helper) { + if ($name === $helper->getName()) { + + return $helper; + } + } + + throw new \Exception(sprintf('Unable to find a context helper named "%s"', $name)); + } +} diff --git a/src/Knp/FriendlyExtension/Context/Initializer/FriendlyInitializer.php b/src/Knp/FriendlyExtension/Context/Initializer/FriendlyInitializer.php new file mode 100644 index 00000000..2256b153 --- /dev/null +++ b/src/Knp/FriendlyExtension/Context/Initializer/FriendlyInitializer.php @@ -0,0 +1,31 @@ +registry = $registry; + } + + public function initializeContext(Context $context) + { + if (false === $this->supports($context)) { + + return; + } + + $context->setHelperRegistry($this->registry); + } + + private function supports($context) + { + return $context instanceof ContextInterface; + } +} diff --git a/src/Knp/FriendlyExtension/DependencyInjection/Compiler/ContextHelperRegistrationPass.php b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/ContextHelperRegistrationPass.php new file mode 100644 index 00000000..6e1637ee --- /dev/null +++ b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/ContextHelperRegistrationPass.php @@ -0,0 +1,20 @@ +findTaggedServiceIds('friendly.context.helper')); + $regitry = $container->getDefinition('friendly.context.helper.registry'); + + foreach ($helpers as $helper) { + $regitry->addMethodCall('addHelper', [ new Reference($helper) ]); + } + } +} diff --git a/src/Knp/FriendlyExtension/DependencyInjection/Compiler/FakerProviderRegistrationPass.php b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/FakerProviderRegistrationPass.php index d459b713..5bb49aac 100755 --- a/src/Knp/FriendlyExtension/DependencyInjection/Compiler/FakerProviderRegistrationPass.php +++ b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/FakerProviderRegistrationPass.php @@ -49,6 +49,7 @@ private function buildBaseProviderDefinition() { return (new Definition()) ->setClass('Knp\FriendlyExtension\Faker\Provider\Base') + ->addArgument(new Reference('friendly.faker.generator')) ; } } diff --git a/src/Knp/FriendlyExtension/DependencyInjection/Compiler/SymfonyServicePass.php b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/SymfonyServicePass.php new file mode 100644 index 00000000..4e226aa3 --- /dev/null +++ b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/SymfonyServicePass.php @@ -0,0 +1,28 @@ +findTaggedServiceIds('friendly.symfony.service'); + + foreach ($services as $id => $options) { + if (null === $kernel = $this->getKernel($container)) { + $container->set($id, (new ReflectionClass($options['class']))->createInstanceWithoutConstructor()); + } else { + $kernel->boot(); + $container->set($id, $kernel->getContainer()->get($id)); + } + } + } + + private function getKernel(ContainerBuilder $container) + { + return $container->get('friendly.symfony.kernel', ContainerBuilder::NULL_ON_INVALID_REFERENCE); + } +} diff --git a/src/Knp/FriendlyExtension/Doctrine/Resolver.php b/src/Knp/FriendlyExtension/Doctrine/Resolver.php index 4334802a..490c007b 100755 --- a/src/Knp/FriendlyExtension/Doctrine/Resolver.php +++ b/src/Knp/FriendlyExtension/Doctrine/Resolver.php @@ -27,7 +27,7 @@ public function resolveEntity($name, $onlyOne = false) $results = []; foreach ($this->getMetadata() as $metadata) { - if ($this->proposer->match($name, $this->reflector->getClassShortName($metadata->name))) { + if ($this->proposer->match($name, $this->reflector->getClassName($metadata->name), true)) { $results[] = $this->reflector->getClassLongName($metadata->name); } } @@ -42,13 +42,22 @@ public function resolveEntity($name, $onlyOne = false) } return $onlyOne - ? empty($entities) ? null : current($entities) - : $entities + ? empty($results) ? null : current($results) + : $results ; } public function getMetadataFor($class, $property = null) { + if (is_object($class)) { + $class = get_class($class); + } elseif (is_string($class)) { + $class = (string)$class; + } else { + + throw new \Exception('Need string or object'); + } + $metadata = $this->em->getMetadataFactory()->getMetadataFor($class); if (null === $property) { diff --git a/src/Knp/FriendlyExtension/Entity/Hydrator.php b/src/Knp/FriendlyExtension/Entity/Hydrator.php index dde178ac..c9614c0e 100755 --- a/src/Knp/FriendlyExtension/Entity/Hydrator.php +++ b/src/Knp/FriendlyExtension/Entity/Hydrator.php @@ -53,11 +53,6 @@ public function hydrate(ObjectManager $em, $entity, $values) return $this; } - public function completeRequired(ObjectManager $em, $entity) - { - $this->completeFields($em, $entity); - } - public function completeFields(ObjectManager $em, $entity) { $accessor = PropertyAccess::getPropertyAccessor(); diff --git a/src/Knp/FriendlyExtension/Type/Guesser/AbstractGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/AbstractGuesser.php index 8f802196..894374d7 100755 --- a/src/Knp/FriendlyExtension/Type/Guesser/AbstractGuesser.php +++ b/src/Knp/FriendlyExtension/Type/Guesser/AbstractGuesser.php @@ -3,35 +3,16 @@ namespace Knp\FriendlyExtension\Type\Guesser; use Knp\FriendlyExtension\Faker\Provider\Base; -use Knp\FriendlyExtension\Type\GuesserRegistry; use Knp\FriendlyExtension\Type\Guesser\GuesserInterface; abstract class AbstractGuesser implements GuesserInterface { - protected $manager; protected $fakers = []; - public function getManager() - { - return $this->manager; - } - - public function setManager(GuesserRegistry $manager) - { - $this->manager = $manager; - - return $this; - } - public function addFaker(Base $faker) { if (null !== $faker->getParent()) { $this->fakers[] = $faker; } } - - protected function get($name) - { - return $this->getManager()->getContainer()->get($name); - } } diff --git a/src/Knp/FriendlyExtension/Type/Guesser/ArrayGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/ArrayGuesser.php new file mode 100644 index 00000000..a4b699d3 --- /dev/null +++ b/src/Knp/FriendlyExtension/Type/Guesser/ArrayGuesser.php @@ -0,0 +1,59 @@ +registry = $registry; + $this->formater = $formater; + } + + public function supports(array $mapping) + { + $mapping = array_merge([ 'type' => null ], $mapping); + + return 'array' === $mapping['type']; + } + + public function transform($str, array $mapping = null) + { + return array_map( + function ($e) use ($mapping) { + unset($mapping['type']); + return $this->format($mapping, $e); + }, + $this->formater->listToArray($value) + ); + } + + public function fake(array $mapping) + { + return []; + } + + public function getName() + { + return 'array'; + } + + private function format($mapping, $value) + { + if (false === $guesser = $this->guesserManager->find($mapping)) { + + return $value; + } + + return $guesser->transform($value, $mapping); + } +} diff --git a/src/Knp/FriendlyExtension/Type/Guesser/BigintGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/BigintGuesser.php index 9b729806..0e859e15 100755 --- a/src/Knp/FriendlyExtension/Type/Guesser/BigintGuesser.php +++ b/src/Knp/FriendlyExtension/Type/Guesser/BigintGuesser.php @@ -2,10 +2,18 @@ namespace Knp\FriendlyExtension\Type\Guesser; +use Knp\FriendlyExtension\Type\Guesser\AbstractGuesser; use Knp\FriendlyExtension\Type\Guesser\IntGuesser; -class BigintGuesser extends IntGuesser +final class BigintGuesser extends AbstractGuesser { + private $intGuesser; + + public function __construct(IntGuesser $intGuesser) + { + $this->intGuesser = $intGuesser; + } + public function supports(array $mapping) { $mapping = array_merge([ 'type' => null ], $mapping); @@ -13,6 +21,12 @@ public function supports(array $mapping) return $mapping['type'] === 'bigint'; } + public function transform($str, array $mapping = null) + { + return $this->intGuesser->transform($str, $mapping); + } + + public function fake(array $mapping) { return current($this->fakers)->fake('randomNumber'); diff --git a/src/Knp/FriendlyExtension/Type/Guesser/BooleanGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/BooleanGuesser.php index 09d4a1c3..a81c2bec 100755 --- a/src/Knp/FriendlyExtension/Type/Guesser/BooleanGuesser.php +++ b/src/Knp/FriendlyExtension/Type/Guesser/BooleanGuesser.php @@ -4,7 +4,7 @@ use Knp\FriendlyExtension\Type\Guesser\AbstractGuesser; -class BooleanGuesser extends AbstractGuesser +final class BooleanGuesser extends AbstractGuesser { public function supports(array $mapping) { diff --git a/src/Knp/FriendlyExtension/Type/Guesser/CollectionGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/CollectionGuesser.php new file mode 100644 index 00000000..f6db2be9 --- /dev/null +++ b/src/Knp/FriendlyExtension/Type/Guesser/CollectionGuesser.php @@ -0,0 +1,42 @@ +arrayGuesser = $arrayGuesser; + } + + public function supports(array $mapping) + { + $mapping = array_merge([ 'type' => null ], $mapping); + + return in_array($mapping['type'], [ClassMetadata::ONE_TO_MANY, ClassMetadata::MANY_TO_MANY]); + } + + public function transform($str, array $mapping = null) + { + return new ArrayCollection( + $this->arrayGuesser->transform($str, $mapping) + ); + } + + public function fake(array $mapping) + { + return new ArrayCollection( + $this->arrayGuesser->fake($mapping) + ); + } + + public function getName() + { + return 'array'; + } +} diff --git a/src/Knp/FriendlyExtension/Type/Guesser/DatetimeGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/DatetimeGuesser.php index 194479b6..255c650c 100755 --- a/src/Knp/FriendlyExtension/Type/Guesser/DatetimeGuesser.php +++ b/src/Knp/FriendlyExtension/Type/Guesser/DatetimeGuesser.php @@ -4,7 +4,7 @@ use Knp\FriendlyExtension\Type\Guesser\AbstractGuesser; -class DatetimeGuesser extends AbstractGuesser +final class DatetimeGuesser extends AbstractGuesser { public function supports(array $mapping) { diff --git a/src/Knp/FriendlyExtension/Type/Guesser/DecimalGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/DecimalGuesser.php index 2c67f543..6c2d4988 100755 --- a/src/Knp/FriendlyExtension/Type/Guesser/DecimalGuesser.php +++ b/src/Knp/FriendlyExtension/Type/Guesser/DecimalGuesser.php @@ -4,7 +4,7 @@ use Knp\FriendlyExtension\Type\Guesser\AbstractGuesser; -class DecimalGuesser extends AbstractGuesser +final class DecimalGuesser extends AbstractGuesser { public function supports(array $mapping) { diff --git a/src/Knp/FriendlyExtension/Type/Guesser/EntityGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/EntityGuesser.php index de987dee..6a44e62b 100755 --- a/src/Knp/FriendlyExtension/Type/Guesser/EntityGuesser.php +++ b/src/Knp/FriendlyExtension/Type/Guesser/EntityGuesser.php @@ -5,7 +5,7 @@ use Knp\FriendlyExtension\Record\Collection\Bag; use Knp\FriendlyExtension\Type\Guesser\AbstractGuesser; -class EntityGuesser extends AbstractGuesser +final class EntityGuesser extends AbstractGuesser { public function __construct(Bag $bag) { diff --git a/src/Knp/FriendlyExtension/Type/Guesser/GuesserInterface.php b/src/Knp/FriendlyExtension/Type/Guesser/GuesserInterface.php index 1abda5a4..bbdc293b 100755 --- a/src/Knp/FriendlyExtension/Type/Guesser/GuesserInterface.php +++ b/src/Knp/FriendlyExtension/Type/Guesser/GuesserInterface.php @@ -12,9 +12,5 @@ public function transform($str, array $mapping); public function fake(array $mapping); - public function getManager(); - - public function setManager(GuesserRegistry $manager); - public function getName(); } diff --git a/src/Knp/FriendlyExtension/Type/Guesser/IntGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/IntGuesser.php index fc776126..5ba6ae73 100755 --- a/src/Knp/FriendlyExtension/Type/Guesser/IntGuesser.php +++ b/src/Knp/FriendlyExtension/Type/Guesser/IntGuesser.php @@ -4,7 +4,7 @@ use Knp\FriendlyExtension\Type\Guesser\AbstractGuesser; -class IntGuesser extends AbstractGuesser +final class IntGuesser extends AbstractGuesser { public function supports(array $mapping) { diff --git a/src/Knp/FriendlyExtension/Type/Guesser/SmallintGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/SmallintGuesser.php index 18b53d2d..945eb242 100755 --- a/src/Knp/FriendlyExtension/Type/Guesser/SmallintGuesser.php +++ b/src/Knp/FriendlyExtension/Type/Guesser/SmallintGuesser.php @@ -2,10 +2,18 @@ namespace Knp\FriendlyExtension\Type\Guesser; +use Knp\FriendlyExtension\Type\Guesser\AbstractGuesser; use Knp\FriendlyExtension\Type\Guesser\IntGuesser; -class SmallintGuesser extends IntGuesser +final class SmallintGuesser extends AbstractGuesser { + private $intGuesser; + + public function __construct(IntGuesser $intGuesser) + { + $this->intGuesser = $intGuesser; + } + public function supports(array $mapping) { $mapping = array_merge([ 'type' => null ], $mapping); @@ -13,6 +21,11 @@ public function supports(array $mapping) return $mapping['type'] === 'smallint'; } + public function transform($str, array $mapping = null) + { + return $this->intGuesser->transform($str, $mapping); + } + public function fake(array $mapping) { return $this->faker->fake('numberBetween', [0, 32000]); diff --git a/src/Knp/FriendlyExtension/Type/Guesser/StringGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/StringGuesser.php index 410827b3..a735f144 100755 --- a/src/Knp/FriendlyExtension/Type/Guesser/StringGuesser.php +++ b/src/Knp/FriendlyExtension/Type/Guesser/StringGuesser.php @@ -4,7 +4,7 @@ use Knp\FriendlyExtension\Type\Guesser\AbstractGuesser; -class StringGuesser extends AbstractGuesser +final class StringGuesser extends AbstractGuesser { public function supports(array $mapping) { diff --git a/src/Knp/FriendlyExtension/Type/GuesserRegistry.php b/src/Knp/FriendlyExtension/Type/GuesserRegistry.php index d14c9895..b394d588 100755 --- a/src/Knp/FriendlyExtension/Type/GuesserRegistry.php +++ b/src/Knp/FriendlyExtension/Type/GuesserRegistry.php @@ -10,12 +10,10 @@ class GuesserRegistry public function addGuesser(GuesserInterface $guesser) { - $guesser->setManager($this); - array_unshift($this->guessers, $guesser); } - public function find($mapping) + public function find(array $mapping) { foreach ($this->guessers as $g) { if ($g->supports($mapping)) { diff --git a/src/Knp/FriendlyExtension/Utils/NameProposer.php b/src/Knp/FriendlyExtension/Utils/NameProposer.php index 150a1341..ac3eb9db 100755 --- a/src/Knp/FriendlyExtension/Utils/NameProposer.php +++ b/src/Knp/FriendlyExtension/Utils/NameProposer.php @@ -16,14 +16,15 @@ public function __construct(TextFormater $formater) public function match($subject, $expected, $pluralize = false) { - $proposals = $this->buildProposals($name, $pluralize); + $proposals = $this->buildProposals($expected, $pluralize); - return in_array($other, $proposals); + return in_array($subject, $proposals); } public function buildProposals($name, $pluralize = false) { $proposals = [ + $name, $this->formater->toCamelCase($name), $this->formater->toUnderscoreCase($name), $this->formater->toSpaceCase($name), @@ -37,10 +38,14 @@ public function buildProposals($name, $pluralize = false) } $proposals = array_merge( + $proposals, array_map('strtoupper', $proposals), array_map('strtolower', $proposals) ); - return array_unique($proposals); + $proposals = array_unique($proposals); + sort($proposals); + + return $proposals; } } diff --git a/src/Knp/FriendlyExtension/Utils/ObjectWrapper.php b/src/Knp/FriendlyExtension/Utils/ObjectWrapper.php new file mode 100644 index 00000000..ffd05718 --- /dev/null +++ b/src/Knp/FriendlyExtension/Utils/ObjectWrapper.php @@ -0,0 +1,13 @@ +wrapped = $wrapped; + } +} diff --git a/src/Knp/FriendlyExtension/Utils/TextFormater.php b/src/Knp/FriendlyExtension/Utils/TextFormater.php index 4503fca2..d1b2e645 100755 --- a/src/Knp/FriendlyExtension/Utils/TextFormater.php +++ b/src/Knp/FriendlyExtension/Utils/TextFormater.php @@ -13,7 +13,9 @@ public function toCamelCase($str) public function toUnderscoreCase($str) { - return Inflector::tableize($str); + return Inflector::tableize( + Inflector::classify($str) + ); } public function toSpaceCase($str) diff --git a/src/Knp/FriendlyExtension/services/context.yml b/src/Knp/FriendlyExtension/services/context.yml new file mode 100644 index 00000000..cb08578f --- /dev/null +++ b/src/Knp/FriendlyExtension/services/context.yml @@ -0,0 +1,36 @@ +services: + + friendly.context.initializer.friendly_initializer: + class: Knp\FriendlyExtension\Context\Initializer\FriendlyInitializer + arguments: + - @friendly.context.helper.registry + tags: + - { name: context.initializer } + + friendly.context.helper.registry: + class: Knp\FriendlyExtension\Context\Helper\Registry + + friendly.context.helper.doctrine_helper: + class: Knp\FriendlyExtension\Context\Helper\DoctrineHelper + arguments: + - @doctrine.orm.entity_manager + - @friendly.doctrine.resolver + tags: + - { name: friendly.context.helper } + + friendly.context.helper.entity_helper: + class: Knp\FriendlyExtension\Context\Helper\EntityHelper + arguments: + - @friendly.doctrine.resolver + - @friendly.record.collection.bag + - @friendly.faker.unique_cache + - @friendly.type.guesser_registry + tags: + - { name: friendly.context.helper } + + friendly.context.helper.asserter_helper: + class: Knp\FriendlyExtension\Context\Helper\AsserterHelper + arguments: + - @friendly.utils.text_formater + tags: + - { name: friendly.context.helper } diff --git a/src/Knp/FriendlyExtension/services/core.yml b/src/Knp/FriendlyExtension/services/core.yml index 0fd5b39b..2a2ec87c 100755 --- a/src/Knp/FriendlyExtension/services/core.yml +++ b/src/Knp/FriendlyExtension/services/core.yml @@ -4,3 +4,25 @@ services: class: Knp\FriendlyExtension\Doctrine\Resolver arguments: - @doctrine.orm.entity_manager + - @friendly.utils.object_reflector + - @friendly.utils.text_formater + - @friendly.utils.name_proposer + + friendly.record.collection.bag: + class: Knp\FriendlyExtension\Record\Collection\Bag + arguments: + - @friendly.utils.object_reflector + + friendly.faker.unique_cache: + class: Knp\FriendlyExtension\Faker\UniqueCache + + friendly.utils.object_reflector: + class: Knp\FriendlyExtension\Utils\ObjectReflector + + friendly.utils.text_formater: + class: Knp\FriendlyExtension\Utils\TextFormater + + friendly.utils.name_proposer: + class: Knp\FriendlyExtension\Utils\NameProposer + arguments: + - @friendly.utils.text_formater diff --git a/src/Knp/FriendlyExtension/services/guesser.yml b/src/Knp/FriendlyExtension/services/guesser.yml index 549eac29..a69429fe 100755 --- a/src/Knp/FriendlyExtension/services/guesser.yml +++ b/src/Knp/FriendlyExtension/services/guesser.yml @@ -5,6 +5,8 @@ services: friendly.type.guesser.bigint_guesser: class: Knp\FriendlyExtension\Type\Guesser\BigintGuesser + arguments: + - @friendly.type.guesser.int_guesser tags: - { name: friendly.type.guesser } @@ -25,6 +27,8 @@ services: friendly.type.guesser.entity_guesser: class: Knp\FriendlyExtension\Type\Guesser\EntityGuesser + arguments: + - @friendly.record.collection.bag tags: - { name: friendly.type.guesser } @@ -35,6 +39,8 @@ services: friendly.type.guesser.smallint_guesser: class: Knp\FriendlyExtension\Type\Guesser\SmallintGuesser + arguments: + - @friendly.type.guesser.int_guesser tags: - { name: friendly.type.guesser } diff --git a/src/Knp/FriendlyExtension/services/symfony.yml b/src/Knp/FriendlyExtension/services/symfony.yml index 997028d4..6536c654 100755 --- a/src/Knp/FriendlyExtension/services/symfony.yml +++ b/src/Knp/FriendlyExtension/services/symfony.yml @@ -1,18 +1,11 @@ services: - friendly.symfony.service_shifter: - class: Knp\FriendlyExtension\Symfony\ServiceShifter - arguments: - - @service_container - doctrine: - class: Doctrine\ORM\Registry - factoryService: friendly.symfony.service_shifter - factoryMethod: get - arguments: [ doctrine ] + synthetic: true + tags: + - { name: friendly.symfony.service, class: Doctrine\ORM\Registry } doctrine.orm.entity_manager: - class: Doctrine\ORM\RegistryInterface - factoryService: friendly.symfony.service_shifter - factoryMethod: get - arguments: [ doctrine.orm.entity_manager ] + synthetic: true + tags: + - { name: friendly.symfony.service, class: Doctrine\ORM\EntityManager } From 479e7785606ab816134b00e7bd198495b40211e9 Mon Sep 17 00:00:00 2001 From: Pierre PLAZANET Date: Tue, 22 Jul 2014 14:04:17 +0200 Subject: [PATCH 07/33] WIP --- .../Context/Helper/AsserterHelper.php | 10 ++++++++++ .../Context/Helper/EntityHelper.php | 13 ++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/Knp/FriendlyExtension/Context/Helper/AsserterHelper.php b/src/Knp/FriendlyExtension/Context/Helper/AsserterHelper.php index dcf7e5d0..d0d05535 100755 --- a/src/Knp/FriendlyExtension/Context/Helper/AsserterHelper.php +++ b/src/Knp/FriendlyExtension/Context/Helper/AsserterHelper.php @@ -73,6 +73,16 @@ public function assertNotEquals($expected, $real, $message = "Failing to assert return $this->assert($expected !== $real, $message); } + public function assertNull($real, $message = "Failing to assert null.") + { + return $this->assertEquals(null, $real, $message); + } + + public function assertNotNull($real, $message = "Failing to assert not null.") + { + return $this->assertNotEquals(null, $real, $message); + } + public function assert($result, $message = "Assert failure") { if (false === $result) { diff --git a/src/Knp/FriendlyExtension/Context/Helper/EntityHelper.php b/src/Knp/FriendlyExtension/Context/Helper/EntityHelper.php index 7f354577..6dbde620 100755 --- a/src/Knp/FriendlyExtension/Context/Helper/EntityHelper.php +++ b/src/Knp/FriendlyExtension/Context/Helper/EntityHelper.php @@ -45,6 +45,8 @@ public function hydrate($entity, array $values) foreach ($values as $property => $value) { $mapping = $this->resolver->getMetadataFor($entity, $property); + $this->get('asserter')->assertNotNull($mapping, sprintf('No property named "%s" have been found', $property)); + PropertyAccess::getPropertyAccessor() ->setValue( $entity, @@ -57,14 +59,17 @@ public function hydrate($entity, array $values) public function complete($entity) { - $metadata = array_merge( + $mappings = array_merge( $this->resolver->getMetadataFor($entity)->fieldMappings, $this->resolver->getMetadataFor($entity)->associationMappings ); $accessor = PropertyAccess::getPropertyAccessor(); + $metadata = $this->resolver->getMetadataFor($entity); - foreach ($metadata as $property => $mapping) { - if (false === $metadata->isNullable($property) && null === $accessor->getValue($entity, $property)) { + foreach ($mappings as $property => $mapping) { + if (false === $metadata->isNullable($property) + && false === $metadata->isIdentifier($property) + && null === $accessor->getValue($entity, $property)) { $accessor ->setValue( $entity, $mapping['fieldName'], @@ -108,5 +113,7 @@ private function fake($mapping) return $guesser->fake($mapping); }); } + + return $guesser->fake($mapping); } } From e910bf341925e6a0e37a549b359e02846d5a8497 Mon Sep 17 00:00:00 2001 From: Pierre PLAZANET Date: Fri, 1 Aug 2014 17:41:01 +0200 Subject: [PATCH 08/33] Add event listener and new tag policy --- .../Gherkin/Node/ExplorerSpec.php | 57 ++++++++++++ src/Knp/FriendlyExtension.php | 8 ++ .../Context/EntityContext.php | 49 ++++++++++- .../Context/Helper/DoctrineHelper.php | 3 +- .../Context/Helper/EntityHelper.php | 27 +++--- .../Context/Helper/RecordHelper.php | 73 +++++++++++++++ .../EventListener/DoctrineSubscriber.php | 39 ++++++++ .../FriendlyExtension/Faker/Provider/Base.php | 2 +- .../Gherkin/Node/Explorer.php | 88 +++++++++++++++++++ .../FriendlyExtension/Record/Collection.php | 31 ++----- src/Knp/FriendlyExtension/Record/Record.php | 5 ++ .../Type/Guesser/ArrayGuesser.php | 2 +- .../FriendlyExtension/services/context.yml | 8 +- src/Knp/FriendlyExtension/services/core.yml | 9 ++ .../FriendlyExtension/services/guesser.yml | 15 ++++ 15 files changed, 375 insertions(+), 41 deletions(-) create mode 100644 spec/Knp/FriendlyExtension/Gherkin/Node/ExplorerSpec.php create mode 100644 src/Knp/FriendlyExtension/Context/Helper/RecordHelper.php create mode 100644 src/Knp/FriendlyExtension/EventListener/DoctrineSubscriber.php create mode 100644 src/Knp/FriendlyExtension/Gherkin/Node/Explorer.php diff --git a/spec/Knp/FriendlyExtension/Gherkin/Node/ExplorerSpec.php b/spec/Knp/FriendlyExtension/Gherkin/Node/ExplorerSpec.php new file mode 100644 index 00000000..639d7268 --- /dev/null +++ b/spec/Knp/FriendlyExtension/Gherkin/Node/ExplorerSpec.php @@ -0,0 +1,57 @@ +getTags()->willReturn([ + 'javascript', + 'reset-schema', + '~admin', + 'alice(Product)', + 'alice(User)', + ]); + $scenario->getTags()->willReturn([ + '~javascript', + 'admin', + 'alice(Prototype, Order)', + '~alice(User)', + ]); + + $this->beConstructedWith($feature); + } + + function it_is_initializable() + { + $this->shouldHaveType('Knp\FriendlyExtension\Gherkin\Node\Explorer'); + } + + function it_returns_feature_tags() + { + $this->getTags()->shouldReturn([ 'alice', 'javascript', 'reset-schema' ]); + } + + function it_returns_scenario_tags(FeatureNode $feature, ScenarioNode $scenario) + { + $this->beConstructedWith($feature, $scenario); + $this->getTags()->shouldReturn([ 'admin', 'alice', 'reset-schema' ]); + } + + function it_return_arguments() + { + $this->getArguments('alice')->shouldReturn([ 'Product', 'User' ]); + } + + function it_return_arguments_with_scenario(FeatureNode $feature, ScenarioNode $scenario) + { + $this->beConstructedWith($feature, $scenario); + $this->getArguments('alice')->shouldReturn([ 'Order', 'Product', 'Prototype' ]); + } +} diff --git a/src/Knp/FriendlyExtension.php b/src/Knp/FriendlyExtension.php index f6567c8c..66e54ced 100755 --- a/src/Knp/FriendlyExtension.php +++ b/src/Knp/FriendlyExtension.php @@ -53,6 +53,14 @@ public function configure(ArrayNodeDefinition $builder) ->end() ->end() ->end() + ->arrayNode('doctrine') + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('reset_schema') + ->defaultValue(false) + ->end() + ->end() + ->end() ->arrayNode('alice') ->addDefaultsIfNotSet() ->children() diff --git a/src/Knp/FriendlyExtension/Context/EntityContext.php b/src/Knp/FriendlyExtension/Context/EntityContext.php index 3a5f99db..5acd30f3 100644 --- a/src/Knp/FriendlyExtension/Context/EntityContext.php +++ b/src/Knp/FriendlyExtension/Context/EntityContext.php @@ -15,12 +15,53 @@ public function theFollowingEntities($name, TableNode $table) $data = $table->getColumnsHash(); foreach ($data as $values) { - $entity = $this->get('entity')->createNew($name); - $this->get('entity')->hydrate($entity, $values); - $this->get('entity')->complete($entity); - $this->get('doctrine')->persist($entity); + $this->buildEntity($name, $values); } $this->get('doctrine')->flush(); } + + /** + * @Given there is :count :name + * @Given there is :count :name like: + */ + public function thereIsEntities($count, $name, TableNode $table = null) + { + $data = $table ? $table->getColumnsHash() : [[]]; + + for ($i = 0; $i < $count; $i++) { + $values = $data[$i % count($data)]; + $this->buildEntity($name, $values); + } + + $this->get('doctrine')->flush(); + } + + /** + * @Then :count :name should have been :state + */ + public function entitiesShoudhaveBeen($count, $name, $state) + { + $diff = $this->get('entity')->getDiff($name); + $count = is_numeric($count) ? intval($count) : 0; + + if (false === array_key_exists($state, $diff)) { + + throw new \Exception(sprintf('Don\'t know how to get %s %s', $state, $name)); + } + + $message = sprintf('%s %s have been %s, %s expected', count($diff[$state]), $name, $state, $count); + $this->get('asserter')->assertEquals($count, count($diff[$state]), $message); + } + + public function buildEntity($name, array $values) + { + $entity = $this->get('entity')->createNew($name); + $this->get('entity')->hydrate($entity, $values); + $this->get('entity')->complete($entity); + $this->get('doctrine')->persist($entity); + $this->get('record')->attach($entity, $values); + + return $entity; + } } diff --git a/src/Knp/FriendlyExtension/Context/Helper/DoctrineHelper.php b/src/Knp/FriendlyExtension/Context/Helper/DoctrineHelper.php index 1f1dd44b..2a024813 100755 --- a/src/Knp/FriendlyExtension/Context/Helper/DoctrineHelper.php +++ b/src/Knp/FriendlyExtension/Context/Helper/DoctrineHelper.php @@ -66,8 +66,9 @@ public function flush($entity = null) $this->em->flush($entity); } - public function reset() + public function resetSchema() { + var_dump(true); $metadata = $this ->em ->getMetadataFactory() diff --git a/src/Knp/FriendlyExtension/Context/Helper/EntityHelper.php b/src/Knp/FriendlyExtension/Context/Helper/EntityHelper.php index 6dbde620..be43b38e 100755 --- a/src/Knp/FriendlyExtension/Context/Helper/EntityHelper.php +++ b/src/Knp/FriendlyExtension/Context/Helper/EntityHelper.php @@ -6,18 +6,14 @@ use Knp\FriendlyExtension\Context\Helper\AbstractHelper; use Knp\FriendlyExtension\Doctrine\Resolver; use Knp\FriendlyExtension\Faker\UniqueCache; -use Knp\FriendlyExtension\Record\Collection\Bag; use Knp\FriendlyExtension\Type\GuesserRegistry; use Symfony\Component\PropertyAccess\PropertyAccess; class EntityHelper extends AbstractHelper { - private $bag; - - public function __construct(Resolver $resolver, Bag $bag, UniqueCache $cache, GuesserRegistry $registry) + public function __construct(Resolver $resolver, UniqueCache $cache, GuesserRegistry $registry) { $this->resolver = $resolver; - $this->bag = $bag; $this->cache = $cache; $this->registry = $registry; } @@ -30,7 +26,6 @@ public function getName() public function clear() { $this->cache->clear(); - $this->bag->clear(); } public function createNew($name) @@ -83,15 +78,27 @@ public function getDiff($name) { $class = $this->get('doctrine')->getClass($name); $existing = $this->get('doctrine')->all($class); - $collection = $this->bag->getCollection($class); - $registered = array_map(function ($e) { return $e->getEntity(); }, $collection->all()); + $registered = $this->get('record')->find($class); return [ - 'created' => array_diff($existing, $registered), - 'deleted' => array_diff($registered, $existing), + 'created' => $this->buildDiff($existing, $registered), + 'deleted' => $this->buildDiff($registered, $existing), ]; } + private function buildDiff(array $base, array $other) + { + $diff = []; + + foreach ($base as $item) { + if (false === in_array($item, $other)) { + $diff[] = $item; + } + } + + return $diff; + } + private function format(array $mapping, $value) { if (false === $guesser = $this->registry->find($mapping)) { diff --git a/src/Knp/FriendlyExtension/Context/Helper/RecordHelper.php b/src/Knp/FriendlyExtension/Context/Helper/RecordHelper.php new file mode 100644 index 00000000..2a047839 --- /dev/null +++ b/src/Knp/FriendlyExtension/Context/Helper/RecordHelper.php @@ -0,0 +1,73 @@ +bag = $bag; + } + + public function getName() + { + return 'record'; + } + + public function clear() + { + $this->bag->clear(); + } + + public function getCollection($class) + { + return $this->bag->getCollection($class); + } + + public function find($class, $value = null) + { + $collection = $this->getCollection($class); + + if (null === $value) { + + return array_map(function ($e) { return $e->getEntity(); }, $collection->all()); + } + + return $collection->search($value); + } + + public function attach($entity, array $values) + { + $collection = $this->getCollection($entity); + + $collection->attach($entity, $this->buildValues($entity, $values)); + } + + private function buildValues($entity, array $values) + { + $collection = $this->getCollection($entity); + $accessor = PropertyAccess::getPropertyAccessor(); + + foreach ($collection->getHeaders() as $header) { + if (array_key_exists($header, $values)) { + continue; + } + try { + $value = $accessor->getValue($entity, $header); + if (is_scalar($value)) { + $values[$header] = $value; + } + } catch (\Exception $ex) { + unset($ex); + } + } + + return $values; + } +} diff --git a/src/Knp/FriendlyExtension/EventListener/DoctrineSubscriber.php b/src/Knp/FriendlyExtension/EventListener/DoctrineSubscriber.php new file mode 100644 index 00000000..f961e7b5 --- /dev/null +++ b/src/Knp/FriendlyExtension/EventListener/DoctrineSubscriber.php @@ -0,0 +1,39 @@ +resetSchema = $resetSchema; + $this->helper = $helper; + } + + public static function getSubscribedEvents() + { + return [ + 'tester.scenario_tested.before' => 'beforeScenario', + ]; + } + + public function beforeScenario(BeforeScenarioTested $event) + { + $explorer = new Explorer($event->getFeature(), $event->getScenario()); + + if ($this->resetSchema || $explorer->hasTag(self::RESET_TAG)) { + + $this->helper->resetSchema(); + } + } +} diff --git a/src/Knp/FriendlyExtension/Faker/Provider/Base.php b/src/Knp/FriendlyExtension/Faker/Provider/Base.php index fd2fb6fd..619d6fab 100755 --- a/src/Knp/FriendlyExtension/Faker/Provider/Base.php +++ b/src/Knp/FriendlyExtension/Faker/Provider/Base.php @@ -29,7 +29,7 @@ public function setParent(FakerBase $parent) return $this; } - public function supportsParent($parent) + public function supportsParent(FakerBase $parent) { return false; } diff --git a/src/Knp/FriendlyExtension/Gherkin/Node/Explorer.php b/src/Knp/FriendlyExtension/Gherkin/Node/Explorer.php new file mode 100644 index 00000000..832c6fde --- /dev/null +++ b/src/Knp/FriendlyExtension/Gherkin/Node/Explorer.php @@ -0,0 +1,88 @@ +feature = $feature; + $this->scenario = $scenario; + } + + public function getTags($values = false) + { + $results = []; + $this->extract($this->feature, $results); + if (null !== $this->scenario) { + $this->extract($this->scenario, $results); + } + + return $values ? $results : array_keys($results); + } + + public function hasTag($tag) + { + return in_array($tag, $this->getTags()); + } + + public function getArguments($tag) + { + if (false === $this->hasTag($tag)) { + + return; + } + + $tags = $this->getTags(true); + + return $tags[$tag]; + } + + private function extract(TaggedNodeInterface $element, array &$results) + { + foreach ($element->getTags() as $tag) + { + $negative = (0 === strpos($tag, '~')); + $tag = $negative ? substr($tag, 1) : $tag; + $matches = []; + if (0 !== preg_match('/^(.+)\((.*)\)$/', $tag, $matches)) { + list($str, $tag, $arguments) = $matches; + $arguments = explode(',', $arguments); + $arguments = array_map('trim', $arguments); + $arguments = array_filter($arguments, function ($e) { return false === empty($e); }); + if ($negative) { + foreach ($arguments as $argument) { + if ( + array_key_exists($tag, $results) + && false !== $index = array_search($argument, $results[$tag]) + ) { + unset($results[$tag][$index]); + } + } + } else { + foreach ($arguments as $argument) { + $results[$tag][] = $argument; + } + } + sort($results[$tag]); + } else { + if ($negative) { + if (array_key_exists($tag, $results)) { + unset($results[$tag]); + } + } else { + $results[$tag] = []; + } + } + } + + ksort($results); + } +} diff --git a/src/Knp/FriendlyExtension/Record/Collection.php b/src/Knp/FriendlyExtension/Record/Collection.php index b526856b..3ebb5959 100755 --- a/src/Knp/FriendlyExtension/Record/Collection.php +++ b/src/Knp/FriendlyExtension/Record/Collection.php @@ -44,9 +44,13 @@ public function setReferencial($entity) return $this; } - public function attach($entity, array $values = null) + public function getHeaders() + { + return $this->headers; + } + + public function attach($entity, array $values) { - $values = $values ?: $this->buildValues($entity); $this->mergeHeaders(array_keys($values)); $record = new Record($this->reflector, $this); @@ -60,7 +64,7 @@ public function attach($entity, array $values = null) public function search($value) { foreach ($this->records as $record) { - if ((string) $record === $value) { + if ($record->isStringable() && (string) $record === $value) { return $record; } } @@ -84,7 +88,7 @@ public function count() return count($this->records); } - protected function mergeHeaders($headers) + private function mergeHeaders($headers) { foreach ($headers as $header) { if (!in_array($header, $this->headers)) { @@ -92,23 +96,4 @@ protected function mergeHeaders($headers) } } } - - protected function buildValues($entity) - { - $result = []; - $accessor = PropertyAccess::getPropertyAccessor(); - - foreach ($this->headers as $header) { - try { - $value = $accessor->setValue($entity, $header); - if (is_scalar($value)) { - $result[$header] = $value; - } - } catch (\Exception $ex) { - unset($ex); - } - } - - return $result; - } } diff --git a/src/Knp/FriendlyExtension/Record/Record.php b/src/Knp/FriendlyExtension/Record/Record.php index 50e8dc15..6ce1317f 100755 --- a/src/Knp/FriendlyExtension/Record/Record.php +++ b/src/Knp/FriendlyExtension/Record/Record.php @@ -24,6 +24,11 @@ public function __toString() return (string) $this->entity; } + public function isStringable() + { + return method_exists($this->entity, '__toString'); + } + public function attach($entity, $values = []) { if (!$this->collection->support($entity)) { diff --git a/src/Knp/FriendlyExtension/Type/Guesser/ArrayGuesser.php b/src/Knp/FriendlyExtension/Type/Guesser/ArrayGuesser.php index a4b699d3..3658616b 100644 --- a/src/Knp/FriendlyExtension/Type/Guesser/ArrayGuesser.php +++ b/src/Knp/FriendlyExtension/Type/Guesser/ArrayGuesser.php @@ -23,7 +23,7 @@ public function supports(array $mapping) { $mapping = array_merge([ 'type' => null ], $mapping); - return 'array' === $mapping['type']; + return in_array($mapping['type'], [ 'array', 'json_array', 'simple_array' ]); } public function transform($str, array $mapping = null) diff --git a/src/Knp/FriendlyExtension/services/context.yml b/src/Knp/FriendlyExtension/services/context.yml index cb08578f..7dac00f8 100644 --- a/src/Knp/FriendlyExtension/services/context.yml +++ b/src/Knp/FriendlyExtension/services/context.yml @@ -22,12 +22,18 @@ services: class: Knp\FriendlyExtension\Context\Helper\EntityHelper arguments: - @friendly.doctrine.resolver - - @friendly.record.collection.bag - @friendly.faker.unique_cache - @friendly.type.guesser_registry tags: - { name: friendly.context.helper } + friendly.context.helper.record_helper: + class: Knp\FriendlyExtension\Context\Helper\RecordHelper + arguments: + - @friendly.record.collection.bag + tags: + - { name: friendly.context.helper } + friendly.context.helper.asserter_helper: class: Knp\FriendlyExtension\Context\Helper\AsserterHelper arguments: diff --git a/src/Knp/FriendlyExtension/services/core.yml b/src/Knp/FriendlyExtension/services/core.yml index 2a2ec87c..32500738 100755 --- a/src/Knp/FriendlyExtension/services/core.yml +++ b/src/Knp/FriendlyExtension/services/core.yml @@ -26,3 +26,12 @@ services: class: Knp\FriendlyExtension\Utils\NameProposer arguments: - @friendly.utils.text_formater + + friendly.event_listener.doctrine_subscriber: + class: Knp\FriendlyExtension\EventListener\DoctrineSubscriber + arguments: + - %friendly.doctrine.reset_schema% + - @friendly.context.helper.doctrine_helper + tags: + - { name: event_dispatcher.subscriber } + diff --git a/src/Knp/FriendlyExtension/services/guesser.yml b/src/Knp/FriendlyExtension/services/guesser.yml index a69429fe..cea122c2 100755 --- a/src/Knp/FriendlyExtension/services/guesser.yml +++ b/src/Knp/FriendlyExtension/services/guesser.yml @@ -3,6 +3,21 @@ services: friendly.type.guesser_registry: class: Knp\FriendlyExtension\Type\GuesserRegistry + friendly.type.guesser.array_guesser: + class: Knp\FriendlyExtension\Type\Guesser\ArrayGuesser + arguments: + - @friendly.type.guesser_registry + - @friendly.utils.text_formater + tags: + - { name: friendly.type.guesser } + + friendly.type.guesser.collection_guesser: + class: Knp\FriendlyExtension\Type\Guesser\CollectionGuesser + arguments: + - @friendly.type.guesser.array_guesser + tags: + - { name: friendly.type.guesser } + friendly.type.guesser.bigint_guesser: class: Knp\FriendlyExtension\Type\Guesser\BigintGuesser arguments: From 08fed764d6791a4bdaea08625266936ab4789905 Mon Sep 17 00:00:00 2001 From: Pierre PLAZANET Date: Thu, 21 Aug 2014 14:42:32 +0200 Subject: [PATCH 09/33] Refactor services --- .../Context/Helper/EntityHelper.php | 34 +++++++++++++------ .../Compiler/FakerGuesserRegistrationPass.php | 27 ++++++++++++--- .../FriendlyExtension/services/context.yml | 24 ++++++------- src/Knp/FriendlyExtension/services/core.yml | 31 ++++++++--------- src/Knp/FriendlyExtension/services/faker.yml | 2 +- .../FriendlyExtension/services/guesser.yml | 24 ++++++------- .../FriendlyExtension/services/symfony.yml | 8 ++--- 7 files changed, 90 insertions(+), 60 deletions(-) diff --git a/src/Knp/FriendlyExtension/Context/Helper/EntityHelper.php b/src/Knp/FriendlyExtension/Context/Helper/EntityHelper.php index be43b38e..c7fcbda4 100755 --- a/src/Knp/FriendlyExtension/Context/Helper/EntityHelper.php +++ b/src/Knp/FriendlyExtension/Context/Helper/EntityHelper.php @@ -54,17 +54,23 @@ public function hydrate($entity, array $values) public function complete($entity) { - $mappings = array_merge( - $this->resolver->getMetadataFor($entity)->fieldMappings, - $this->resolver->getMetadataFor($entity)->associationMappings - ); + $mappings = []; $accessor = PropertyAccess::getPropertyAccessor(); $metadata = $this->resolver->getMetadataFor($entity); + foreach ($this->resolver->getMetadataFor($entity)->fieldMappings as $property => $map) { + if (false === $metadata->isNullable($property) && false === $metadata->isIdentifier($property)) { + $mappings[$property] = $map; + } + } + foreach ($this->resolver->getMetadataFor($entity)->associationMappings as $property => $map) { + if (false === $metadata->isIdentifier($property)) { + $mappings[$property] = $map; + } + } + foreach ($mappings as $property => $mapping) { - if (false === $metadata->isNullable($property) - && false === $metadata->isIdentifier($property) - && null === $accessor->getValue($entity, $property)) { + if (null === $accessor->getValue($entity, $property)) { $accessor ->setValue( $entity, $mapping['fieldName'], @@ -115,10 +121,16 @@ private function fake($mapping) throw new \Exception(sprintf('There is no fake solution for "%s" typed fields', $mapping['type'])); } - if (true === $mapping['unique']) { - return $this->cache->generate($className, $mapping['fieldName'], function () use ($guesser, $mapping) { - return $guesser->fake($mapping); - }); + if (array_key_exists('unique', $mapping) && true === $mapping['unique']) { + return $this + ->cache + ->generate( + $className, + $mapping['fieldName'], + function () use ($guesser, $mapping) { + return $guesser->fake($mapping); + } + ); } return $guesser->fake($mapping); diff --git a/src/Knp/FriendlyExtension/DependencyInjection/Compiler/FakerGuesserRegistrationPass.php b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/FakerGuesserRegistrationPass.php index c251ba52..c7fda767 100755 --- a/src/Knp/FriendlyExtension/DependencyInjection/Compiler/FakerGuesserRegistrationPass.php +++ b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/FakerGuesserRegistrationPass.php @@ -10,10 +10,12 @@ class FakerGuesserRegistrationPass implements CompilerPassInterface { public function process(ContainerBuilder $container) { - $guessers = array_keys($container->findTaggedServiceIds('friendly.type.guesser')); - $fakers = array_keys($container->findTaggedServiceIds('friendly.faker.provider')); - - $regitry = $container->getDefinition('friendly.type.guesser_registry'); + $guessers = $container->findTaggedServiceIds('friendly.type.guesser'); + $priorities = $this->getPriorities($guessers); + $guessers = array_keys($guessers); + $fakers = array_keys($container->findTaggedServiceIds('friendly.faker.provider')); + $regitry = $container->getDefinition('friendly.type.guesser_registry'); + array_multisort($priorities, SORT_ASC, SORT_REGULAR, $guessers); foreach ($guessers as $guesser) { $definition = $container->getDefinition($guesser); @@ -23,4 +25,21 @@ public function process(ContainerBuilder $container) $regitry->addMethodCall('addGuesser', [ new Reference($guesser) ]); } } + + public function getPriorities(array $services) + { + $priorities = []; + + foreach ($services as $service) { + $priority = 0; + foreach ($service as $tag) { + if (array_key_exists('priority', $tag)) { + $priority = 0 - $tag['priority']; + } + } + $priorities[] = $priority; + } + + return $priorities; + } } diff --git a/src/Knp/FriendlyExtension/services/context.yml b/src/Knp/FriendlyExtension/services/context.yml index 7dac00f8..28792440 100644 --- a/src/Knp/FriendlyExtension/services/context.yml +++ b/src/Knp/FriendlyExtension/services/context.yml @@ -1,14 +1,10 @@ services: - - friendly.context.initializer.friendly_initializer: - class: Knp\FriendlyExtension\Context\Initializer\FriendlyInitializer + friendly.context.helper.asserter_helper: + class: Knp\FriendlyExtension\Context\Helper\AsserterHelper arguments: - - @friendly.context.helper.registry + - @friendly.utils.text_formater tags: - - { name: context.initializer } - - friendly.context.helper.registry: - class: Knp\FriendlyExtension\Context\Helper\Registry + - { name: friendly.context.helper } friendly.context.helper.doctrine_helper: class: Knp\FriendlyExtension\Context\Helper\DoctrineHelper @@ -34,9 +30,13 @@ services: tags: - { name: friendly.context.helper } - friendly.context.helper.asserter_helper: - class: Knp\FriendlyExtension\Context\Helper\AsserterHelper + friendly.context.helper.registry: + class: Knp\FriendlyExtension\Context\Helper\Registry + + friendly.context.initializer.friendly_initializer: + class: Knp\FriendlyExtension\Context\Initializer\FriendlyInitializer arguments: - - @friendly.utils.text_formater + - @friendly.context.helper.registry tags: - - { name: friendly.context.helper } + - { name: context.initializer } + diff --git a/src/Knp/FriendlyExtension/services/core.yml b/src/Knp/FriendlyExtension/services/core.yml index 32500738..995c65cc 100755 --- a/src/Knp/FriendlyExtension/services/core.yml +++ b/src/Knp/FriendlyExtension/services/core.yml @@ -1,5 +1,4 @@ services: - friendly.doctrine.resolver: class: Knp\FriendlyExtension\Doctrine\Resolver arguments: @@ -8,30 +7,30 @@ services: - @friendly.utils.text_formater - @friendly.utils.name_proposer - friendly.record.collection.bag: - class: Knp\FriendlyExtension\Record\Collection\Bag + friendly.event_listener.doctrine_subscriber: + class: Knp\FriendlyExtension\EventListener\DoctrineSubscriber arguments: - - @friendly.utils.object_reflector + - %friendly.doctrine.reset_schema% + - @friendly.context.helper.doctrine_helper + tags: + - { name: event_dispatcher.subscriber } friendly.faker.unique_cache: class: Knp\FriendlyExtension\Faker\UniqueCache - friendly.utils.object_reflector: - class: Knp\FriendlyExtension\Utils\ObjectReflector - - friendly.utils.text_formater: - class: Knp\FriendlyExtension\Utils\TextFormater + friendly.record.collection.bag: + class: Knp\FriendlyExtension\Record\Collection\Bag + arguments: + - @friendly.utils.object_reflector friendly.utils.name_proposer: class: Knp\FriendlyExtension\Utils\NameProposer arguments: - @friendly.utils.text_formater - friendly.event_listener.doctrine_subscriber: - class: Knp\FriendlyExtension\EventListener\DoctrineSubscriber - arguments: - - %friendly.doctrine.reset_schema% - - @friendly.context.helper.doctrine_helper - tags: - - { name: event_dispatcher.subscriber } + friendly.utils.object_reflector: + class: Knp\FriendlyExtension\Utils\ObjectReflector + + friendly.utils.text_formater: + class: Knp\FriendlyExtension\Utils\TextFormater diff --git a/src/Knp/FriendlyExtension/services/faker.yml b/src/Knp/FriendlyExtension/services/faker.yml index 593bce8c..73025647 100755 --- a/src/Knp/FriendlyExtension/services/faker.yml +++ b/src/Knp/FriendlyExtension/services/faker.yml @@ -1,5 +1,4 @@ services: - friendly.faker.factory: class: Faker\Factory @@ -44,3 +43,4 @@ services: - @friendly.faker.generator tags: - { name: friendly.faker.provider } + diff --git a/src/Knp/FriendlyExtension/services/guesser.yml b/src/Knp/FriendlyExtension/services/guesser.yml index cea122c2..375fe14e 100755 --- a/src/Knp/FriendlyExtension/services/guesser.yml +++ b/src/Knp/FriendlyExtension/services/guesser.yml @@ -1,22 +1,11 @@ services: - - friendly.type.guesser_registry: - class: Knp\FriendlyExtension\Type\GuesserRegistry - friendly.type.guesser.array_guesser: class: Knp\FriendlyExtension\Type\Guesser\ArrayGuesser arguments: - @friendly.type.guesser_registry - @friendly.utils.text_formater tags: - - { name: friendly.type.guesser } - - friendly.type.guesser.collection_guesser: - class: Knp\FriendlyExtension\Type\Guesser\CollectionGuesser - arguments: - - @friendly.type.guesser.array_guesser - tags: - - { name: friendly.type.guesser } + - { name: friendly.type.guesser, priority: 100 } friendly.type.guesser.bigint_guesser: class: Knp\FriendlyExtension\Type\Guesser\BigintGuesser @@ -30,6 +19,13 @@ services: tags: - { name: friendly.type.guesser } + friendly.type.guesser.collection_guesser: + class: Knp\FriendlyExtension\Type\Guesser\CollectionGuesser + arguments: + - @friendly.type.guesser.array_guesser + tags: + - { name: friendly.type.guesser, priority: 100 } + friendly.type.guesser.datetime_guesser: class: Knp\FriendlyExtension\Type\Guesser\DatetimeGuesser tags: @@ -63,3 +59,7 @@ services: class: Knp\FriendlyExtension\Type\Guesser\StringGuesser tags: - { name: friendly.type.guesser } + + friendly.type.guesser_registry: + class: Knp\FriendlyExtension\Type\GuesserRegistry + diff --git a/src/Knp/FriendlyExtension/services/symfony.yml b/src/Knp/FriendlyExtension/services/symfony.yml index 6536c654..818d9599 100755 --- a/src/Knp/FriendlyExtension/services/symfony.yml +++ b/src/Knp/FriendlyExtension/services/symfony.yml @@ -1,11 +1,11 @@ services: + doctrine.orm.entity_manager: + synthetic: true + tags: + - { name: friendly.symfony.service, class: Doctrine\ORM\EntityManager } doctrine: synthetic: true tags: - { name: friendly.symfony.service, class: Doctrine\ORM\Registry } - doctrine.orm.entity_manager: - synthetic: true - tags: - - { name: friendly.symfony.service, class: Doctrine\ORM\EntityManager } From b6ffa4a1c9c49d1139902ac7762737d82ba17bb7 Mon Sep 17 00:00:00 2001 From: Pierre PLAZANET Date: Fri, 29 Aug 2014 17:44:17 +0200 Subject: [PATCH 10/33] Introduce command context --- behat.yml.dist | 9 +- composer.json | 25 ++- .../FriendlyExtension/Command/Application.php | 52 +++++ .../Command/CommandLoader.php | 47 +++++ .../Command/CommandTester.php | 12 ++ .../Context/CommandContext.php | 192 ++++++++++++++++++ .../Context/Helper/AsserterHelper.php | 10 + .../Context/Helper/CommandHelper.php | 64 ++++++ .../Compiler/KernelRegistrationPass.php | 3 + .../Compiler/SymfonyServicePass.php | 4 +- .../FriendlyExtension/services/context.yml | 8 + src/Knp/FriendlyExtension/services/core.yml | 2 + .../FriendlyExtension/services/symfony.yml | 2 +- 13 files changed, 410 insertions(+), 20 deletions(-) create mode 100644 src/Knp/FriendlyExtension/Command/Application.php create mode 100644 src/Knp/FriendlyExtension/Command/CommandLoader.php create mode 100644 src/Knp/FriendlyExtension/Command/CommandTester.php create mode 100644 src/Knp/FriendlyExtension/Context/CommandContext.php create mode 100644 src/Knp/FriendlyExtension/Context/Helper/CommandHelper.php diff --git a/behat.yml.dist b/behat.yml.dist index 49708adc..57a61836 100755 --- a/behat.yml.dist +++ b/behat.yml.dist @@ -4,11 +4,6 @@ default: suites: default: path: %paths.base%/features - contexts: - - Knp\FriendlyContexts\Context\MinkContext - - Knp\FriendlyContexts\Context\TableContext - - Knp\FriendlyContexts\Context\EntityContext - - Knp\FriendlyContexts\Context\AliceContext - - Knp\FriendlyContexts\Context\PageContext + contexts: ~ extensions: - Knp\FriendlyContexts\Extension: ~ + Knp\FriendlyExtension: ~ diff --git a/composer.json b/composer.json index 755ef56e..c944332d 100755 --- a/composer.json +++ b/composer.json @@ -6,19 +6,22 @@ "Knp\\FriendlyExtension": "src/" } }, - "require": { - "behat/behat": "~3.0", - "symfony/property-access": "~2.0", - "doctrine/inflector": "~1.0", - "doctrine/data-fixtures": "~1.0", - "behat/mink-extension": "~2.0", - "fzaninotto/faker": "~1.0", - "nelmio/alice": "~1.0", - "guzzle/guzzle": "~3.7" + "require": { + "behat/behat": "~3.0", + "behat/mink-extension": "~2@dev", + "doctrine/common": "~2.0", + "doctrine/data-fixtures": "~1.0", + "doctrine/orm": "~2.0", + "doctrine/inflector": "~1.0", + "fzaninotto/faker": "~1.0", + "guzzle/guzzle": "~3.7", + "nelmio/alice": "~1.0", + "symfony/property-access": "~2.0", + "symfony/http-kernel": "~2.0", + "symfony/framework-bundle": "~2.0" }, "require-dev": { - "phpspec/phpspec": "~2.0.0", - "doctrine/orm": "dev-master" + "phpspec/phpspec": "~2.0.0" }, "license": "MIT", "authors": [ diff --git a/src/Knp/FriendlyExtension/Command/Application.php b/src/Knp/FriendlyExtension/Command/Application.php new file mode 100644 index 00000000..6be18987 --- /dev/null +++ b/src/Knp/FriendlyExtension/Command/Application.php @@ -0,0 +1,52 @@ +kernel = $kernel; + $this->loadedCommands = []; + + parent::__construct($this->kernel); + } + + public function getKernel() + { + return $this->kernel; + } + + public function add(Command $command, $name = null) + { + $this->loadedCommands[$name ?: $command->getName()] = $command; + $command->setApplication($this); + } + + public function getCommands() + { + return $this->loadedCommands; + } + + public function hasCommand($name) + { + return array_key_exists($name, $this->loadedCommands); + } + + public function getCommand($name) + { + return $this->loadedCommands[$name]; + } + + public function find($name) + { + return $this->getCommand($name); + } +} diff --git a/src/Knp/FriendlyExtension/Command/CommandLoader.php b/src/Knp/FriendlyExtension/Command/CommandLoader.php new file mode 100644 index 00000000..ff232053 --- /dev/null +++ b/src/Knp/FriendlyExtension/Command/CommandLoader.php @@ -0,0 +1,47 @@ +defaultRegistered) { + return; + } + + $this->defaultRegistered = true; + + foreach ($this->defaultCommands as $name => $command) { + $application->add($command, $name); + } + } + + public function registerCommandsFromKernel(Application $application, KernelInterface $kernel) + { + $this->registerDefaultCommands($application); + + foreach ($kernel->getBundles() as $bundle) { + $this->registerCommandsFromBundle($application, $bundle); + } + } + + public function registerCommandsFromBundle(Application $application, BundleInterface $bundle) + { + $this->registerDefaultCommands($application); + $bundle->registerCommands($application); + } + + public function addDefaultCommand($name, Command $command) + { + $this->defaultCommands[$name] = $command; + } +} diff --git a/src/Knp/FriendlyExtension/Command/CommandTester.php b/src/Knp/FriendlyExtension/Command/CommandTester.php new file mode 100644 index 00000000..bc840630 --- /dev/null +++ b/src/Knp/FriendlyExtension/Command/CommandTester.php @@ -0,0 +1,12 @@ +command = null; + $this->input = []; + } + + /** + * @Given I prepare a :name command + */ + public function buildCommand($name) + { + $this->clear(); + $this->command = $this->get('command')->buildCommand($this->getApplication(), $name); + } + + /** + * @Given show available commands + */ + public function showCommands() + { + foreach ($this->get('command')->getCommands($this->getApplication()) as $name => $command) + { + echo "$name\n"; + } + } + + /** + * @Given I add the argument :name with value ":value" + */ + public function addArgument($name, $value = null) + { + $this->isCommandBuilding(); + + $this->input[$name] = $value; + } + + /** + * @Given I add the option ":name" + * @Given I add the option ":name" with value ":value" + */ + public function addOption($name, $value = null) + { + $this->isCommandBuilding(); + + $name = $this->cleanOption($name); + $this->input[sprintf('--%s', $name)] = $value; + } + + /** + * @Given I add the short option ":name" + * @Given I add the short option ":name" with value ":value" + */ + public function addShortOption($name, $value = null) + { + $this->isCommandBuilding(); + + $name = $this->cleanOption($name); + $this->input[sprintf('-%s', $name)] = $value; + } + + /** + * @Given I add the following command parameters: + */ + public function andTheFollowing(TableNode $arguments) + { + $arguments = $arguments->getRowsHash(); + + $this->input = array_merge($this->input, $arguments); + } + + /** + * @When I run the command + */ + public function runCommand() + { + $this->isCommandBuilding(); + + $this->command->execute($this->input); + } + + /** + * @Then show command result + */ + public function showResult() + { + $this->isCommandBuilding(); + + echo $this->command->getDisplay(); + } + + /** + * @Then the command result should contains :string + */ + public function resultContainsString($string) + { + $expected = $string; + $real = explode("\n", $this->command->getDisplay()); + + $this + ->get('asserter') + ->assertArrayContains($expected, $real) + ; + } + + /** + * @Then the command result should contains: + */ + public function resultContainsStrings(PyStringNode $strings) + { + $expected = $strings->getStrings(); + $real = explode("\n", $this->command->getDisplay()); + + $this + ->get('asserter') + ->assertArrayContains($expected, $real) + ; + } + + /** + * @Then the command should be a success + */ + public function isSuccess() + { + $this->testResult(0); + } + + + /** + * @Then the command should be in error + */ + public function isError() + { + $this->testResult(1); + } + + /** + * @Then the command result should be :code + */ + public function testResult($code) + { + $this->isCommandBuilding(); + + $this + ->get('asserter') + ->assertEquals((int)$code, $this->command->getStatusCode()) + ; + } + + private function isCommandBuilding() + { + $this + ->get('asserter') + ->assertNotNull($this->command, 'No command in building') + ; + } + + private function getApplication() + { + return $this->application = $this->application + ?: $this->get('command')->getApplication() + ; + } + + private function cleanOption($name) + { + $matches = []; + + if (preg_match('/(--|-)(?P.*)/', $name, $matches)) { + + return $matches['name']; + } + + return $name; + } +} diff --git a/src/Knp/FriendlyExtension/Context/Helper/AsserterHelper.php b/src/Knp/FriendlyExtension/Context/Helper/AsserterHelper.php index d0d05535..b9ef68d7 100755 --- a/src/Knp/FriendlyExtension/Context/Helper/AsserterHelper.php +++ b/src/Knp/FriendlyExtension/Context/Helper/AsserterHelper.php @@ -63,6 +63,16 @@ public function assertArrayContains(array $expected, array $real, $message = nul } } + public function assertTrue($real, $message = "Failing to assert true.") + { + return $this->assertEquals(true, $real, $message); + } + + public function assertFalse($real, $message = "Failing to assert false.") + { + return $this->assertEquals(false, $real, $message); + } + public function assertEquals($expected, $real, $message = "Failing to assert equals.") { return $this->assert($expected === $real, $message); diff --git a/src/Knp/FriendlyExtension/Context/Helper/CommandHelper.php b/src/Knp/FriendlyExtension/Context/Helper/CommandHelper.php new file mode 100644 index 00000000..f6b7ae57 --- /dev/null +++ b/src/Knp/FriendlyExtension/Context/Helper/CommandHelper.php @@ -0,0 +1,64 @@ +loader = $loader; + $this->kernel = $kernel; + } + + public function getApplication() + { + $application = new Application($this->kernel); + + $this->loader->registerCommandsFromKernel($application, $this->kernel); + + return $application; + } + + public function getCommands(Application $application) + { + $commands = $application->getCommands(); + ksort($commands); + + return $commands; + } + + public function buildCommand(Application $application, $name) + { + $this + ->get('asserter') + ->assertTrue( + $application->hasCommand($name), + sprintf( + 'No command named "%s" found. "%s" available.', + $name, + implode('", "', array_keys($this->getCommands($application))) + ) + ) + ; + + return new CommandTester($application->getCommand($name)); + } + + public function clear() + { + } + + public function getName() + { + return 'command'; + } +} diff --git a/src/Knp/FriendlyExtension/DependencyInjection/Compiler/KernelRegistrationPass.php b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/KernelRegistrationPass.php index 84b53f87..f66d4c47 100755 --- a/src/Knp/FriendlyExtension/DependencyInjection/Compiler/KernelRegistrationPass.php +++ b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/KernelRegistrationPass.php @@ -5,6 +5,7 @@ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\HttpKernel\Kernel; class KernelRegistrationPass implements CompilerPassInterface { @@ -22,6 +23,8 @@ public function process(ContainerBuilder $container) ->addArgument($container->getParameter('friendly.symfony_kernel.debug')) ; $container->setDefinition('friendly.symfony.kernel', $definition); + } else { + $container->set('friendly.symfony.kernel', new Kernel('', false)); } } diff --git a/src/Knp/FriendlyExtension/DependencyInjection/Compiler/SymfonyServicePass.php b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/SymfonyServicePass.php index 4e226aa3..1490ee8a 100644 --- a/src/Knp/FriendlyExtension/DependencyInjection/Compiler/SymfonyServicePass.php +++ b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/SymfonyServicePass.php @@ -4,6 +4,7 @@ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; +use \ReflectionClass; class SymfonyServicePass implements CompilerPassInterface { @@ -12,8 +13,9 @@ public function process(ContainerBuilder $container) $services = $container->findTaggedServiceIds('friendly.symfony.service'); foreach ($services as $id => $options) { + $options = current($options); if (null === $kernel = $this->getKernel($container)) { - $container->set($id, (new ReflectionClass($options['class']))->createInstanceWithoutConstructor()); + $container->set($id, (new ReflectionClass($options['class']))->newInstanceWithoutConstructor()); } else { $kernel->boot(); $container->set($id, $kernel->getContainer()->get($id)); diff --git a/src/Knp/FriendlyExtension/services/context.yml b/src/Knp/FriendlyExtension/services/context.yml index 28792440..e96b6acb 100644 --- a/src/Knp/FriendlyExtension/services/context.yml +++ b/src/Knp/FriendlyExtension/services/context.yml @@ -6,6 +6,14 @@ services: tags: - { name: friendly.context.helper } + friendly.context.helper.command_helper: + class: Knp\FriendlyExtension\Context\Helper\CommandHelper + arguments: + - @friendly.command.command_loader + - @friendly.symfony.kernel + tags: + - { name: friendly.context.helper } + friendly.context.helper.doctrine_helper: class: Knp\FriendlyExtension\Context\Helper\DoctrineHelper arguments: diff --git a/src/Knp/FriendlyExtension/services/core.yml b/src/Knp/FriendlyExtension/services/core.yml index 995c65cc..2b0ca2ad 100755 --- a/src/Knp/FriendlyExtension/services/core.yml +++ b/src/Knp/FriendlyExtension/services/core.yml @@ -34,3 +34,5 @@ services: friendly.utils.text_formater: class: Knp\FriendlyExtension\Utils\TextFormater + friendly.command.command_loader: + class: Knp\FriendlyExtension\Command\CommandLoader diff --git a/src/Knp/FriendlyExtension/services/symfony.yml b/src/Knp/FriendlyExtension/services/symfony.yml index 818d9599..459f6680 100755 --- a/src/Knp/FriendlyExtension/services/symfony.yml +++ b/src/Knp/FriendlyExtension/services/symfony.yml @@ -7,5 +7,5 @@ services: doctrine: synthetic: true tags: - - { name: friendly.symfony.service, class: Doctrine\ORM\Registry } + - { name: friendly.symfony.service, class: Doctrine\Common\Persistence\AbstractManagerRegistry } From aeacc7a334125dba81fb61e55f07a78bee92967a Mon Sep 17 00:00:00 2001 From: Pierre PLAZANET Date: Mon, 13 Oct 2014 23:15:39 +0200 Subject: [PATCH 11/33] Improve stability --- src/Knp/FriendlyExtension.php | 4 +- .../Context/Helper/AsserterHelper.php | 4 +- .../Compiler/KernelRegistrationPass.php | 2 +- .../RemoveUnavailableServicesPass.php | 66 +++++++++++++++++++ .../Compiler/SymfonyServicePass.php | 2 +- .../FriendlyExtension/services/context.yml | 3 + src/Knp/FriendlyExtension/services/core.yml | 3 + .../FriendlyExtension/services/symfony.yml | 2 + 8 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 src/Knp/FriendlyExtension/DependencyInjection/Compiler/RemoveUnavailableServicesPass.php diff --git a/src/Knp/FriendlyExtension.php b/src/Knp/FriendlyExtension.php index 66e54ced..45bdefc4 100755 --- a/src/Knp/FriendlyExtension.php +++ b/src/Knp/FriendlyExtension.php @@ -11,6 +11,7 @@ use Knp\FriendlyExtension\DependencyInjection\Compiler\FakerProviderRegistrationPass; use Knp\FriendlyExtension\DependencyInjection\Compiler\KernelRegistrationPass; use Knp\FriendlyExtension\DependencyInjection\Compiler\ParameterBuildingPass; +use Knp\FriendlyExtension\DependencyInjection\Compiler\RemoveUnavailableServicesPass; use Knp\FriendlyExtension\DependencyInjection\Compiler\SymfonyServicePass; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; use Symfony\Component\Config\FileLocator; @@ -122,8 +123,9 @@ public function load(ContainerBuilder $container, array $config) $container->addCompilerPass(new FakerProviderRegistrationPass); $container->addCompilerPass(new FakerGuesserRegistrationPass); $container->addCompilerPass(new ApiUrlTransitionPass); - $container->addCompilerPass(new ContextHelperRegistrationPass); $container->addCompilerPass(new SymfonyServicePass); + $container->addCompilerPass(new RemoveUnavailableServicesPass); + $container->addCompilerPass(new ContextHelperRegistrationPass); } public function process(ContainerBuilder $container) diff --git a/src/Knp/FriendlyExtension/Context/Helper/AsserterHelper.php b/src/Knp/FriendlyExtension/Context/Helper/AsserterHelper.php index b9ef68d7..34c39550 100755 --- a/src/Knp/FriendlyExtension/Context/Helper/AsserterHelper.php +++ b/src/Knp/FriendlyExtension/Context/Helper/AsserterHelper.php @@ -42,8 +42,10 @@ public function assertArrayEquals(array $expected, array $real, $fullText = fals } } - public function assertArrayContains(array $expected, array $real, $message = null) + public function assertArrayContains($expected, array $real, $message = null) { + $expected = is_array($expected) ? $expected : [$expected]; + $message = $message ?: sprintf("The given array\r\n\r\n%s\r\ndoes not contains the following rows\r\n\r\n%s", $this->explode($real), $this->explode($expected)); foreach ($expected as $key => $value) { diff --git a/src/Knp/FriendlyExtension/DependencyInjection/Compiler/KernelRegistrationPass.php b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/KernelRegistrationPass.php index f66d4c47..c8924d35 100755 --- a/src/Knp/FriendlyExtension/DependencyInjection/Compiler/KernelRegistrationPass.php +++ b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/KernelRegistrationPass.php @@ -24,7 +24,7 @@ public function process(ContainerBuilder $container) ; $container->setDefinition('friendly.symfony.kernel', $definition); } else { - $container->set('friendly.symfony.kernel', new Kernel('', false)); + $container->removeDefinition('friendly.symfony.kernel'); } } diff --git a/src/Knp/FriendlyExtension/DependencyInjection/Compiler/RemoveUnavailableServicesPass.php b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/RemoveUnavailableServicesPass.php new file mode 100644 index 00000000..3c4b2d50 --- /dev/null +++ b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/RemoveUnavailableServicesPass.php @@ -0,0 +1,66 @@ +removeDependendiesFromContainer($container); + } + + private function removeDependendiesFromContainer(ContainerBuilder $container, $id = null) + { + foreach ($container->findTaggedServiceIds('remove-when-missing') as $id => $tags) { + foreach ($tags as $tag) { + if (!isset($tag['service'])) { + continue; + } + + if (null !== $id && $id === $tag['service']) { + continue; + } + + if ($container->hasDefinition($tag['service'])) { + continue; + } + + if ($container->hasAlias($tag['service'])) { + continue; + } + + $container->removeDefinition($id); + + $this->removeDependendiesFromContainer($container, $id); + $this->removeFromEventDispatcher($container, $id); + } + } + } + + private function removeFromEventDispatcher(ContainerBuilder $container, $id) + { + $dispatcher = $container->getDefinition('event_dispatcher'); + $calls = $dispatcher->getMethodCalls(); + + foreach ($calls as $index => $call) { + list($method, $arguments) = $call; + + if (false === in_array($method, [ 'addSubscriber', 'addListener' ])) { + + continue; + } + + if ($id !== (string)current($arguments)) { + + continue; + } + + unset($calls[$index]); + } + + $dispatcher->setMethodCalls($calls); + } +} diff --git a/src/Knp/FriendlyExtension/DependencyInjection/Compiler/SymfonyServicePass.php b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/SymfonyServicePass.php index 1490ee8a..bf6db737 100644 --- a/src/Knp/FriendlyExtension/DependencyInjection/Compiler/SymfonyServicePass.php +++ b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/SymfonyServicePass.php @@ -15,7 +15,7 @@ public function process(ContainerBuilder $container) foreach ($services as $id => $options) { $options = current($options); if (null === $kernel = $this->getKernel($container)) { - $container->set($id, (new ReflectionClass($options['class']))->newInstanceWithoutConstructor()); + $container->removeDefinition($id); } else { $kernel->boot(); $container->set($id, $kernel->getContainer()->get($id)); diff --git a/src/Knp/FriendlyExtension/services/context.yml b/src/Knp/FriendlyExtension/services/context.yml index e96b6acb..614f3527 100644 --- a/src/Knp/FriendlyExtension/services/context.yml +++ b/src/Knp/FriendlyExtension/services/context.yml @@ -13,6 +13,7 @@ services: - @friendly.symfony.kernel tags: - { name: friendly.context.helper } + - { name: remove-when-missing, service: friendly.symfony.kernel } friendly.context.helper.doctrine_helper: class: Knp\FriendlyExtension\Context\Helper\DoctrineHelper @@ -21,6 +22,7 @@ services: - @friendly.doctrine.resolver tags: - { name: friendly.context.helper } + - { name: remove-when-missing, service: doctrine.orm.entity_manager } friendly.context.helper.entity_helper: class: Knp\FriendlyExtension\Context\Helper\EntityHelper @@ -30,6 +32,7 @@ services: - @friendly.type.guesser_registry tags: - { name: friendly.context.helper } + - { name: remove-when-missing, service: friendly.doctrine.resolver } friendly.context.helper.record_helper: class: Knp\FriendlyExtension\Context\Helper\RecordHelper diff --git a/src/Knp/FriendlyExtension/services/core.yml b/src/Knp/FriendlyExtension/services/core.yml index 2b0ca2ad..e4de6f41 100755 --- a/src/Knp/FriendlyExtension/services/core.yml +++ b/src/Knp/FriendlyExtension/services/core.yml @@ -6,6 +6,8 @@ services: - @friendly.utils.object_reflector - @friendly.utils.text_formater - @friendly.utils.name_proposer + tags: + - { name: remove-when-missing, service: doctrine.orm.entity_manager } friendly.event_listener.doctrine_subscriber: class: Knp\FriendlyExtension\EventListener\DoctrineSubscriber @@ -14,6 +16,7 @@ services: - @friendly.context.helper.doctrine_helper tags: - { name: event_dispatcher.subscriber } + - { name: remove-when-missing, service: friendly.context.helper.doctrine_helper } friendly.faker.unique_cache: class: Knp\FriendlyExtension\Faker\UniqueCache diff --git a/src/Knp/FriendlyExtension/services/symfony.yml b/src/Knp/FriendlyExtension/services/symfony.yml index 459f6680..7caefb72 100755 --- a/src/Knp/FriendlyExtension/services/symfony.yml +++ b/src/Knp/FriendlyExtension/services/symfony.yml @@ -3,9 +3,11 @@ services: synthetic: true tags: - { name: friendly.symfony.service, class: Doctrine\ORM\EntityManager } + - { name: remove-when-missing, service: friendly.symfony.kernel } doctrine: synthetic: true tags: - { name: friendly.symfony.service, class: Doctrine\Common\Persistence\AbstractManagerRegistry } + - { name: remove-when-missing, service: friendly.symfony.kernel } From 58a6b4a248b179fa62cf3bbe0058068deac091dc Mon Sep 17 00:00:00 2001 From: Pierre PLAZANET Date: Mon, 13 Oct 2014 23:47:55 +0200 Subject: [PATCH 12/33] Patch CS --- src/Knp/FriendlyExtension/Context/CommandContext.php | 3 +-- src/Knp/FriendlyExtension/Gherkin/Node/Explorer.php | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Knp/FriendlyExtension/Context/CommandContext.php b/src/Knp/FriendlyExtension/Context/CommandContext.php index 45a8753a..ec69977f 100644 --- a/src/Knp/FriendlyExtension/Context/CommandContext.php +++ b/src/Knp/FriendlyExtension/Context/CommandContext.php @@ -35,8 +35,7 @@ public function buildCommand($name) */ public function showCommands() { - foreach ($this->get('command')->getCommands($this->getApplication()) as $name => $command) - { + foreach ($this->get('command')->getCommands($this->getApplication()) as $name => $command) { echo "$name\n"; } } diff --git a/src/Knp/FriendlyExtension/Gherkin/Node/Explorer.php b/src/Knp/FriendlyExtension/Gherkin/Node/Explorer.php index 832c6fde..eade3a95 100644 --- a/src/Knp/FriendlyExtension/Gherkin/Node/Explorer.php +++ b/src/Knp/FriendlyExtension/Gherkin/Node/Explorer.php @@ -47,8 +47,7 @@ public function getArguments($tag) private function extract(TaggedNodeInterface $element, array &$results) { - foreach ($element->getTags() as $tag) - { + foreach ($element->getTags() as $tag) { $negative = (0 === strpos($tag, '~')); $tag = $negative ? substr($tag, 1) : $tag; $matches = []; From ecd9db2e4df537ed3ac6a5427ec4a81bab343361 Mon Sep 17 00:00:00 2001 From: Pierre PLAZANET Date: Tue, 14 Oct 2014 16:23:47 +0100 Subject: [PATCH 13/33] Add tag API --- .../Gherkin/TagFactorySpec.php | 14 ++++ .../Gherkin/TagLoaderSpec.php | 71 ++++++++++++++++++ .../Knp/FriendlyExtension/Gherkin/TagSpec.php | 45 +++++++++++ src/Knp/FriendlyExtension/Gherkin/Tag.php | 67 +++++++++++++++++ .../FriendlyExtension/Gherkin/TagFactory.php | 13 ++++ .../FriendlyExtension/Gherkin/TagLoader.php | 75 +++++++++++++++++++ 6 files changed, 285 insertions(+) create mode 100644 spec/Knp/FriendlyExtension/Gherkin/TagFactorySpec.php create mode 100644 spec/Knp/FriendlyExtension/Gherkin/TagLoaderSpec.php create mode 100644 spec/Knp/FriendlyExtension/Gherkin/TagSpec.php create mode 100644 src/Knp/FriendlyExtension/Gherkin/Tag.php create mode 100644 src/Knp/FriendlyExtension/Gherkin/TagFactory.php create mode 100644 src/Knp/FriendlyExtension/Gherkin/TagLoader.php diff --git a/spec/Knp/FriendlyExtension/Gherkin/TagFactorySpec.php b/spec/Knp/FriendlyExtension/Gherkin/TagFactorySpec.php new file mode 100644 index 00000000..dc8902b3 --- /dev/null +++ b/spec/Knp/FriendlyExtension/Gherkin/TagFactorySpec.php @@ -0,0 +1,14 @@ +shouldHaveType('Knp\FriendlyExtension\Gherkin\TagFactory'); + } +} diff --git a/spec/Knp/FriendlyExtension/Gherkin/TagLoaderSpec.php b/spec/Knp/FriendlyExtension/Gherkin/TagLoaderSpec.php new file mode 100644 index 00000000..115ee37a --- /dev/null +++ b/spec/Knp/FriendlyExtension/Gherkin/TagLoaderSpec.php @@ -0,0 +1,71 @@ +beConstructedWith($factory); + + $event->getFeature()->willReturn($feature); + $event->getScenario()->willReturn($scenario); + + $feature->getTags()->willReturn([ 'tag1', 'tag2', 'tag3(Foo)', 'tag3(Bar)' ]); + $scenario->getTags()->willReturn([ '~tag2', 'tag3(~Foo)', 'tag3(Baz)' ]); + + $factory->create('tag1')->willReturn($tag1)->shouldBeCalledTimes(1); + $factory->create('tag2')->willReturn($tag2)->shouldBeCalledTimes(1); + $factory->create('tag3')->willReturn($tag3)->shouldBeCalledTimes(1); + } + + function it_is_initializable(TagFactory $factory) + { + $factory->create('tag1')->shouldNotBeCalled(); + $factory->create('tag2')->shouldNotBeCalled(); + $factory->create('tag3')->shouldNotBeCalled(); + $this->shouldHaveType('Knp\FriendlyExtension\Gherkin\TagLoader'); + } + + function it_load_tags(ScenarioLikeTested $event, Tag $tag1, Tag $tag2, Tag $tag3) + { + $tag1->addArgument(Argument::cetera())->shouldNotBeCalled(); + $tag1->enable()->shouldBeCalled(); + $tag1->disable()->shouldNotBeCalled(); + + $tag2->addArgument(Argument::cetera())->shouldNotBeCalled(); + $tag2->enable()->shouldBeCalled(); + $tag2->disable()->shouldBeCalled(); + + $tag3->addArgument('Foo', true)->shouldBeCalled(); + $tag3->addArgument('Foo', false)->shouldBeCalled(); + $tag3->addArgument('Bar', true)->shouldBeCalled(); + $tag3->addArgument('Baz', true)->shouldBeCalled(); + $tag3->enable()->shouldBeCalled(); + $tag3->disable()->shouldNotBeCalled(); + + $this->beforeScenario($event); + } + + function it_return_a_tag_by_name(ScenarioLikeTested $event, Tag $tag1) + { + $this->beforeScenario($event); + + $this->getTag('tag1')->shouldReturn($tag1); + } + + function it_return_null_if_tag_doesnt_exists(ScenarioLikeTested $event) + { + $this->beforeScenario($event); + + $this->getTag('tag9')->shouldBeNull(); + } +} diff --git a/spec/Knp/FriendlyExtension/Gherkin/TagSpec.php b/spec/Knp/FriendlyExtension/Gherkin/TagSpec.php new file mode 100644 index 00000000..7de0364d --- /dev/null +++ b/spec/Knp/FriendlyExtension/Gherkin/TagSpec.php @@ -0,0 +1,45 @@ +beConstructedWith('tag1'); + + $this->addArgument('Arg1', true); + $this->addArgument('Arg2', true); + $this->addArgument('Arg3', false); + $this->addArgument('Arg4', true); + } + + function it_is_initializable() + { + $this->shouldHaveType('Knp\FriendlyExtension\Gherkin\Tag'); + } + + function it_return_active_arguments() + { + $this->getArguments()->shouldReturn([ 'Arg1', 'Arg2', 'Arg4' ]); + } + + function it_revoke_unactive_argument() + { + $this->revokeArgument('Arg3')->shouldReturn(true); + } + + function it_doesnt_revoke_active_argument() + { + $this->revokeArgument('Arg2')->shouldReturn(false); + } + + function it_doesnt_revoke_newly_unactive_argument() + { + $this->addArgument('Arg2', false); + $this->revokeArgument('Arg2')->shouldReturn(true); + } +} diff --git a/src/Knp/FriendlyExtension/Gherkin/Tag.php b/src/Knp/FriendlyExtension/Gherkin/Tag.php new file mode 100644 index 00000000..2bdf3109 --- /dev/null +++ b/src/Knp/FriendlyExtension/Gherkin/Tag.php @@ -0,0 +1,67 @@ +name = $name; + } + + public function addArgument($argument, $enabled) + { + $this->arguments[$argument] = $enabled; + } + + public function getArguments() + { + $arguments = []; + + foreach ($this->arguments as $name => $enabled) { + if ($enabled) { + $arguments[] = $name; + } + } + + return $arguments; + } + + public function hasArgument($argument) + { + if (false === isset($this->arguments[$argument])) { + + return false; + } + + return $this->arguments[$argument]; + } + + public function revokeArgument($argument) + { + if (false === isset($this->arguments[$argument])) { + + return false; + } + + return false === $this->arguments[$argument]; + } + + public function enable() + { + $this->enable = true; + + return $this; + } + + public function disable() + { + $this->enable = false; + + return $this; + } +} diff --git a/src/Knp/FriendlyExtension/Gherkin/TagFactory.php b/src/Knp/FriendlyExtension/Gherkin/TagFactory.php new file mode 100644 index 00000000..41654d0b --- /dev/null +++ b/src/Knp/FriendlyExtension/Gherkin/TagFactory.php @@ -0,0 +1,13 @@ +factory = $factory; + } + + public function beforeScenario(ScenarioLikeTested $event) + { + $this->feature = $event->getFeature(); + $this->scenario = $event->getScenario(); + + foreach ($this->extractTags() as $tag) { + $tagActive = '~' !== substr($tag, 0, 1); + $tag = $tagActive ? $tag : substr($tag, 1); + $arguments = []; + if (0 !== preg_match('/^(.+)\((.*)\)$/', $tag, $matches)) { + list($str, $tag, $arguments) = $matches; + $arguments = explode(',', $arguments); + $arguments = array_map('trim', $arguments); + $arguments = array_filter($arguments, function ($e) { return !empty($e); }); + } + + $object = $this->getTag($tag) ?: $this->factory->create($tag); + if ($tagActive) { + $object->enable(); + } else { + $object->disable(); + } + + foreach ($arguments as $argument) { + $argumentActive = '~' !== substr($argument, 0, 1); + $argument = $argumentActive ? $argument : substr($argument, 1); + $object->addArgument($argument, $argumentActive); + } + + $this->tags[$tag] = $object; + } + } + + public function getTag($name) + { + if (false === array_key_exists($name, $this->tags)) { + + return; + } + + return $this->tags[$name]; + } + + private function extractTags() + { + if (null === $this->feature || null === $this->scenario) { + + return []; + } + + return array_merge( + $this->feature->getTags(), + $this->scenario->getTags() + ); + } +} From 8a78a216ff0e6b2b2d9ac22264148b48cc70a26f Mon Sep 17 00:00:00 2001 From: Pierre PLAZANET Date: Tue, 14 Oct 2014 16:37:47 +0100 Subject: [PATCH 14/33] Register TagLoaderHasService --- src/Knp/FriendlyExtension/Gherkin/TagLoader.php | 4 ++-- src/Knp/FriendlyExtension/services/core.yml | 10 ++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Knp/FriendlyExtension/Gherkin/TagLoader.php b/src/Knp/FriendlyExtension/Gherkin/TagLoader.php index 340c93ed..84b78171 100644 --- a/src/Knp/FriendlyExtension/Gherkin/TagLoader.php +++ b/src/Knp/FriendlyExtension/Gherkin/TagLoader.php @@ -12,9 +12,9 @@ class TagLoader private $scenario; private $tags = []; - public function __construct(TagFactory $factory) + public function __construct(TagFactory $factory = null) { - $this->factory = $factory; + $this->factory = $factory ?: new TagFactory; } public function beforeScenario(ScenarioLikeTested $event) diff --git a/src/Knp/FriendlyExtension/services/core.yml b/src/Knp/FriendlyExtension/services/core.yml index e4de6f41..02021de2 100755 --- a/src/Knp/FriendlyExtension/services/core.yml +++ b/src/Knp/FriendlyExtension/services/core.yml @@ -1,4 +1,7 @@ services: + friendly.command.command_loader: + class: Knp\FriendlyExtension\Command\CommandLoader + friendly.doctrine.resolver: class: Knp\FriendlyExtension\Doctrine\Resolver arguments: @@ -21,6 +24,11 @@ services: friendly.faker.unique_cache: class: Knp\FriendlyExtension\Faker\UniqueCache + friendly.gherkin.tag_loader: + class: Knp\FriendlyExtension\Gherkin\TagLoader + tags: + - { name: event_dispatcher.listener, event: tester.scenario_tested.before, method: beforeScenario } + friendly.record.collection.bag: class: Knp\FriendlyExtension\Record\Collection\Bag arguments: @@ -37,5 +45,3 @@ services: friendly.utils.text_formater: class: Knp\FriendlyExtension\Utils\TextFormater - friendly.command.command_loader: - class: Knp\FriendlyExtension\Command\CommandLoader From 213a6846e3118aab949c3167fed1e622cf104c6d Mon Sep 17 00:00:00 2001 From: Pierre PLAZANET Date: Tue, 14 Oct 2014 17:44:38 +0100 Subject: [PATCH 15/33] Add alice class loader Add alice class loader Add alice class loader --- .../Alice/ClassLoaderSpec.php | 60 ++++++++++++++ src/Knp/FriendlyExtension.php | 3 + .../FriendlyExtension/Alice/ClassLoader.php | 79 +++++++++++++++++++ .../Compiler/SetArgumentToNullPass.php | 38 +++++++++ src/Knp/FriendlyExtension/services/alice.yml | 7 ++ 5 files changed, 187 insertions(+) create mode 100644 spec/Knp/FriendlyExtension/Alice/ClassLoaderSpec.php create mode 100644 src/Knp/FriendlyExtension/Alice/ClassLoader.php create mode 100644 src/Knp/FriendlyExtension/DependencyInjection/Compiler/SetArgumentToNullPass.php create mode 100644 src/Knp/FriendlyExtension/services/alice.yml diff --git a/spec/Knp/FriendlyExtension/Alice/ClassLoaderSpec.php b/spec/Knp/FriendlyExtension/Alice/ClassLoaderSpec.php new file mode 100644 index 00000000..ee7e9d13 --- /dev/null +++ b/spec/Knp/FriendlyExtension/Alice/ClassLoaderSpec.php @@ -0,0 +1,60 @@ +getContainer()->willReturn($container); + $container->has('other')->willReturn(false); + $container->has('service')->willReturn(true); + $container->get('service')->willReturn($service); + } + + function it_is_initializable() + { + $this->shouldHaveType('Knp\FriendlyExtension\Alice\ClassLoader'); + } + + function it_can_instanciate_a_class() + { + $this->instanciate('Knp\FriendlyExtension\Alice\ClassLoader')->shouldHaveType('Knp\FriendlyExtension\Alice\ClassLoader'); + } + + function it_cant_instanciate_onject_with_constructor() + { + $this + ->shouldThrow(new \InvalidArgumentException('Constructor of Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException isn\'t supported because it needs arguments.')) + ->duringInstanciate('Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException'); + } + + function it_can_instanciate_existing_services(KernelInterface $kernel, $service) + { + $this->beConstructedWith($kernel); + $this->instanciate('@service')->shouldReturn($service); + } + + function it_cant_instaciate_unknown_service(KernelInterface $kernel) + { + $this->beConstructedWith($kernel); + $this + ->shouldThrow(new ServiceNotFoundException('other')) + ->duringInstanciate('@other') + ; + } + + function it_cant_instantiate_service_without_kernel() + { + $this + ->shouldThrow(new \InvalidArgumentException('@service is not a valide class name')) + ->duringInstanciate('@service') + ; + } +} diff --git a/src/Knp/FriendlyExtension.php b/src/Knp/FriendlyExtension.php index 45bdefc4..78b15bbf 100755 --- a/src/Knp/FriendlyExtension.php +++ b/src/Knp/FriendlyExtension.php @@ -12,6 +12,7 @@ use Knp\FriendlyExtension\DependencyInjection\Compiler\KernelRegistrationPass; use Knp\FriendlyExtension\DependencyInjection\Compiler\ParameterBuildingPass; use Knp\FriendlyExtension\DependencyInjection\Compiler\RemoveUnavailableServicesPass; +use Knp\FriendlyExtension\DependencyInjection\Compiler\SetArgumentToNullPass; use Knp\FriendlyExtension\DependencyInjection\Compiler\SymfonyServicePass; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; use Symfony\Component\Config\FileLocator; @@ -111,6 +112,7 @@ public function load(ContainerBuilder $container, array $config) { $loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/FriendlyExtension/services')); $loader->load('context.yml'); + $loader->load('alice.yml'); $loader->load('core.yml'); $loader->load('faker.yml'); $loader->load('guesser.yml'); @@ -125,6 +127,7 @@ public function load(ContainerBuilder $container, array $config) $container->addCompilerPass(new ApiUrlTransitionPass); $container->addCompilerPass(new SymfonyServicePass); $container->addCompilerPass(new RemoveUnavailableServicesPass); + $container->addCompilerPass(new SetArgumentToNullPass); $container->addCompilerPass(new ContextHelperRegistrationPass); } diff --git a/src/Knp/FriendlyExtension/Alice/ClassLoader.php b/src/Knp/FriendlyExtension/Alice/ClassLoader.php new file mode 100644 index 00000000..e1a45937 --- /dev/null +++ b/src/Knp/FriendlyExtension/Alice/ClassLoader.php @@ -0,0 +1,79 @@ +kernel = $kernel; + } + + public function instanciate($name) + { + if (null !== $instance = $this->getFromClassname($name)) { + + return $instance; + } + + if (null !== $instance = $this->getFromKernel($name)) { + + return $instance; + } + + $message = sprintf('%s is not a valide class name', $name); + + if (null !== $this->kernel) { + $message .= ' or a valide service name'; + } + + throw new \InvalidArgumentException($message); + } + + private function getFromClassname($class) + { + if ("@" === substr($class, 0, 1)) { + + return; + } + + if (!class_exists($class)) { + + throw new \InvalidArgumentException(sprintf('Can\'t find class "%s"'), $class); + } + + $rfl = new \ReflectionClass($class); + $constructor = $rfl->getConstructor(); + + if (null !== $constructor && 0 !== $constructor->getNumberOfRequiredParameters()) { + throw new \InvalidArgumentException(sprintf('Constructor of %s isn\'t supported because it needs arguments.', $class)); + } + + return $rfl->newInstance(); + } + + private function getFromKernel($service) + { + if ("@" !== substr($service, 0, 1)) { + + return; + } + + if (null === $this->kernel) { + + return; + } + + $service = substr($service, 1); + + if (false === $this->kernel->getContainer()->has($service)) { + + throw new ServiceNotFoundException($service); + } + + return $this->kernel->getContainer()->get($service); + } +} diff --git a/src/Knp/FriendlyExtension/DependencyInjection/Compiler/SetArgumentToNullPass.php b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/SetArgumentToNullPass.php new file mode 100644 index 00000000..722f2059 --- /dev/null +++ b/src/Knp/FriendlyExtension/DependencyInjection/Compiler/SetArgumentToNullPass.php @@ -0,0 +1,38 @@ +findTaggedServiceIds('null-when-missing') as $id => $tags) { + $definition = $container->getDefinition($id); + $arguments = $definition->getArguments(); + foreach ($tags as $tag) { + if (!isset($tag['service'])) { + continue; + } + + if ($container->hasDefinition($tag['service'])) { + continue; + } + + if ($container->hasAlias($tag['service'])) { + continue; + } + + foreach ($arguments as $index => $argument) { + if ($tag['service'] === (string)$argument) { + $arguments[$index] = null; + } + } + + $definition->setArguments($arguments); + } + } + } +} diff --git a/src/Knp/FriendlyExtension/services/alice.yml b/src/Knp/FriendlyExtension/services/alice.yml new file mode 100644 index 00000000..7192289e --- /dev/null +++ b/src/Knp/FriendlyExtension/services/alice.yml @@ -0,0 +1,7 @@ +services: + friendly.alice.class_loader: + class: Knp\FriendlyExtension\Alice\ClassLoader + arguments: + - @friendly.symfony.kernel + tags: + - { name: null-when-missing, service: friendly.symfony.kernel } From 531e3d1029579e00d1bf0baea1c0f3f69e12f9f6 Mon Sep 17 00:00:00 2001 From: Pierre PLAZANET Date: Tue, 14 Oct 2014 17:49:09 +0100 Subject: [PATCH 16/33] Add alice config --- src/Knp/FriendlyExtension.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Knp/FriendlyExtension.php b/src/Knp/FriendlyExtension.php index 78b15bbf..e7924dfa 100755 --- a/src/Knp/FriendlyExtension.php +++ b/src/Knp/FriendlyExtension.php @@ -66,6 +66,9 @@ public function configure(ArrayNodeDefinition $builder) ->arrayNode('alice') ->addDefaultsIfNotSet() ->children() + ->scalarNode('locale') + ->defaultValue('en_US') + ->end() ->arrayNode('fixtures') ->prototype('scalar')->end() ->end() @@ -75,6 +78,12 @@ public function configure(ArrayNodeDefinition $builder) ->prototype('scalar')->end() ->end() ->end() + ->arrayNode('providers') + ->prototype('scalar')->end() + ->end() + ->arrayNode('processors') + ->prototype('scalar')->end() + ->end() ->end() ->end() ->arrayNode('page') From 0fe226de9c0b02926d79a31c6071ce88e03867c1 Mon Sep 17 00:00:00 2001 From: Pierre PLAZANET Date: Wed, 15 Oct 2014 09:34:29 +0100 Subject: [PATCH 17/33] Move smartstep feature, intraduce alice --- composer.json | 6 +- .../Call/CallCenter.php | 4 +- .../Context/Helper/AliceHelper.php | 58 +++++++++++++++++++ .../Definition/DefinitionFinder.php | 6 +- .../Reader/SmartReader.php | 18 +++--- src/Knp/FriendlyExtension/services/core.yml | 25 ++++++++ 6 files changed, 100 insertions(+), 17 deletions(-) rename src/Knp/{FriendlyContexts => FriendlyExtension}/Call/CallCenter.php (90%) create mode 100644 src/Knp/FriendlyExtension/Context/Helper/AliceHelper.php rename src/Knp/{FriendlyContexts => FriendlyExtension}/Definition/DefinitionFinder.php (92%) rename src/Knp/{FriendlyContexts => FriendlyExtension}/Reader/SmartReader.php (96%) diff --git a/composer.json b/composer.json index c944332d..2fa87a60 100755 --- a/composer.json +++ b/composer.json @@ -8,14 +8,14 @@ }, "require": { "behat/behat": "~3.0", - "behat/mink-extension": "~2@dev", + "behat/mink-extension": "~2.0", "doctrine/common": "~2.0", "doctrine/data-fixtures": "~1.0", "doctrine/orm": "~2.0", "doctrine/inflector": "~1.0", "fzaninotto/faker": "~1.0", "guzzle/guzzle": "~3.7", - "nelmio/alice": "~1.0", + "nelmio/alice": "~1", "symfony/property-access": "~2.0", "symfony/http-kernel": "~2.0", "symfony/framework-bundle": "~2.0" @@ -37,5 +37,5 @@ "config": { "bin-dir": "bin" }, - "minimum-stability": "dev" + "minimum-stability": "stable" } diff --git a/src/Knp/FriendlyContexts/Call/CallCenter.php b/src/Knp/FriendlyExtension/Call/CallCenter.php similarity index 90% rename from src/Knp/FriendlyContexts/Call/CallCenter.php rename to src/Knp/FriendlyExtension/Call/CallCenter.php index 4950a0e6..9b8303f4 100755 --- a/src/Knp/FriendlyContexts/Call/CallCenter.php +++ b/src/Knp/FriendlyExtension/Call/CallCenter.php @@ -1,9 +1,9 @@ classLoader = $classLoader; + $this->tagLoader = $tagLoader; + $this->locale = $locale; + $this->fixtures = $fixtures; + $this->dependencies = $dependencies; + $this->providers = $providers; + $this->processors = $processors; + } + + public function loadFilturesFiles() + { + if (null === $this->tagLoader->getTag('alice')) { + + return; + } + } + + public function loadFixtureFile($file) + { + + } + + protected function resolveDependencies($fixture, array &$result = []) + { + $result[] = $fixture; + $tree = $this->getParameter('friendly.alice.dependencies'); + + if (!empty($tree[$fixture])) { + foreach ($tree[$fixture] as $dep) { + if (!in_array($dep, $result)) { + $this->resolveDeps($dep, $result); + } + } + } + + return $result; + } +} diff --git a/src/Knp/FriendlyContexts/Definition/DefinitionFinder.php b/src/Knp/FriendlyExtension/Definition/DefinitionFinder.php similarity index 92% rename from src/Knp/FriendlyContexts/Definition/DefinitionFinder.php rename to src/Knp/FriendlyExtension/Definition/DefinitionFinder.php index 906d9b51..ad7381a3 100755 --- a/src/Knp/FriendlyContexts/Definition/DefinitionFinder.php +++ b/src/Knp/FriendlyExtension/Definition/DefinitionFinder.php @@ -1,11 +1,11 @@ Date: Wed, 15 Oct 2014 09:35:07 +0100 Subject: [PATCH 18/33] Fix service def --- src/Knp/FriendlyExtension/services/core.yml | 47 ++++++++++----------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/src/Knp/FriendlyExtension/services/core.yml b/src/Knp/FriendlyExtension/services/core.yml index c9b30ce6..76ea973f 100755 --- a/src/Knp/FriendlyExtension/services/core.yml +++ b/src/Knp/FriendlyExtension/services/core.yml @@ -1,7 +1,17 @@ services: + friendly.call.call_center: + class: Knp\FriendlyExtension\Call\CallCenter + arguments: + - @call.center + friendly.command.command_loader: class: Knp\FriendlyExtension\Command\CommandLoader + friendly.definition.definition_finder: + class: Knp\FriendlyExtension\Definition\DefinitionFinder + arguments: + - @definition.finder + friendly.doctrine.resolver: class: Knp\FriendlyExtension\Doctrine\Resolver arguments: @@ -29,6 +39,18 @@ services: tags: - { name: event_dispatcher.listener, event: tester.scenario_tested.before, method: beforeScenario } + friendly.reader.smart_reader: + class: Knp\FriendlyExtension\Reader\SmartReader + arguments: + - @gherkin + - @suite.registry + - @specifications.locator.filesystem_feature + - @friendly.definition.definition_finder + - @friendly.call.call_center + - %friendly.smartTag% + tags: + - { name: environment.reader } + friendly.record.collection.bag: class: Knp\FriendlyExtension\Record\Collection\Bag arguments: @@ -45,28 +67,3 @@ services: friendly.utils.text_formater: class: Knp\FriendlyExtension\Utils\TextFormater - - - friendly.reader.smart_reader: - class: Knp\FriendlyContexts\Reader\SmartReader - arguments: - - @gherkin - - @suite.registry - - @specifications.locator.filesystem_feature - - @friendly.definition.definition_finder - - @friendly.call.call_center - - %friendly.smartTag% - tags: - - { name: environment.reader } - - - - friendly.call.call_center: - class: Knp\FriendlyExtension\Call\CallCenter - arguments: - - @call.center - - friendly.definition.definition_finder: - class: Knp\FriendlyExtension\Definition\DefinitionFinder - arguments: - - @definition.finder From 880a5d070eca2eb4ad6f042c9d9ac1b5937ed351 Mon Sep 17 00:00:00 2001 From: Pierre PLAZANET Date: Wed, 15 Oct 2014 10:01:21 +0100 Subject: [PATCH 19/33] Migrate API classes and Page classes --- src/Knp/FriendlyContexts/services/builder.yml | 45 ------------------ src/Knp/FriendlyExtension.php | 3 +- .../Builder/AbstractRequestBuilder.php | 3 +- .../Builder/DeleteRequestBuilder.php | 4 +- .../Builder/GetRequestBuilder.php | 3 +- .../Builder/HeadRequestBuilder.php | 4 +- .../Builder/OptionsRequestBuilder.php | 4 +- .../Builder/PatchRequestBuilder.php | 4 +- .../Builder/PostRequestBuilder.php | 3 +- .../Builder/PutRequestBuilder.php | 4 +- .../Builder/RequestBuilder.php | 5 +- .../Builder/RequestBuilderInterface.php | 2 +- src/Knp/FriendlyExtension/Entity/Hydrator.php | 2 +- .../Http/Factory/OauthPluginFactory.php | 2 +- .../Http/HttpContentTypeGuesser.php | 2 +- .../Http/Security/HttpBasicExtension.php | 4 +- .../Http/Security/OauthExtension.php | 8 ++-- .../Security/SecurityExtensionInterface.php | 4 +- .../Node/FeatureWalker.php | 2 +- .../Page/Page.php | 2 +- .../Page/Resolver/PageClassResolver.php | 4 +- .../Request/RequestMethods.php | 2 +- .../FriendlyExtension/services/builder.yml | 46 +++++++++++++++++++ src/Knp/FriendlyExtension/services/core.yml | 10 +++- 24 files changed, 98 insertions(+), 74 deletions(-) delete mode 100755 src/Knp/FriendlyContexts/services/builder.yml rename src/Knp/{FriendlyContexts => FriendlyExtension}/Builder/AbstractRequestBuilder.php (89%) rename src/Knp/{FriendlyContexts => FriendlyExtension}/Builder/DeleteRequestBuilder.php (89%) rename src/Knp/{FriendlyContexts => FriendlyExtension}/Builder/GetRequestBuilder.php (83%) rename src/Knp/{FriendlyContexts => FriendlyExtension}/Builder/HeadRequestBuilder.php (83%) rename src/Knp/{FriendlyContexts => FriendlyExtension}/Builder/OptionsRequestBuilder.php (83%) rename src/Knp/{FriendlyContexts => FriendlyExtension}/Builder/PatchRequestBuilder.php (88%) rename src/Knp/{FriendlyContexts => FriendlyExtension}/Builder/PostRequestBuilder.php (84%) rename src/Knp/{FriendlyContexts => FriendlyExtension}/Builder/PutRequestBuilder.php (88%) rename src/Knp/{FriendlyContexts => FriendlyExtension}/Builder/RequestBuilder.php (97%) rename src/Knp/{FriendlyContexts => FriendlyExtension}/Builder/RequestBuilderInterface.php (88%) rename src/Knp/{FriendlyContexts => FriendlyExtension}/Http/Factory/OauthPluginFactory.php (78%) rename src/Knp/{FriendlyContexts => FriendlyExtension}/Http/HttpContentTypeGuesser.php (98%) rename src/Knp/{FriendlyContexts => FriendlyExtension}/Http/Security/HttpBasicExtension.php (87%) rename src/Knp/{FriendlyContexts => FriendlyExtension}/Http/Security/OauthExtension.php (79%) rename src/Knp/{FriendlyContexts => FriendlyExtension}/Http/Security/SecurityExtensionInterface.php (72%) rename src/Knp/{FriendlyContexts => FriendlyExtension}/Node/FeatureWalker.php (96%) rename src/Knp/{FriendlyContexts => FriendlyExtension}/Page/Page.php (82%) rename src/Knp/{FriendlyContexts => FriendlyExtension}/Page/Resolver/PageClassResolver.php (96%) rename src/Knp/{FriendlyContexts => FriendlyExtension}/Request/RequestMethods.php (85%) create mode 100644 src/Knp/FriendlyExtension/services/builder.yml diff --git a/src/Knp/FriendlyContexts/services/builder.yml b/src/Knp/FriendlyContexts/services/builder.yml deleted file mode 100755 index d81dc3e1..00000000 --- a/src/Knp/FriendlyContexts/services/builder.yml +++ /dev/null @@ -1,45 +0,0 @@ -services: - friendly.http_client: - class: Guzzle\Http\Client - arguments: - - %friendly.api.base_url% - - friendly.builder.get_request_builder: - class: Knp\FriendlyContexts\Builder\GetRequestBuilder - calls: - - [setClient, ['@friendly.http_client']] - - friendly.builder.post_request_builder: - class: Knp\FriendlyContexts\Builder\PostRequestBuilder - calls: - - [setClient, ['@friendly.http_client']] - - friendly.builder.put_request_builder: - class: Knp\FriendlyContexts\Builder\PutRequestBuilder - calls: - - [setClient, ['@friendly.http_client']] - - friendly.builder.patch_request_builder: - class: Knp\FriendlyContexts\Builder\PatchRequestBuilder - calls: - - [setClient, ['@friendly.http_client']] - - friendly.builder.delete_request_builder: - class: Knp\FriendlyContexts\Builder\DeleteRequestBuilder - calls: - - [setClient, ['@friendly.http_client']] - - friendly.builder.options_request_builder: - class: Knp\FriendlyContexts\Builder\OptionsRequestBuilder - calls: - - [setClient, ['@friendly.http_client']] - - friendly.builder.request_builder: - class: Knp\FriendlyContexts\Builder\RequestBuilder - calls: - - [addRequestBuilder, ['@friendly.builder.get_request_builder', 'GET']] - - [addRequestBuilder, ['@friendly.builder.post_request_builder', 'POST']] - - [addRequestBuilder, ['@friendly.builder.put_request_builder', 'PUT']] - - [addRequestBuilder, ['@friendly.builder.patch_request_builder', 'PATCH']] - - [addRequestBuilder, ['@friendly.builder.delete_request_builder', 'DELETE']] - - [addRequestBuilder, ['@friendly.builder.options_request_builder', 'OPTIONS']] diff --git a/src/Knp/FriendlyExtension.php b/src/Knp/FriendlyExtension.php index e7924dfa..d8421d78 100755 --- a/src/Knp/FriendlyExtension.php +++ b/src/Knp/FriendlyExtension.php @@ -110,7 +110,7 @@ public function configure(ArrayNodeDefinition $builder) ->end() ->end() ->end() - ->scalarNode('smartTag') + ->scalarNode('smart_tag') ->defaultValue('smartStep') ->end() ->end() @@ -125,6 +125,7 @@ public function load(ContainerBuilder $container, array $config) $loader->load('core.yml'); $loader->load('faker.yml'); $loader->load('guesser.yml'); + $loader->load('builder.yml'); $loader->load('symfony.yml'); $container->setParameter('friendly.parameters', $config); diff --git a/src/Knp/FriendlyContexts/Builder/AbstractRequestBuilder.php b/src/Knp/FriendlyExtension/Builder/AbstractRequestBuilder.php similarity index 89% rename from src/Knp/FriendlyContexts/Builder/AbstractRequestBuilder.php rename to src/Knp/FriendlyExtension/Builder/AbstractRequestBuilder.php index 638c7b21..71696288 100755 --- a/src/Knp/FriendlyContexts/Builder/AbstractRequestBuilder.php +++ b/src/Knp/FriendlyExtension/Builder/AbstractRequestBuilder.php @@ -1,8 +1,9 @@ Date: Thu, 16 Oct 2014 10:52:25 +0100 Subject: [PATCH 20/33] Add page context and behat tests --- .travis.yml | 1 + behat.yml.dist | 15 ++- composer.json | 22 ++-- features/Context/FeatureContext.php | 9 ++ features/Context/ServerContext.php | 70 ++++++++++ features/Page/APage.php | 13 ++ features/Page/IndexPage.php | 13 ++ features/Page/TablePage.php | 13 ++ features/html/index.html | 1 + features/html/table1.html | 61 +++++++++ features/page.feature | 28 ++++ .../Gherkin/Node/ExplorerSpec.php | 57 -------- .../Context/Helper/AbstractHelper.php | 4 + .../Context/Helper/AliceHelper.php | 5 + .../Context/Helper/ApiHelper.php | 13 ++ .../Context/Helper/AsserterHelper.php | 4 - .../Context/Helper/CommandHelper.php | 4 - .../Context/Helper/MinkHelper.php | 47 +++++++ .../Context/Helper/PageHelper.php | 124 ++++++++++++++++++ .../FriendlyExtension/Context/PageContext.php | 47 +++++++ .../Gherkin/Node/Explorer.php | 87 ------------ .../FriendlyExtension/Reader/SmartReader.php | 2 +- .../FriendlyExtension/services/context.yml | 15 +++ src/Knp/FriendlyExtension/services/core.yml | 2 +- 24 files changed, 491 insertions(+), 166 deletions(-) create mode 100644 features/Context/FeatureContext.php create mode 100644 features/Context/ServerContext.php create mode 100644 features/Page/APage.php create mode 100644 features/Page/IndexPage.php create mode 100644 features/Page/TablePage.php create mode 100644 features/html/index.html create mode 100644 features/html/table1.html create mode 100644 features/page.feature delete mode 100644 spec/Knp/FriendlyExtension/Gherkin/Node/ExplorerSpec.php create mode 100644 src/Knp/FriendlyExtension/Context/Helper/ApiHelper.php create mode 100644 src/Knp/FriendlyExtension/Context/Helper/MinkHelper.php create mode 100644 src/Knp/FriendlyExtension/Context/Helper/PageHelper.php create mode 100644 src/Knp/FriendlyExtension/Context/PageContext.php delete mode 100644 src/Knp/FriendlyExtension/Gherkin/Node/Explorer.php diff --git a/.travis.yml b/.travis.yml index f4bba82f..81bd606d 100755 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,7 @@ before_script: script: - bin/phpspec run -fpretty + - bin/behat --no-snippets --verbose notifications: webhooks: diff --git a/behat.yml.dist b/behat.yml.dist index 57a61836..72bae151 100755 --- a/behat.yml.dist +++ b/behat.yml.dist @@ -1,9 +1,20 @@ default: autoload: "Context": %paths.base%/features + "Page": %paths.base%/features suites: default: path: %paths.base%/features - contexts: ~ + contexts: + - Context\FeatureContext + - Context\ServerContext + - Knp\FriendlyExtension\Context\PageContext extensions: - Knp\FriendlyExtension: ~ + Knp\FriendlyExtension: + smart_tag: 'smart-step' + Behat\MinkExtension: + base_url: 'http://localhost:8080/' + goutte: ~ + selenium2: ~ + default_session: goutte + javascript_session: selenium2 diff --git a/composer.json b/composer.json index 2fa87a60..a4e3134d 100755 --- a/composer.json +++ b/composer.json @@ -6,22 +6,24 @@ "Knp\\FriendlyExtension": "src/" } }, - "require": { + "require": { "behat/behat": "~3.0", - "behat/mink-extension": "~2.0", - "doctrine/common": "~2.0", - "doctrine/data-fixtures": "~1.0", - "doctrine/orm": "~2.0", - "doctrine/inflector": "~1.0", "fzaninotto/faker": "~1.0", "guzzle/guzzle": "~3.7", "nelmio/alice": "~1", - "symfony/property-access": "~2.0", - "symfony/http-kernel": "~2.0", - "symfony/framework-bundle": "~2.0" + "symfony/property-access": "~2.0" }, "require-dev": { - "phpspec/phpspec": "~2.0.0" + "symfony/http-kernel": "~2.0", + "symfony/framework-bundle": "~2.0", + "doctrine/common": "~2.0", + "doctrine/data-fixtures": "~1.0", + "doctrine/orm": "~2.0", + "doctrine/inflector": "~1.0", + "behat/mink-extension": "~2.0", + "behat/mink-goutte-driver": "~1.0", + "behat/mink-selenium2-driver": "~1.0", + "phpspec/phpspec": "~2.0" }, "license": "MIT", "authors": [ diff --git a/features/Context/FeatureContext.php b/features/Context/FeatureContext.php new file mode 100644 index 00000000..86f0ca3f --- /dev/null +++ b/features/Context/FeatureContext.php @@ -0,0 +1,9 @@ + %s 2>&1 & echo $! >> %s", $command, $outputfile, self::$proc)); + + $loop = 0; + while ($loop < 5) { + try { + self::test(); + return; + } catch (\Exception $ex) { + $loop++; + sleep(1); + } + } + } + + /** + * @BeforeScenario + */ + public static function test() + { + $ch = curl_init(sprintf('%s/html/index.html', self::SERVER_ADDRESS)); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_exec($ch); + + if (200 !== curl_getinfo($ch, CURLINFO_HTTP_CODE)) { + + throw new \Exception('PHP builtin server is down.'); + } else { + + return; + } + } + + /** + * @AfterSuite + */ + public static function stop() + { + if (file_exists(self::$proc)) { + $pids = file(self::$proc); + foreach ($pids as $pid) { + shell_exec('kill -9 ' . $pid); + } + unlink(self::$proc); + } + } +} diff --git a/features/Page/APage.php b/features/Page/APage.php new file mode 100644 index 00000000..6c60879d --- /dev/null +++ b/features/Page/APage.php @@ -0,0 +1,13 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
GenderFirstnameLastname
Mr.GoergesAbitbol
Mr.JohnDO
Dr.DoctorWHO
+ Copyright KNPLabs +
+ + + + + + + + + + + + + + + + + + + + + + +
AddressCityCountry
My Address + ParisFrance
Good StreetLondonEngland
Perfect HouseBerlinGERMANY
+ + diff --git a/features/page.feature b/features/page.feature new file mode 100644 index 00000000..e848593e --- /dev/null +++ b/features/page.feature @@ -0,0 +1,28 @@ +Feature: I am able to navigate between pages + + @smart-step + Scenario: I open a page + When I go to the table page + Then I should be on the table page + + @smart-step + Scenario: I change the page + Given I open a page + When I go to the index page + Then I should be on the index page + + Scenario: I come bak to the first page + Given I change the page + When I go to the table page + Then I should be on the table page + + Scenario: I should be on a compite page + Given I am on the a page with: + | part | html | + | file | index | + | extension | html | + When I go to the table page + Then I should be on the a page with: + | part | html | + | file | table1 | + | extension | html | diff --git a/spec/Knp/FriendlyExtension/Gherkin/Node/ExplorerSpec.php b/spec/Knp/FriendlyExtension/Gherkin/Node/ExplorerSpec.php deleted file mode 100644 index 639d7268..00000000 --- a/spec/Knp/FriendlyExtension/Gherkin/Node/ExplorerSpec.php +++ /dev/null @@ -1,57 +0,0 @@ -getTags()->willReturn([ - 'javascript', - 'reset-schema', - '~admin', - 'alice(Product)', - 'alice(User)', - ]); - $scenario->getTags()->willReturn([ - '~javascript', - 'admin', - 'alice(Prototype, Order)', - '~alice(User)', - ]); - - $this->beConstructedWith($feature); - } - - function it_is_initializable() - { - $this->shouldHaveType('Knp\FriendlyExtension\Gherkin\Node\Explorer'); - } - - function it_returns_feature_tags() - { - $this->getTags()->shouldReturn([ 'alice', 'javascript', 'reset-schema' ]); - } - - function it_returns_scenario_tags(FeatureNode $feature, ScenarioNode $scenario) - { - $this->beConstructedWith($feature, $scenario); - $this->getTags()->shouldReturn([ 'admin', 'alice', 'reset-schema' ]); - } - - function it_return_arguments() - { - $this->getArguments('alice')->shouldReturn([ 'Product', 'User' ]); - } - - function it_return_arguments_with_scenario(FeatureNode $feature, ScenarioNode $scenario) - { - $this->beConstructedWith($feature, $scenario); - $this->getArguments('alice')->shouldReturn([ 'Order', 'Product', 'Prototype' ]); - } -} diff --git a/src/Knp/FriendlyExtension/Context/Helper/AbstractHelper.php b/src/Knp/FriendlyExtension/Context/Helper/AbstractHelper.php index 606692c6..6df71bae 100644 --- a/src/Knp/FriendlyExtension/Context/Helper/AbstractHelper.php +++ b/src/Knp/FriendlyExtension/Context/Helper/AbstractHelper.php @@ -17,4 +17,8 @@ public function get($name) { return $this->registry->get($name); } + + public function clear() + { + } } diff --git a/src/Knp/FriendlyExtension/Context/Helper/AliceHelper.php b/src/Knp/FriendlyExtension/Context/Helper/AliceHelper.php index 20b796d5..a514258b 100644 --- a/src/Knp/FriendlyExtension/Context/Helper/AliceHelper.php +++ b/src/Knp/FriendlyExtension/Context/Helper/AliceHelper.php @@ -27,6 +27,11 @@ public function __construct(ClassLoader $classLoader, TagLoader $tagLoader, $loc $this->processors = $processors; } + public function getName() + { + return 'alice'; + } + public function loadFilturesFiles() { if (null === $this->tagLoader->getTag('alice')) { diff --git a/src/Knp/FriendlyExtension/Context/Helper/ApiHelper.php b/src/Knp/FriendlyExtension/Context/Helper/ApiHelper.php new file mode 100644 index 00000000..0a076a79 --- /dev/null +++ b/src/Knp/FriendlyExtension/Context/Helper/ApiHelper.php @@ -0,0 +1,13 @@ +explode($real), $this->explode($expected)); diff --git a/src/Knp/FriendlyExtension/Context/Helper/CommandHelper.php b/src/Knp/FriendlyExtension/Context/Helper/CommandHelper.php index f6b7ae57..1c81f16d 100644 --- a/src/Knp/FriendlyExtension/Context/Helper/CommandHelper.php +++ b/src/Knp/FriendlyExtension/Context/Helper/CommandHelper.php @@ -53,10 +53,6 @@ public function buildCommand(Application $application, $name) return new CommandTester($application->getCommand($name)); } - public function clear() - { - } - public function getName() { return 'command'; diff --git a/src/Knp/FriendlyExtension/Context/Helper/MinkHelper.php b/src/Knp/FriendlyExtension/Context/Helper/MinkHelper.php new file mode 100644 index 00000000..9600504e --- /dev/null +++ b/src/Knp/FriendlyExtension/Context/Helper/MinkHelper.php @@ -0,0 +1,47 @@ +mink = $mink; + $this->minkParameters = $minkParameters; + } + + public function getName() + { + return 'mink'; + } + + public function getMink() + { + return $this->mink; + } + + public function getMinkParameter($name) + { + return isset($this->minkParameters[$name]) ? $this->minkParameters[$name] : null; + } + + public function getSession($name = null) + { + return $this->mink->getSession($name); + } + + public function assertSession($name = null) + { + return $this->mink->assertSession($name); + } + + public function locatePath($path) + { + $startUrl = rtrim($this->getMinkParameter('base_url'), '/') . '/'; + + return 0 !== strpos($path, 'http') ? $startUrl . ltrim($path, '/') : $path; + } +} diff --git a/src/Knp/FriendlyExtension/Context/Helper/PageHelper.php b/src/Knp/FriendlyExtension/Context/Helper/PageHelper.php new file mode 100644 index 00000000..6170933a --- /dev/null +++ b/src/Knp/FriendlyExtension/Context/Helper/PageHelper.php @@ -0,0 +1,124 @@ +pageClassResolver = $pageClassResolver; + } + + public function getName() + { + return 'page'; + } + + public function getPage($page) + { + if (isset($this->pages[$page])) { + return $this->pages[$page]; + } + + $class = $this->pageClassResolver->resolveName($page); + + $this->pages[$page] = $this->pageClassResolver->create( + $this->get('mink')->getSession(), + $class + ); + + return $this->pages[$page]; + } + + public function getPagePath($page, $arguments = null) + { + list($parameters, $entities) = $this->extractTable($arguments); + + $page = $this->getPage($page); + + return $this->resolvePagePath($page, $parameters, $entities); + } + + private function resolvePagePath(Page $page, $parameters, $entities) + { + $path = $page->getPath(); + + foreach ($parameters as $key => $value) { + $path = str_replace(sprintf('{%s}', $key), $value, $path); + } + + if (!preg_match_all('/\{([a-zA-Z0-9]+\.[a-zA-Z0-9]+)\}/', $path, $matches)) { + return $path; + } + + $properties = array(); + + foreach ($matches[1] as $parameter) { + list($entityName, $field) = explode('.', $parameter); + + if (!isset($entities[$entityName])) { + throw new \Exception(sprintf( + 'No entity can be resolved for "%s"', + $entityName + )); + } + + $entity = $entities[$entityName]; + $properties[] = PropertyAccess::createPropertyAccessor() + ->getValue($entity, $field) + ; + } + + foreach ($matches[0] as $index => $pattern) { + $path = str_replace($pattern, $properties[$index], $path); + } + + return $path; + } + + private function extractTable($parameters = null) + { + if (null === $parameters) { + return [[], []]; + } + + if ($parameters instanceof TableNode) { + $parameters = $parameters->getRowsHash(); + } + + if (!is_array($parameters)) { + throw new \InvalidArgumentException( + 'You must precised a valid array or Behat\Gherkin\Node\TableNode to extract' + ); + } + + $entities = []; + + foreach ($parameters as $name => $value) { + $matches = array(); + if (preg_match('/^the (.+) "([^"]+)"$/', $value, $matches)) { + if (null === $entity = $this->get('record')->find($matches[1], $matches[2])) { + throw new \Exception(sprintf( + 'No entity %s has been found for "%s"', + $class, + $field + )); + } + + $entities[$name] = $entity; + unset($parameters[$name]); + } + } + + return array($parameters, $entities); + } +} diff --git a/src/Knp/FriendlyExtension/Context/PageContext.php b/src/Knp/FriendlyExtension/Context/PageContext.php new file mode 100644 index 00000000..d4ac1c9e --- /dev/null +++ b/src/Knp/FriendlyExtension/Context/PageContext.php @@ -0,0 +1,47 @@ +get('page')->getPagePath($page, $table); + $this + ->get('mink') + ->getSession() + ->visit( + $this->get('mink')->locatePath($page) + ) + ; + } + + /** + * @Then /^I should be on the (.*) page$/ + * @Then /^I should be on the (.*) page with:?$/ + */ + public function iShouldBeOnThePageWith($page, TableNode $table = null) + { + $page = $this->get('page')->getPagePath($page, $table); + try { + $this->get('mink')->assertSession()->addressEquals($page); + } catch (\Exception $e) { + $this + ->get('mink') + ->assertSession() + ->addressEquals( + sprintf('%s/', $page) + ) + ; + } + } +} diff --git a/src/Knp/FriendlyExtension/Gherkin/Node/Explorer.php b/src/Knp/FriendlyExtension/Gherkin/Node/Explorer.php deleted file mode 100644 index eade3a95..00000000 --- a/src/Knp/FriendlyExtension/Gherkin/Node/Explorer.php +++ /dev/null @@ -1,87 +0,0 @@ -feature = $feature; - $this->scenario = $scenario; - } - - public function getTags($values = false) - { - $results = []; - $this->extract($this->feature, $results); - if (null !== $this->scenario) { - $this->extract($this->scenario, $results); - } - - return $values ? $results : array_keys($results); - } - - public function hasTag($tag) - { - return in_array($tag, $this->getTags()); - } - - public function getArguments($tag) - { - if (false === $this->hasTag($tag)) { - - return; - } - - $tags = $this->getTags(true); - - return $tags[$tag]; - } - - private function extract(TaggedNodeInterface $element, array &$results) - { - foreach ($element->getTags() as $tag) { - $negative = (0 === strpos($tag, '~')); - $tag = $negative ? substr($tag, 1) : $tag; - $matches = []; - if (0 !== preg_match('/^(.+)\((.*)\)$/', $tag, $matches)) { - list($str, $tag, $arguments) = $matches; - $arguments = explode(',', $arguments); - $arguments = array_map('trim', $arguments); - $arguments = array_filter($arguments, function ($e) { return false === empty($e); }); - if ($negative) { - foreach ($arguments as $argument) { - if ( - array_key_exists($tag, $results) - && false !== $index = array_search($argument, $results[$tag]) - ) { - unset($results[$tag][$index]); - } - } - } else { - foreach ($arguments as $argument) { - $results[$tag][] = $argument; - } - } - sort($results[$tag]); - } else { - if ($negative) { - if (array_key_exists($tag, $results)) { - unset($results[$tag]); - } - } else { - $results[$tag] = []; - } - } - } - - ksort($results); - } -} diff --git a/src/Knp/FriendlyExtension/Reader/SmartReader.php b/src/Knp/FriendlyExtension/Reader/SmartReader.php index 1459c1e1..be8236a7 100755 --- a/src/Knp/FriendlyExtension/Reader/SmartReader.php +++ b/src/Knp/FriendlyExtension/Reader/SmartReader.php @@ -76,7 +76,7 @@ protected function buildCallee($feature, $scenario, $callable) $description = sprintf('%s:%s', $feature->getFile(), $scenario->getLine()); return [ - new Call\Given(sprintf('/^%s$/', $scenario->getTitle()), $callable, $description), + new Call\Given($scenario->getTitle(), $callable, $description), ]; } diff --git a/src/Knp/FriendlyExtension/services/context.yml b/src/Knp/FriendlyExtension/services/context.yml index 614f3527..1678068e 100644 --- a/src/Knp/FriendlyExtension/services/context.yml +++ b/src/Knp/FriendlyExtension/services/context.yml @@ -34,6 +34,15 @@ services: - { name: friendly.context.helper } - { name: remove-when-missing, service: friendly.doctrine.resolver } + friendly.context.helper.mink_helper: + class: Knp\FriendlyExtension\Context\Helper\MinkHelper + arguments: + - @mink + - %mink.parameters% + tags: + - { name: friendly.context.helper } + - { name: remove-when-missing, service: mink } + friendly.context.helper.record_helper: class: Knp\FriendlyExtension\Context\Helper\RecordHelper arguments: @@ -51,3 +60,9 @@ services: tags: - { name: context.initializer } + friendly.context.helper.page_helper: + class: Knp\FriendlyExtension\Context\Helper\PageHelper + arguments: + - @friendly.page.resolver.page_class_resolver + tags: + - { name: friendly.context.helper } diff --git a/src/Knp/FriendlyExtension/services/core.yml b/src/Knp/FriendlyExtension/services/core.yml index f9b53276..5cecb7fb 100755 --- a/src/Knp/FriendlyExtension/services/core.yml +++ b/src/Knp/FriendlyExtension/services/core.yml @@ -42,7 +42,7 @@ services: friendly.http.http_content_type_guesser: class: Knp\FriendlyExtension\Http\HttpContentTypeGuesser - friendly.page.resolver: + friendly.page.resolver.page_class_resolver: class: Knp\FriendlyExtension\Page\Resolver\PageClassResolver arguments: - %friendly.page.namespace% From 9f41cabc31fbcc10ddb3dd243f8c749d25b7342f Mon Sep 17 00:00:00 2001 From: Pierre PLAZANET Date: Thu, 16 Oct 2014 15:58:08 +0100 Subject: [PATCH 21/33] Add table and specs --- .../Builder/DeleteRequestBuilderSpec.php | 63 +++++++++ .../Builder/GetRequestBuilderSpec.php | 39 +++++ .../Builder/HeadRequestBuilderSpec.php | 41 ++++++ .../Builder/OptionsRequestBuilderSpec.php | 40 ++++++ .../Builder/PatchRequestBuilderSpec.php | 63 +++++++++ .../Builder/PostRequestBuilderSpec.php | 42 ++++++ .../Builder/PutRequestBuilderSpec.php | 63 +++++++++ .../Builder/RequestBuilderSpec.php | 95 +++++++++++++ .../Faker/UniqueCacheSpec.php | 31 ++++ .../Http/Factory/OauthPluginFactorySpec.php | 19 +++ .../Http/HttpContentTypeGuesserSpec.php | 32 +++++ .../Http/Security/HttpBasicExtensionSpec.php | 51 +++++++ .../Http/Security/OauthExtensionSpec.php | 50 +++++++ spec/Knp/FriendlyExtension/Page/PageSpec.php | 34 +++++ .../Page/Resolver/PageClassResolverSpec.php | 57 ++++++++ .../Reader/SmartReaderSpec.php | 24 ++++ spec/Knp/FriendlyExtension/Table/NodeSpec.php | 62 ++++++++ .../Utils/TextFormaterSpec.php | 43 ++++++ src/Knp/FriendlyExtension/Table/Node.php | 133 ++++++++++++++++++ .../Table/NodeCollection.php | 65 +++++++++ .../FriendlyExtension/Table/NodeFactory.php | 19 +++ .../FriendlyExtension/Table/NodesBuilder.php | 33 +++++ 22 files changed, 1099 insertions(+) create mode 100644 spec/Knp/FriendlyExtension/Builder/DeleteRequestBuilderSpec.php create mode 100644 spec/Knp/FriendlyExtension/Builder/GetRequestBuilderSpec.php create mode 100644 spec/Knp/FriendlyExtension/Builder/HeadRequestBuilderSpec.php create mode 100644 spec/Knp/FriendlyExtension/Builder/OptionsRequestBuilderSpec.php create mode 100644 spec/Knp/FriendlyExtension/Builder/PatchRequestBuilderSpec.php create mode 100644 spec/Knp/FriendlyExtension/Builder/PostRequestBuilderSpec.php create mode 100644 spec/Knp/FriendlyExtension/Builder/PutRequestBuilderSpec.php create mode 100644 spec/Knp/FriendlyExtension/Builder/RequestBuilderSpec.php create mode 100644 spec/Knp/FriendlyExtension/Faker/UniqueCacheSpec.php create mode 100644 spec/Knp/FriendlyExtension/Http/Factory/OauthPluginFactorySpec.php create mode 100644 spec/Knp/FriendlyExtension/Http/HttpContentTypeGuesserSpec.php create mode 100644 spec/Knp/FriendlyExtension/Http/Security/HttpBasicExtensionSpec.php create mode 100644 spec/Knp/FriendlyExtension/Http/Security/OauthExtensionSpec.php create mode 100644 spec/Knp/FriendlyExtension/Page/PageSpec.php create mode 100644 spec/Knp/FriendlyExtension/Page/Resolver/PageClassResolverSpec.php create mode 100644 spec/Knp/FriendlyExtension/Reader/SmartReaderSpec.php create mode 100644 spec/Knp/FriendlyExtension/Table/NodeSpec.php create mode 100644 spec/Knp/FriendlyExtension/Utils/TextFormaterSpec.php create mode 100644 src/Knp/FriendlyExtension/Table/Node.php create mode 100644 src/Knp/FriendlyExtension/Table/NodeCollection.php create mode 100644 src/Knp/FriendlyExtension/Table/NodeFactory.php create mode 100644 src/Knp/FriendlyExtension/Table/NodesBuilder.php diff --git a/spec/Knp/FriendlyExtension/Builder/DeleteRequestBuilderSpec.php b/spec/Knp/FriendlyExtension/Builder/DeleteRequestBuilderSpec.php new file mode 100644 index 00000000..1d86b7cf --- /dev/null +++ b/spec/Knp/FriendlyExtension/Builder/DeleteRequestBuilderSpec.php @@ -0,0 +1,63 @@ +shouldHaveType('Knp\FriendlyExtension\Builder\DeleteRequestBuilder'); + } + + function it_is_a_request_builder() + { + $this->shouldHaveType('Knp\FriendlyExtension\Builder\RequestBuilderInterface'); + } + + function it_build_a_delete_request(ClientInterface $client, RequestInterface $request) + { + $client->delete( + '/resource?foo=bar', + ['some headers'], + 'body', + ['some options'] + )->shouldBeCalled(1)->willReturn($request); + + $this->setClient($client); + + $this->build( + '/resource', + ['foo' => 'bar'], + ['some headers'], + null, + 'body', + ['some options'] + )->shouldReturn($request); + } + + function it_format_body_to_a_valid_form_urlencod_request(ClientInterface $client, RequestInterface $request) + { + $client->delete( + '/resource?foo=bar', + ['Content-Type' => 'application/x-www-form-urlencoded'], + 'foo=bar&baz=plop', + ['some options'] + )->shouldBeCalled(1)->willReturn($request); + + $this->setClient($client); + + $this->build( + '/resource', + ['foo' => 'bar'], + null, + null, + ['foo' => 'bar', 'baz' => 'plop'], + ['some options'] + )->shouldReturn($request); + } +} diff --git a/spec/Knp/FriendlyExtension/Builder/GetRequestBuilderSpec.php b/spec/Knp/FriendlyExtension/Builder/GetRequestBuilderSpec.php new file mode 100644 index 00000000..6a67c1ac --- /dev/null +++ b/spec/Knp/FriendlyExtension/Builder/GetRequestBuilderSpec.php @@ -0,0 +1,39 @@ +shouldHaveType('Knp\FriendlyExtension\Builder\GetRequestBuilder'); + } + + function it_is_a_request_builder() + { + $this->shouldHaveType('Knp\FriendlyExtension\Builder\RequestBuilderInterface'); + } + + function it_can_not_build_request_without_client() + { + $this->shouldThrow('RuntimeException')->duringBuild(); + } + + function it_build_a_get_request(ClientInterface $client, RequestInterface $request) + { + $client->get( + '/resource?foo=bar&baz=foo', + ['some headers'], + ['some options'] + )->shouldBeCalled(1)->willReturn($request); + + $this->setClient($client); + + $this->build('/resource', ['foo' => 'bar', 'baz' => 'foo'], ['some headers'], null, null, ['some options'])->shouldReturn($request); + } +} diff --git a/spec/Knp/FriendlyExtension/Builder/HeadRequestBuilderSpec.php b/spec/Knp/FriendlyExtension/Builder/HeadRequestBuilderSpec.php new file mode 100644 index 00000000..02814c29 --- /dev/null +++ b/spec/Knp/FriendlyExtension/Builder/HeadRequestBuilderSpec.php @@ -0,0 +1,41 @@ +shouldHaveType('Knp\FriendlyExtension\Builder\HeadRequestBuilder'); + } + + function it_is_a_builder() + { + $this->shouldHaveType('Knp\FriendlyExtension\Builder\RequestBuilderInterface'); + } + + function it_build_a_head_request(ClientInterface $client, RequestInterface $request) + { + $client->head( + '/resource?foo=bar', + ['some headers'], + ['some options'] + )->shouldBeCalled(1)->willReturn($request); + + $this->setClient($client); + + $this->build( + '/resource', + ['foo' => 'bar'], + ['some headers'], + null, + null, + ['some options'] + )->shouldReturn($request); + } +} diff --git a/spec/Knp/FriendlyExtension/Builder/OptionsRequestBuilderSpec.php b/spec/Knp/FriendlyExtension/Builder/OptionsRequestBuilderSpec.php new file mode 100644 index 00000000..be06a0ad --- /dev/null +++ b/spec/Knp/FriendlyExtension/Builder/OptionsRequestBuilderSpec.php @@ -0,0 +1,40 @@ +shouldHaveType('Knp\FriendlyExtension\Builder\OptionsRequestBuilder'); + } + + function it_is_a_builder() + { + $this->shouldHaveType('Knp\FriendlyExtension\Builder\RequestBuilderInterface'); + } + + function it_build_an_option_request(ClientInterface $client, RequestInterface $request) + { + $client->options( + '/resource?foo=bar', + ['some options'] + )->shouldBeCalled(1)->willReturn($request); + + $this->setClient($client); + + $this->build( + '/resource', + ['foo' => 'bar'], + null, + null, + null, + ['some options'] + )->shouldReturn($request); + } +} diff --git a/spec/Knp/FriendlyExtension/Builder/PatchRequestBuilderSpec.php b/spec/Knp/FriendlyExtension/Builder/PatchRequestBuilderSpec.php new file mode 100644 index 00000000..80275c35 --- /dev/null +++ b/spec/Knp/FriendlyExtension/Builder/PatchRequestBuilderSpec.php @@ -0,0 +1,63 @@ +shouldHaveType('Knp\FriendlyExtension\Builder\PatchRequestBuilder'); + } + + function it_is_a_request_builder() + { + $this->shouldHaveType('Knp\FriendlyExtension\Builder\RequestBuilderInterface'); + } + + function it_build_a_patch_request(ClientInterface $client, RequestInterface $request) + { + $client->patch( + '/resource?foo=bar', + ['some headers'], + 'body datas', + ['some options'] + )->shouldBeCalled(1)->willReturn($request); + + $this->setClient($client); + + $this->build( + '/resource', + ['foo' => 'bar'], + ['some headers'], + null, + 'body datas', + ['some options'] + )->shouldReturn($request); + } + + function it_format_the_request_to_a_valid_form_urlencode(ClientInterface $client, RequestInterface $request) + { + $client->patch( + '/resource', + ['Content-Type' => 'application/x-www-form-urlencoded'], + 'foo=bar&baz=plop', + ['some options'] + )->shouldBeCalled(1)->willReturn($request); + + $this->setClient($client); + + $this->build( + '/resource', + null, + null, + null, + ['foo' => 'bar', 'baz' => 'plop'], + ['some options'] + )->shouldReturn($request); + } +} diff --git a/spec/Knp/FriendlyExtension/Builder/PostRequestBuilderSpec.php b/spec/Knp/FriendlyExtension/Builder/PostRequestBuilderSpec.php new file mode 100644 index 00000000..c53da5cf --- /dev/null +++ b/spec/Knp/FriendlyExtension/Builder/PostRequestBuilderSpec.php @@ -0,0 +1,42 @@ +shouldHaveType('Knp\FriendlyExtension\Builder\PostRequestBuilder'); + } + + function it_is_request_builder() + { + $this->shouldHaveType('Knp\FriendlyExtension\Builder\RequestBuilderInterface'); + } + + function it_build_a_post_request(ClientInterface $client, RequestInterface $request) + { + $client->post( + '/resource?foo=bar', + ['some headers'], + ['data' => 'plop'], + ['some options'] + )->shouldBeCalled(1)->willReturn($request); + + $this->setClient($client); + + $this->build( + '/resource', + ['foo' => 'bar'], + ['some headers'], + ['data' => 'plop'], + null, + ['some options'] + )->shouldReturn($request); + } +} diff --git a/spec/Knp/FriendlyExtension/Builder/PutRequestBuilderSpec.php b/spec/Knp/FriendlyExtension/Builder/PutRequestBuilderSpec.php new file mode 100644 index 00000000..0a06987f --- /dev/null +++ b/spec/Knp/FriendlyExtension/Builder/PutRequestBuilderSpec.php @@ -0,0 +1,63 @@ +shouldHaveType('Knp\FriendlyExtension\Builder\PutRequestBuilder'); + } + + function it_is_a_request_builder() + { + $this->shouldHaveType('Knp\FriendlyExtension\Builder\RequestBuilderInterface'); + } + + function it_build_a_put_request(ClientInterface $client, RequestInterface $request) + { + $client->put( + '/resource?foo=bar', + ['some headers'], + 'body datas', + ['some options'] + )->shouldBeCalled(1)->willReturn($request); + + $this->setClient($client); + + $this->build( + '/resource', + ['foo' => 'bar'], + ['some headers'], + null, + 'body datas', + ['some options'] + )->shouldReturn($request); + } + + function it_format_the_request_to_a_valid_form_urlencode(ClientInterface $client, RequestInterface $request) + { + $client->put( + '/resource', + ['Content-Type' => 'application/x-www-form-urlencoded'], + 'foo=bar&baz=plop', + ['some options'] + )->shouldBeCalled(1)->willReturn($request); + + $this->setClient($client); + + $this->build( + '/resource', + null, + null, + null, + ['foo' => 'bar', 'baz' => 'plop'], + ['some options'] + )->shouldReturn($request); + } +} diff --git a/spec/Knp/FriendlyExtension/Builder/RequestBuilderSpec.php b/spec/Knp/FriendlyExtension/Builder/RequestBuilderSpec.php new file mode 100644 index 00000000..46cc5d34 --- /dev/null +++ b/spec/Knp/FriendlyExtension/Builder/RequestBuilderSpec.php @@ -0,0 +1,95 @@ +shouldHaveType('Knp\FriendlyExtension\Builder\RequestBuilder'); + } + + function it_is_a_request_builder() + { + $this->shouldHaveType('Knp\FriendlyExtension\Builder\RequestBuilderInterface'); + } + + function it_attach_a_request_builder_to_valid_method(RequestBuilderInterface $builder) + { + $this->addRequestBuilder($builder, 'GET'); + + $this->shouldThrow('InvalidArgumentException')->duringAddRequestBuilder($builder, 'INVALID'); + + $this->shouldThrow('RuntimeException')->duringAddRequestBuilder($builder, 'GET'); + } + + function it_contains_a_valid_http_method() + { + $this->setMethod('get'); + + $this->getMethod()->shouldReturn('GET'); + + $this->shouldThrow('InvalidArgumentException')->duringSetMethod('Invalid'); + } + + function it_build_sub_request_builders_and_clean_the_builder( + Client $client, + RequestBuilderInterface $builder, + Request $request, + SecurityExtensionInterface $extension + ) + { + $this->setMethod('GET'); + $this->setUri('/some/resource'); + $this->setQueries(['a' => 'b']); + $this->setHeaders(['foo' => 'bar']); + $this->setPostBody(['baz' => 'bar']); + $this->setBody('body'); + $this->setCookies(['plop' => 'foo']); + $this->setOptions(['some options']); + $this->setCredentials([ + 'username' => 'john', + 'password' => 'johnpass' + ]); + $this->addSecurityExtension($extension); + + $builder->getClient()->shouldBeCalled()->willReturn($client); + + $extension->secureClient($client, $this)->shouldBeCalled(); + $extension->secureRequest($request, $this)->shouldBeCalled(); + + $builder->build( + 'some/resource', + ['a' => 'b'], + ['foo' => 'bar'], + ['baz' => 'bar'], + 'body', + ['some options'] + )->shouldBeCalled(1)->willReturn($request); + + $request->addCookie('plop', 'foo')->shouldBeCalled(1); + + $this->addRequestBuilder($builder, 'GET'); + + $this->build(); + + $this->getMethod()->shouldReturn(null); + $this->getUri()->shouldReturn(null); + $this->getQueries()->shouldReturn(null); + $this->getHeaders()->shouldReturn(null); + $this->getPostBody()->shouldReturn(null); + $this->getBody()->shouldReturn(null); + $this->getCookies()->shouldReturn(null); + $this->getOptions()->shouldReturn([]); + $this->getSecurityExtensions()->shouldReturn([]); + $this->getCredentials()->shouldReturn([]); + } +} diff --git a/spec/Knp/FriendlyExtension/Faker/UniqueCacheSpec.php b/spec/Knp/FriendlyExtension/Faker/UniqueCacheSpec.php new file mode 100644 index 00000000..1a0a2ba4 --- /dev/null +++ b/spec/Knp/FriendlyExtension/Faker/UniqueCacheSpec.php @@ -0,0 +1,31 @@ +shouldHaveType('Knp\FriendlyExtension\Faker\UniqueCache'); + } + + function its_generate_should_generate_a_new_unique_value() + { + $this->generate('Class', 'property', function () { + return 'test'; + }); + + $this->exists('Class', 'property', 'test')->shouldReturn(true); + + $cache = null; + $this->generate('Class', 'property', function () use (&$cache) { + $cache = rand(); + return $cache; + }); + + $this->exists('Class', 'property', $cache)->shouldReturn(true); + } +} diff --git a/spec/Knp/FriendlyExtension/Http/Factory/OauthPluginFactorySpec.php b/spec/Knp/FriendlyExtension/Http/Factory/OauthPluginFactorySpec.php new file mode 100644 index 00000000..1da9a866 --- /dev/null +++ b/spec/Knp/FriendlyExtension/Http/Factory/OauthPluginFactorySpec.php @@ -0,0 +1,19 @@ +shouldHaveType('Knp\FriendlyExtension\Http\Factory\OauthPluginFactory'); + } + + function it_create_an_oauth_plugin() + { + $this->create(['some datas'])->shouldHaveType('Guzzle\Plugin\Oauth\OauthPlugin'); + } +} diff --git a/spec/Knp/FriendlyExtension/Http/HttpContentTypeGuesserSpec.php b/spec/Knp/FriendlyExtension/Http/HttpContentTypeGuesserSpec.php new file mode 100644 index 00000000..c0ba6622 --- /dev/null +++ b/spec/Knp/FriendlyExtension/Http/HttpContentTypeGuesserSpec.php @@ -0,0 +1,32 @@ +shouldHaveType('Knp\FriendlyExtension\Http\HttpContentTypeGuesser'); + } + + function it_guess_a_short_content_type() + { + $this->guess('json')->shouldReturn(['application/json']); + $this->guess('xml')->shouldReturn(['application/xml', 'text/xml']); + $this->guess('html')->shouldReturn(['application/xhtml+xml', 'text/html']); + } + + function it_test_is_a_short_type_exists() + { + $this->exists('plop')->shouldReturn(false); + $this->exists('wave')->shouldReturn(true); + } + + function it_throw_an_error_on_non_existent_short_type_guessing() + { + $this->shouldThrow('InvalidArgumentException')->duringGuess('plop'); + } +} diff --git a/spec/Knp/FriendlyExtension/Http/Security/HttpBasicExtensionSpec.php b/spec/Knp/FriendlyExtension/Http/Security/HttpBasicExtensionSpec.php new file mode 100644 index 00000000..57ea12dd --- /dev/null +++ b/spec/Knp/FriendlyExtension/Http/Security/HttpBasicExtensionSpec.php @@ -0,0 +1,51 @@ +shouldHaveType('Knp\FriendlyExtension\Http\Security\HttpBasicExtension'); + } + + function it_is_a_security_extension() + { + $this->shouldHaveType('Knp\FriendlyExtension\Http\Security\SecurityExtensionInterface'); + } + + function it_failed_if_we_dont_precised_valid_credentials(Request $request, RequestBuilder $builder) + { + $this->shouldThrow('RuntimeException')->duringSecureRequest($request, $builder); + + $builder->getCredentials()->shouldBeCalled()->willReturn([ + 'bad_one' => 'some values', + 'other_bad_one' => 'some other values' + ]); + + $this->shouldThrow('RuntimeException')->duringSecureRequest($request, $builder); + } + + function it_set_up_request_basic_authentication(Request $request, RequestBuilder $builder) + { + $request->setAuth('username', 'password')->shouldBeCalled(1); + + $builder->getCredentials()->shouldBeCalled()->willReturn([ + 'username' => 'username', + 'password' => 'password' + ]); + + $this->secureRequest($request, $builder); + } + + function it_does_nothing_when_we_called_secure_client(Client $client, RequestBuilder $builder) + { + $this->secureClient($client, $builder)->shouldReturn(null); + } +} diff --git a/spec/Knp/FriendlyExtension/Http/Security/OauthExtensionSpec.php b/spec/Knp/FriendlyExtension/Http/Security/OauthExtensionSpec.php new file mode 100644 index 00000000..21e5d925 --- /dev/null +++ b/spec/Knp/FriendlyExtension/Http/Security/OauthExtensionSpec.php @@ -0,0 +1,50 @@ +beConstructedWith($factory); + $factory->create(Argument::cetera())->willReturn($plugin); + } + + function it_is_initializable() + { + $this->shouldHaveType('Knp\FriendlyExtension\Http\Security\OauthExtension'); + } + + function it_is_a_security_extension() + { + $this->shouldHaveType('Knp\FriendlyExtension\Http\Security\SecurityExtensionInterface'); + } + + function it_does_not_secure_the_request(Request $request, RequestBuilder $builder) + { + $this->secureRequest($request, $builder)->shouldReturn(null); + } + + function it_set_up_a_client_oauth_plugin_subscriber(Client $client, RequestBuilder $builder, $factory, $plugin) + { + $builder->getCredentials()->willReturn([ + 'some builder credentials' + ]); + + $factory->create([ + 'some builder credentials' + ])->shouldBeCalled()->willReturn($plugin); + + $client->addSubscriber($plugin)->shouldBeCalled(); + + $this->secureClient($client, $builder); + } +} diff --git a/spec/Knp/FriendlyExtension/Page/PageSpec.php b/spec/Knp/FriendlyExtension/Page/PageSpec.php new file mode 100644 index 00000000..d4af48b4 --- /dev/null +++ b/spec/Knp/FriendlyExtension/Page/PageSpec.php @@ -0,0 +1,34 @@ +beConstructedWith($session); + } + + function it_is_initializable() + { + $this->shouldHaveType('Knp\FriendlyExtension\Page\Page'); + } + + function it_is_a_document_element() + { + $this->shouldHaveType('Behat\Mink\Element\DocumentElement'); + } + + function it_contains_the_page_path() + { + $this->path = 'foo/bar'; + + $this->getPath()->shouldReturn('foo/bar'); + } +} diff --git a/spec/Knp/FriendlyExtension/Page/Resolver/PageClassResolverSpec.php b/spec/Knp/FriendlyExtension/Page/Resolver/PageClassResolverSpec.php new file mode 100644 index 00000000..076a2475 --- /dev/null +++ b/spec/Knp/FriendlyExtension/Page/Resolver/PageClassResolverSpec.php @@ -0,0 +1,57 @@ +beConstructedWith('Page\Namespace'); + } + + function it_is_initializable() + { + $this->shouldHaveType('Knp\FriendlyExtension\Page\Resolver\PageClassResolver'); + } + + function it_test_if_a_class_exists() + { + $this->exists('Behat\Mink\Mink')->shouldReturn(true); + $this->exists('Invalid\Class')->shouldReturn(false); + } + + /** + * @param Behat\Mink\Session $session + */ + function it_throw_an_exception_when_create_a_non_existent_page($session) + { + $this->shouldThrow('InvalidArgumentException')->duringCreate($session, 'Invalid\Class'); + } + + /** + * @param Behat\Mink\Session $session + */ + function it_throw_an_exception_when_create_an_invalid_page($session) + { + $this->shouldThrow('InvalidArgumentException')->duringCreate($session, 'Knp\FriendlyExtension\Page\Resolver\PageClassResolver'); + } + + /** + * @param Behat\Mink\Session $session + */ + function it_create_a_page_object($session) + { + $this + ->create($session, 'Knp\FriendlyExtension\Page\Page') + ->shouldHaveType('Knp\FriendlyExtension\Page\Page') + ; + } + + function it_resolve_a_page_class_name() + { + $this->resolveName('some name')->shouldReturn('Page\Namespace\SomeNamePage'); + } +} diff --git a/spec/Knp/FriendlyExtension/Reader/SmartReaderSpec.php b/spec/Knp/FriendlyExtension/Reader/SmartReaderSpec.php new file mode 100644 index 00000000..4f861a8d --- /dev/null +++ b/spec/Knp/FriendlyExtension/Reader/SmartReaderSpec.php @@ -0,0 +1,24 @@ +beConstructedWith($gherkin, $registry, $locator, $definitionFinder, $callCenter, 'smartStep'); + } + + function it_is_initializable() + { + $this->shouldHaveType('Knp\FriendlyExtension\Reader\SmartReader'); + } +} diff --git a/spec/Knp/FriendlyExtension/Table/NodeSpec.php b/spec/Knp/FriendlyExtension/Table/NodeSpec.php new file mode 100644 index 00000000..605e38ce --- /dev/null +++ b/spec/Knp/FriendlyExtension/Table/NodeSpec.php @@ -0,0 +1,62 @@ +setContent('this'); + $this->setRight($right); + $this->setBottom($bottom); + + $other->getContent()->willReturn('this'); + $other->getRight()->willReturn($otherRight); + $other->getBottom()->willReturn($otherBottom); + + $right->equals($otherRight)->willReturn(true); + $bottom->equals($otherBottom)->willReturn(true); + + $other->equals(Argument::any())->shouldNotBeCalled(); + $otherRight->equals(Argument::any())->shouldNotBeCalled(); + $otherBottom->equals(Argument::any())->shouldNotBeCalled(); + } + + function it_is_initializable() + { + $this->shouldHaveType('Knp\FriendlyExtension\Table\Node'); + } + + function it_is_equals(Node $other) + { + $this->equals($other)->shouldReturn(true); + } + + function it_is_not_equals_if_content_is_different(Node $other) + { + $other->getContent()->willReturn('other'); + $this->equals($other)->shouldReturn(false); + } + + function it_is_not_equals_if_branch_are_diferent(Node $other, Node $right, Node $otherRight) + { + $right->equals($otherRight)->willReturn(false); + $this->equals($other)->shouldReturn(false); + } + + function it_is_not_equals_if_branch_are_inexistant(Node $other) + { + $other->getRight()->willReturn(null); + $this->equals($other)->shouldReturn(false); + } + + function it_is_equals_if_branch_are_inexistant_but_the_other_is_partial(Node $other) + { + $other->getRight()->willReturn(null); + $this->equals($other, true)->shouldReturn(true); + } +} diff --git a/spec/Knp/FriendlyExtension/Utils/TextFormaterSpec.php b/spec/Knp/FriendlyExtension/Utils/TextFormaterSpec.php new file mode 100644 index 00000000..e5d0dd75 --- /dev/null +++ b/spec/Knp/FriendlyExtension/Utils/TextFormaterSpec.php @@ -0,0 +1,43 @@ +shouldHaveType('Knp\FriendlyExtension\Utils\TextFormater'); + } + + function it_should_camel_case_string() + { + $this->toCamelCase('the first string')->shouldReturn('theFirstString'); + $this->toCamelCase('string')->shouldReturn('string'); + } + + function it_should_underscore_string() + { + $this->toUnderscoreCase('the first string')->shouldReturn('the_first_string'); + $this->toUnderscoreCase('string')->shouldReturn('string'); + } + + function it_should_build_array() + { + $this->tableToString([ 'test', 'tata', 'toto' ])->shouldReturn('| test | tata | toto |'); + } + + function it_should_build_table() + { + $table = [ + [ 'test', 'tata', 'toto' ], + [ '0', '123456789', 'azertyuiop' ], + [ '987654321', '0', '12345' ], + ]; + + $return = "| test | tata | toto |\n| 0 | 123456789 | azertyuiop |\n| 987654321 | 0 | 12345 |\n"; + + $this->tableToString($table)->shouldReturn($return); + } +} diff --git a/src/Knp/FriendlyExtension/Table/Node.php b/src/Knp/FriendlyExtension/Table/Node.php new file mode 100644 index 00000000..9f3bf56d --- /dev/null +++ b/src/Knp/FriendlyExtension/Table/Node.php @@ -0,0 +1,133 @@ +content; + } + + public function setContent($content) + { + $this->content = $content; + + return $this; + } + + public function getTop() + { + return $this->top; + } + + public function setTop(Node $top = null) + { + $this->top = $top; + + if (null !== $top && $this !== $top->getBottom()) { + $top->setBottom($this); + } + + return $this; + } + + public function getBottom() + { + return $this->bottom; + } + + public function setBottom(Node $bottom = null) + { + $this->bottom = $bottom; + + if (null !== $bottom && $this !== $bottom->getTop()) { + $bottom->setTop($this); + } + + return $this; + } + + public function getLeft() + { + return $this->left; + } + + public function setLeft(Node $left = null) + { + $this->left = $left; + + if (null !== $left && $this !== $left->getRight()) { + $left->setRight($this); + } + + return $this; + } + + public function getRight() + { + return $this->right; + } + + public function setRight(Node $right = null) + { + $this->right = $right; + + if (null !== $right && $this !== $right->getLeft()) { + $right->setLeft($this); + } + + return $this; + } + + public function equals(Node $other, $otherIsPartial = false) + { + if ($this->content !== $other->getContent()) { + + return false; + } + + if (null !== $this->right && null !== $other->getRight() && false === $this->right->equals($other->getRight())) { + + return false; + } + + if (null !== $this->bottom && null !== $other->getBottom() && false === $this->bottom->equals($other->getBottom())) { + + return false; + } + + if (null === $this->right && null !== $other->getRight()) { + + return false; + } + + if (null === $this->bottom && null !== $other->getBottom()) { + + return false; + } + + if (true === $otherIsPartial) { + + return true; + } + + if (null !== $this->right && null === $other->getRight()) { + + return false; + } + + if (null !== $this->bottom && null === $other->getBottom()) { + + return false; + } + + return true; + } +} diff --git a/src/Knp/FriendlyExtension/Table/NodeCollection.php b/src/Knp/FriendlyExtension/Table/NodeCollection.php new file mode 100644 index 00000000..93fef6c3 --- /dev/null +++ b/src/Knp/FriendlyExtension/Table/NodeCollection.php @@ -0,0 +1,65 @@ +nodes, + function ($previous, $line) { + return array_merge($previous, $line); + }, + [] + ); + } + + public function addNode(Node $node, $line, $column) + { + $this->nodes[$line][$column] = $node; + + return $this; + } + + public function atPosition($line = null, $column = null) + { + switch (true) { + case null === $line && null === $column: + return $this->getNodes(); + case null !== $line && null === $column: + return array_key_exists($line, $this->nodes) + ? $this->nodes[$line] + : [] + ; + case null === $line && null !== $column: + $nodes = []; + foreach ($this->nodes as $i => $nodes) { + if (array_key_exists($column, $nodes)) { + $nodes[$i] = $nodes[$column]; + } + } + return $nodes; + case null !== $line && null !== $column: + $nodes = $this->atPosition($line); + return array_key_exists($column, $nodes) + ? $nodes[$column] + : null + ; + } + } + + public function search($content) + { + return array_filter( + $this->getNodes(), + function ($e) use ($content) { + return $e->getContent() === $content; + } + ); + } +} diff --git a/src/Knp/FriendlyExtension/Table/NodeFactory.php b/src/Knp/FriendlyExtension/Table/NodeFactory.php new file mode 100644 index 00000000..7bcda334 --- /dev/null +++ b/src/Knp/FriendlyExtension/Table/NodeFactory.php @@ -0,0 +1,19 @@ +factory = $factory; + } + + public function build(array $table) + { + $collection = $this->factory->createCollection(); + $table = array_values($table); + foreach ($table as $line => $columns) { + $columns = array_values($columns); + foreach ($columns as $column => $content) { + $node = $this->factory->createNode(); + $collection->addNode($node, $line, $column); + $node->setContent($content); + $node->setTop($collection->atPosition($line - 1, $column)); + $node->setBottom($collection->atPosition($line + 1, $column)); + $node->setLeft($collection->atPosition($line, $column - 1)); + $node->setLeft($collection->atPosition($line, $column + 1)); + } + } + + return $collection; + } +} From e41d882fc7b09abd9041f4dd2c75bce43b7b60c5 Mon Sep 17 00:00:00 2001 From: Pierre PLAZANET Date: Thu, 16 Oct 2014 16:34:41 +0100 Subject: [PATCH 22/33] Move mink context --- behat.yml.dist | 2 +- .../FriendlyContexts/Context/MinkContext.php | 179 ------------------ .../Context/Helper/MinkHelper.php | 41 ++++ .../FriendlyExtension/Context/MinkContext.php | 153 +++++++++++++++ 4 files changed, 195 insertions(+), 180 deletions(-) delete mode 100755 src/Knp/FriendlyContexts/Context/MinkContext.php create mode 100644 src/Knp/FriendlyExtension/Context/MinkContext.php diff --git a/behat.yml.dist b/behat.yml.dist index 72bae151..be8ca34a 100755 --- a/behat.yml.dist +++ b/behat.yml.dist @@ -6,9 +6,9 @@ default: default: path: %paths.base%/features contexts: - - Context\FeatureContext - Context\ServerContext - Knp\FriendlyExtension\Context\PageContext + - Knp\FriendlyExtension\Context\MinkContext extensions: Knp\FriendlyExtension: smart_tag: 'smart-step' diff --git a/src/Knp/FriendlyContexts/Context/MinkContext.php b/src/Knp/FriendlyContexts/Context/MinkContext.php deleted file mode 100755 index 740e4fc0..00000000 --- a/src/Knp/FriendlyContexts/Context/MinkContext.php +++ /dev/null @@ -1,179 +0,0 @@ -[^"]*)" (?P[^"]*)$/ - * @When /^(?:|I )(follow|press) the first "(?P[^"]*)" (?P[^"]*)$/ - * @When /^(?:|I )(follow|press) the (?P\d*)(st|nd|rd|th) "(?P[^"]*)" (?P[^"]*)$/ - **/ - public function clickElement($name, $element, $nbr = 1, $filterCallback = null) - { - $this->elementAction($name, $element, $nbr, function ($e) { $e->click(); }, $filterCallback); - } - - /** - * @When /^(?:|I )(?Pcheck|uncheck) the "(?P[^"]*)" checkbox$/ - * @When /^(?:|I )(?Pcheck|uncheck) the first "(?P[^"]*)" checkbox$/ - * @When /^(?:|I )(?Pcheck|uncheck) the (?P\d*)(st|nd|rd|th) "(?P[^"]*)" checkbox$/ - **/ - public function checkCheckbox($state, $name, $nbr = 1) - { - $this->elementAction( - $name, - 'field', - $nbr, - function ($e) use ($state) { if ('check' === $state) { $e->check(); } else { $e->uncheck(); } }, - function ($e) { return 'checkbox' === $e->getAttribute('type'); } - ); - } - - /** - * @When /^(?:|I )check the "(?P[^"]*)" radio$/ - * @When /^(?:|I )check the first "(?P[^"]*)" radio$/ - * @When /^(?:|I )check the (?P\d*)(st|nd|rd|th) "(?P[^"]*)" radio$/ - **/ - public function checkRadio($name, $nbr = 1) - { - $this->elementAction( - $name, - 'field', - $nbr, - function ($e) { $this->getSession()->getDriver()->click($e->getXPath()); }, - function ($e) { return 'radio' === $e->getAttribute('type'); } - ); - } - - - /** - * @Then /^(?:|I )should(?P| not) see (?P\d*) "(?P[^"]*)" (?Plink|button|radio|checkbox)$/ - **/ - public function nbrElement($should, $nbr, $name, $element) - { - $type = in_array($element, [ 'checkbox', 'radio' ]) ? 'field' : $element; - $filterCallback = null; - - if ('field' === $type) { - $filterCallback = function ($e) use ($element) { return $element === $e->getAttribute('type'); }; - } - - $elements = $this->searchElement($name, $type, $filterCallback); - - $message = sprintf('%s %s found', $nbr, $element); - - if (' not' === $should) { - $this->getAsserter()->assertEquals($nbr, count($elements), $message); - } else { - $this->getAsserter()->assertNotEquals($nbr, count($elements), $message); - } - } - - /** - * @Then /^(?:|I )should(?P| not) see a "(?P[^"]*)" (?Plink|button|radio|checkbox)$/ - **/ - public function seeElement($should, $name, $element) - { - $type = in_array($element, [ 'checkbox', 'radio' ]) ? 'field' : $element; - $filterCallback = null; - - if ('field' === $type) { - $filterCallback = function ($e) use ($element) { return $element === $e->getAttribute('type'); }; - } - - $elements = $this->searchElement($name, $type, $filterCallback); - - $message = sprintf('%s %s%s found', $name, $element, ' not' === $should ? '' : ' not'); - - if (' not' === $should) { - $this->getAsserter()->assert(0 == count($elements), $message); - } else { - $this->getAsserter()->assert(0 < count($elements), $message); - } - } - - /** - * @When /^(?:|I )(follow|press) the last "(?P[^"]*)" (?P[^"]*)$/ - **/ - public function clicklastElement($name, $element) - { - $this->clickElement($name, $element, -1); - } - - /** - * @When /^(?:|I )follow the link containing "(?P(?:[^"]|\\")*)"$/ - */ - public function clickLinkContaining($link) - { - parent::clickLink($link); - } - - public function clickLink($link) - { - $this->clickElement($link, 'link', 1, function ($e) use ($link) { return $link === $e->getText(); }); - } - - /** - * @When /^(?:|I )fill in the first "(?P(?:[^"]|\\")*)" field with "(?P(?:[^"]|\\")*)"$/ - * @When /^(?:|I )fill in the (?P\d*)(st|nd|rd|th) "(?P(?:[^"]|\\")*)" field with "(?P(?:[^"]|\\")*)"$/ - **/ - public function fillTheNthField($field, $value, $nbr = 1) - { - $field = $this->fixStepArgument($field); - $value = $this->fixStepArgument($value); - - $this->elementAction( - $field, - 'field', - $nbr, - function ($e) use ($value) { $e->setValue($value); }, - function ($e) { return 'text' === $e->getAttribute('type'); } - ); - } - - protected function searchElement($locator, $element, $filterCallback = null, TraversableElement $parent = null) - { - $parent = $parent ?: $this->getSession()->getPage(); - $locator = $this->fixStepArgument($locator); - - $elements = $parent->findAll('named', array( - $element, $this->getSession()->getSelectorsHandler()->xpathLiteral($locator) - )); - - if (null !== $filterCallback && is_callable($filterCallback)) { - $elements = array_values(array_filter($elements, $filterCallback)); - } - - return $elements; - } - - protected function elementAction($locator, $element, $nbr = 1, $actionCallback, $filterCallback = null) - { - $elements = $this->searchElement($locator, $element, $filterCallback); - - $nbr = is_numeric($nbr) ? intval($nbr) : $nbr; - $nbr = is_string($nbr) ? 1 : (-1 === $nbr ? count($elements) : $nbr); - - $this - ->getAsserter() - ->assert( - $nbr <= count($elements), - sprintf('Expected to find at least %s "%s" %s, %s found', $nbr, $locator, $element, count($elements)) - ) - ; - - $e = $elements[$nbr - 1]; - - $actionCallback($e); - } - - protected function getAsserter() - { - return new Asserter(new TextFormater); - } -} diff --git a/src/Knp/FriendlyExtension/Context/Helper/MinkHelper.php b/src/Knp/FriendlyExtension/Context/Helper/MinkHelper.php index 9600504e..e4d65465 100644 --- a/src/Knp/FriendlyExtension/Context/Helper/MinkHelper.php +++ b/src/Knp/FriendlyExtension/Context/Helper/MinkHelper.php @@ -44,4 +44,45 @@ public function locatePath($path) return 0 !== strpos($path, 'http') ? $startUrl . ltrim($path, '/') : $path; } + + public function fixStepArgument($argument) + { + return str_replace('\\"', '"', $argument); + } + + public function searchElement($locator, $element, $filterCallback = null, TraversableElement $parent = null) + { + $parent = $parent ?: $this->getSession()->getPage(); + $locator = $this->fixStepArgument($locator); + + $elements = $parent->findAll('named', array( + $element, $this->getSession()->getSelectorsHandler()->xpathLiteral($locator) + )); + + if (null !== $filterCallback && is_callable($filterCallback)) { + $elements = array_values(array_filter($elements, $filterCallback)); + } + + return $elements; + } + + public function elementAction($locator, $element, $nbr = 1, $actionCallback, $filterCallback = null) + { + $elements = $this->searchElement($locator, $element, $filterCallback); + + $nbr = is_numeric($nbr) ? intval($nbr) : $nbr; + $nbr = is_string($nbr) ? 1 : (-1 === $nbr ? count($elements) : $nbr); + + $this + ->getAsserter() + ->assert( + $nbr <= count($elements), + sprintf('Expected to find at least %s "%s" %s, %s found', $nbr, $locator, $element, count($elements)) + ) + ; + + $e = $elements[$nbr - 1]; + + $actionCallback($e); + } } diff --git a/src/Knp/FriendlyExtension/Context/MinkContext.php b/src/Knp/FriendlyExtension/Context/MinkContext.php new file mode 100644 index 00000000..f771b6a8 --- /dev/null +++ b/src/Knp/FriendlyExtension/Context/MinkContext.php @@ -0,0 +1,153 @@ +registry = $registry; + } + + /** + * @When I follow the ":name" ":element" + * @When I press the ":name" ":element" + * @When I follow the first ":name" ":element" + * @When I press the first ":name" ":element" + * @When /^I (follow|press) the (?P\d*)(st|nd|rd|th) "(?P[^"]*)" (?P[^"]*)$/ + **/ + public function clickElement($name, $element, $nbr = 1, $filterCallback = null) + { + $this->get('mink')->elementAction($name, $element, $nbr, function ($e) { $e->click(); }, $filterCallback); + } + + /** + * @When /^I (?Pcheck|uncheck) the "(?P[^"]*)" checkbox$/ + * @When /^I (?Pcheck|uncheck) the first "(?P[^"]*)" checkbox$/ + * @When /^I (?Pcheck|uncheck) the (?P\d*)(st|nd|rd|th) "(?P[^"]*)" checkbox$/ + **/ + public function checkCheckbox($state, $name, $nbr = 1) + { + $this->get('mink')->elementAction( + $name, + 'field', + $nbr, + function ($e) use ($state) { if ('check' === $state) { $e->check(); } else { $e->uncheck(); } }, + function ($e) { return 'checkbox' === $e->getAttribute('type'); } + ); + } + + /** + * @When /^I check the ":name" radio + * @When /^I check the first ":name" radio + * @When /^I check the (?P\d*)(st|nd|rd|th) "(?P[^"]*)" radio$/ + **/ + public function checkRadio($name, $nbr = 1) + { + $this->get('mink')->elementAction( + $name, + 'field', + $nbr, + function ($e) { $this->getSession()->getDriver()->click($e->getXPath()); }, + function ($e) { return 'radio' === $e->getAttribute('type'); } + ); + } + + + /** + * @Then /^I should(?P| not) see (?P\d*) "(?P[^"]*)" (?Plink|button|radio|checkbox)$/ + **/ + public function nbrElement($should, $nbr, $name, $element) + { + $type = in_array($element, [ 'checkbox', 'radio' ]) ? 'field' : $element; + $filterCallback = null; + + if ('field' === $type) { + $filterCallback = function ($e) use ($element) { return $element === $e->getAttribute('type'); }; + } + + $elements = $this->get('mink')->searchElement($name, $type, $filterCallback); + + $message = sprintf('%s %s found', $nbr, $element); + + if (' not' === $should) { + $this->get('asserter')->assertEquals($nbr, count($elements), $message); + } else { + $this->get('asserter')->assertNotEquals($nbr, count($elements), $message); + } + } + + /** + * @Then /^(?:|I )should(?P| not) see a "(?P[^"]*)" (?Plink|button|radio|checkbox)$/ + **/ + public function seeElement($should, $name, $element) + { + $type = in_array($element, [ 'checkbox', 'radio' ]) ? 'field' : $element; + $filterCallback = null; + + if ('field' === $type) { + $filterCallback = function ($e) use ($element) { return $element === $e->getAttribute('type'); }; + } + + $elements = $this->get('mink')->searchElement($name, $type, $filterCallback); + + $message = sprintf('%s %s%s found', $name, $element, ' not' === $should ? '' : ' not'); + + if (' not' === $should) { + $this->get('asserter')->assert(0 == count($elements), $message); + } else { + $this->get('asserter')->assert(0 < count($elements), $message); + } + } + + /** + * @When I follow the last ":name" ":element" + * @When I press the last ":name" ":element" + **/ + public function clicklastElement($name, $element) + { + $this->clickElement($name, $element, -1); + } + + /** + * @When I follow the link containing ":link" + */ + public function clickLinkContaining($link) + { + parent::clickLink($link); + } + + public function clickLink($link) + { + $this->clickElement($link, 'link', 1, function ($e) use ($link) { return $link === $e->getText(); }); + } + + /** + * @When I fill in the first ":field" field with ":value" + * @When /^(?:|I )fill in the (?P\d*)(st|nd|rd|th) "(?P(?:[^"]|\\")*)" field with "(?P(?:[^"]|\\")*)"$/ + **/ + public function fillTheNthField($field, $value, $nbr = 1) + { + $field = $this->get('mink')->fixStepArgument($field); + $value = $this->get('mink')->fixStepArgument($field); + + $this->get('mink')->elementAction( + $field, + 'field', + $nbr, + function ($e) use ($value) { $e->setValue($value); }, + function ($e) { return 'text' === $e->getAttribute('type'); } + ); + } + + protected function get($name) + { + return $this->registry->get($name); + } +} From 75b96ea915738e05473a74f4d4a195023a9b172c Mon Sep 17 00:00:00 2001 From: Pierre PLAZANET Date: Thu, 16 Oct 2014 23:21:55 +0100 Subject: [PATCH 23/33] Add tests for mink context --- behat.yml.dist | 1 + features/Context/FeatureContext.php | 11 +++- features/Page/FormPage.php | 13 ++++ features/form.feature | 15 +++++ features/html/form.php | 62 +++++++++++++++++++ features/html/jquery.js | 4 ++ .../Context/Helper/MinkHelper.php | 7 ++- .../FriendlyExtension/Context/MinkContext.php | 8 +++ 8 files changed, 118 insertions(+), 3 deletions(-) create mode 100644 features/Page/FormPage.php create mode 100644 features/form.feature create mode 100644 features/html/form.php create mode 100644 features/html/jquery.js diff --git a/behat.yml.dist b/behat.yml.dist index be8ca34a..af4e37d1 100755 --- a/behat.yml.dist +++ b/behat.yml.dist @@ -6,6 +6,7 @@ default: default: path: %paths.base%/features contexts: + - Context\FeatureContext - Context\ServerContext - Knp\FriendlyExtension\Context\PageContext - Knp\FriendlyExtension\Context\MinkContext diff --git a/features/Context/FeatureContext.php b/features/Context/FeatureContext.php index 86f0ca3f..e25a34a1 100644 --- a/features/Context/FeatureContext.php +++ b/features/Context/FeatureContext.php @@ -2,8 +2,15 @@ namespace Context; -use Behat\Behat\Context\Context; +use Knp\FriendlyExtension\Context\Context; -class FeatureContext implements Context +class FeatureContext extends Context { + /** + * @Given I wait + */ + public function wait($seconds = 2) + { + $this->get('mink')->getSession()->wait($seconds * 1000); + } } diff --git a/features/Page/FormPage.php b/features/Page/FormPage.php new file mode 100644 index 00000000..c8611523 --- /dev/null +++ b/features/Page/FormPage.php @@ -0,0 +1,13 @@ + "" field with "" + And I wait + Then I should see "" + + Examples: + | number | field | value | result | + | first | Text field | foo | Field Text field (text-0) value is foo | + | last | Text field | bar | Field Text field (text-4) value is bar | diff --git a/features/html/form.php b/features/html/form.php new file mode 100644 index 00000000..1af1bd5e --- /dev/null +++ b/features/html/form.php @@ -0,0 +1,62 @@ + sprintf('first-radio-%s', $i), + 'label' => sprintf('Radio field %s', $i), + 'type' => 'radio', + 'name' => 'first-radio', + ]; + $fields[] = $field; + } + + for ($i=0;$i<3;$i++) { + $field = [ + 'id' => sprintf('second-radio-%s', $i), + 'label' => sprintf('Radio field %s', $i), + 'type' => 'radio', + 'name' => 'second-radio', + ]; + $fields[] = $field; + } + + for ($i=0;$i<5;$i++) { + $field = [ + 'id' => sprintf('text-%s', $i), + 'label' => 'Text field', + 'type' => 'text', + 'name' => sprintf('text-%s', $i), + ]; + $fields[] = $field; + } +?> + + + + + +
+
+ + + +
+ +
+ + + diff --git a/features/html/jquery.js b/features/html/jquery.js new file mode 100644 index 00000000..ab28a247 --- /dev/null +++ b/features/html/jquery.js @@ -0,0 +1,4 @@ +/*! jQuery v1.11.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.1",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b=a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+-new Date,v=a.document,w=0,x=0,y=gb(),z=gb(),A=gb(),B=function(a,b){return a===b&&(l=!0),0},C="undefined",D=1<<31,E={}.hasOwnProperty,F=[],G=F.pop,H=F.push,I=F.push,J=F.slice,K=F.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},L="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",N="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=N.replace("w","w#"),P="\\["+M+"*("+N+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+O+"))|)"+M+"*\\]",Q=":("+N+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+P+")*)|.*)\\)|)",R=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),S=new RegExp("^"+M+"*,"+M+"*"),T=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),V=new RegExp(Q),W=new RegExp("^"+O+"$"),X={ID:new RegExp("^#("+N+")"),CLASS:new RegExp("^\\.("+N+")"),TAG:new RegExp("^("+N.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+Q),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+L+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{I.apply(F=J.call(v.childNodes),v.childNodes),F[v.childNodes.length].nodeType}catch(eb){I={apply:F.length?function(a,b){H.apply(a,J.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],!a||"string"!=typeof a)return d;if(1!==(k=b.nodeType)&&9!==k)return[];if(p&&!e){if(f=_.exec(a))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return I.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return I.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=9===k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+qb(o[l]);w=ab.test(a)&&ob(b.parentNode)||b,x=o.join(",")}if(x)try{return I.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function gb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function hb(a){return a[u]=!0,a}function ib(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function jb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function kb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||D)-(~a.sourceIndex||D);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function lb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function nb(a){return hb(function(b){return b=+b,hb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function ob(a){return a&&typeof a.getElementsByTagName!==C&&a}c=fb.support={},f=fb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fb.setDocument=function(a){var b,e=a?a.ownerDocument||a:v,g=e.defaultView;return e!==n&&9===e.nodeType&&e.documentElement?(n=e,o=e.documentElement,p=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){m()},!1):g.attachEvent&&g.attachEvent("onunload",function(){m()})),c.attributes=ib(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ib(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(e.getElementsByClassName)&&ib(function(a){return a.innerHTML="
",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=ib(function(a){return o.appendChild(a).id=u,!e.getElementsByName||!e.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==C&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c=typeof a.getAttributeNode!==C&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==C?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==C&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(e.querySelectorAll))&&(ib(function(a){a.innerHTML="",a.querySelectorAll("[msallowclip^='']").length&&q.push("[*^$]="+M+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+M+"*(?:value|"+L+")"),a.querySelectorAll(":checked").length||q.push(":checked")}),ib(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+M+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ib(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",Q)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===v&&t(v,a)?-1:b===e||b.ownerDocument===v&&t(v,b)?1:k?K.call(k,a)-K.call(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],i=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:k?K.call(k,a)-K.call(k,b):0;if(f===g)return kb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?kb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},e):n},fb.matches=function(a,b){return fb(a,null,null,b)},fb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fb(b,n,null,[a]).length>0},fb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&E.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fb.selectors={cacheLength:50,createPseudo:hb,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+M+")"+a+"("+M+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==C&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?hb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=K.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:hb(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?hb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:hb(function(a){return function(b){return fb(a,b).length>0}}),contains:hb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:hb(function(a){return W.test(a||"")||fb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:nb(function(){return[0]}),last:nb(function(a,b){return[b-1]}),eq:nb(function(a,b,c){return[0>c?c+b:c]}),even:nb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:nb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:nb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:nb(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function rb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function sb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function tb(a,b,c){for(var d=0,e=b.length;e>d;d++)fb(a,b[d],c);return c}function ub(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function vb(a,b,c,d,e,f){return d&&!d[u]&&(d=vb(d)),e&&!e[u]&&(e=vb(e,f)),hb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||tb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ub(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ub(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?K.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ub(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):I.apply(g,r)})}function wb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=rb(function(a){return a===b},h,!0),l=rb(function(a){return K.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>i;i++)if(c=d.relative[a[i].type])m=[rb(sb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return vb(i>1&&sb(m),i>1&&qb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&wb(a.slice(i,e)),f>e&&wb(a=a.slice(e)),f>e&&qb(a))}m.push(c)}return sb(m)}function xb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=G.call(i));s=ub(s)}I.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&fb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?hb(f):f}return h=fb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xb(e,d)),f.selector=a}return f},i=fb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&ob(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qb(j),!a)return I.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&ob(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ib(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ib(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||jb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ib(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||jb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ib(function(a){return null==a.getAttribute("disabled")})||jb(L,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fb}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h; +if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML="
a",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function ab(){return!0}function bb(){return!1}function cb(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),hb=/^\s+/,ib=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,jb=/<([\w:]+)/,kb=/\s*$/g,rb={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:k.htmlSerialize?[0,"",""]:[1,"X
","
"]},sb=db(y),tb=sb.appendChild(y.createElement("div"));rb.optgroup=rb.option,rb.tbody=rb.tfoot=rb.colgroup=rb.caption=rb.thead,rb.th=rb.td;function ub(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ub(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function vb(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wb(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xb(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function yb(a){var b=pb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function zb(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Ab(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Bb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xb(b).text=a.text,yb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!gb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(tb.innerHTML=a.outerHTML,tb.removeChild(f=tb.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ub(f),h=ub(a),g=0;null!=(e=h[g]);++g)d[g]&&Bb(e,d[g]);if(b)if(c)for(h=h||ub(a),d=d||ub(f),g=0;null!=(e=h[g]);g++)Ab(e,d[g]);else Ab(a,f);return d=ub(f,"script"),d.length>0&&zb(d,!i&&ub(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=db(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(lb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(jb.exec(f)||["",""])[1].toLowerCase(),l=rb[i]||rb._default,h.innerHTML=l[1]+f.replace(ib,"<$1>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&hb.test(f)&&p.push(b.createTextNode(hb.exec(f)[0])),!k.tbody){f="table"!==i||kb.test(f)?""!==l[1]||kb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ub(p,"input"),vb),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ub(o.appendChild(f),"script"),g&&zb(h),c)){e=0;while(f=h[e++])ob.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ub(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&zb(ub(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ub(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fb,""):void 0;if(!("string"!=typeof a||mb.test(a)||!k.htmlSerialize&&gb.test(a)||!k.leadingWhitespace&&hb.test(a)||rb[(jb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ib,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ub(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ub(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&nb.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ub(i,"script"),xb),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ub(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,yb),j=0;f>j;j++)d=g[j],ob.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qb,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Cb,Db={};function Eb(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fb(a){var b=y,c=Db[a];return c||(c=Eb(a,b),"none"!==c&&c||(Cb=(Cb||m("