diff --git a/Command/BlogImportCommand.php b/Command/BlogImportCommand.php index eec7ca8..9ca1233 100644 --- a/Command/BlogImportCommand.php +++ b/Command/BlogImportCommand.php @@ -22,15 +22,15 @@ public function configure() $this ->setName('victoire:blog-import') ->setDefinition([ - new InputOption('blog_name', '-b', InputOption::VALUE_REQUIRED, 'The name of the blog to populate'), - new InputOption('blog_template', '-bt', InputOption::VALUE_REQUIRED, 'The id of the blog template'), - new InputOption('blog_parent_id', '-bpi', InputOption::VALUE_REQUIRED, 'The id of the blog parent page'), + new InputOption('blog-name', '-b', InputOption::VALUE_REQUIRED, 'The name of the blog to populate'), + new InputOption('blog-template', '-bt', InputOption::VALUE_REQUIRED, 'The id of the blog template'), + new InputOption('blog-parent-id', '-bpi', InputOption::VALUE_REQUIRED, 'The id of the blog parent page'), new InputOption('dump', '-d', InputOption::VALUE_REQUIRED, 'Path to the dump who should bee imported'), - new InputOption('article_template_name', '-atn', InputOption::VALUE_OPTIONAL, 'article template name'), - new InputOption('article_template_layout', '-atl', InputOption::VALUE_OPTIONAL, 'article template layout designation'), - new InputOption('article_template_parent_id', '-atpid', InputOption::VALUE_OPTIONAL, 'article template parent id'), - new InputOption('article_template_id', '-ati', InputOption::VALUE_OPTIONAL, 'Id of an existing article template'), - new InputOption('article_template_first_slot', '-atfs', InputOption::VALUE_OPTIONAL, 'slot designation for root widget map in article template'), + new InputOption('article-template-name', '-atn', InputOption::VALUE_OPTIONAL, 'article template name'), + new InputOption('article-template-layout', '-atl', InputOption::VALUE_OPTIONAL, 'article template layout designation'), + new InputOption('article-template-parent-id', '-atpid', InputOption::VALUE_OPTIONAL, 'article template parent id'), + new InputOption('article-template-id', '-ati', InputOption::VALUE_OPTIONAL, 'Id of an existing article template'), + new InputOption('article-template-first-slot', '-atfs', InputOption::VALUE_OPTIONAL, 'slot designation for root widget map in article template'), ]) ->setDescription('Import blog form dump') ->setHelp(<<<'EOT' @@ -63,7 +63,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $questionHelper = $this->getQuestionHelper(); $commandParameters = []; - $requiredParameter = ['blog_name', 'dump', 'article_template_first_slot']; + $requiredParameter = ['blog-name', 'dump', 'article-template-first-slot']; foreach ($requiredParameter as $parameter) { if (null == $input->getOption($parameter)) { @@ -75,25 +75,25 @@ protected function execute(InputInterface $input, OutputInterface $output) $commandParameters['dump'] = $input->getOption('dump'); // Blog name - $commandParameters['blog_name'] = $input->getOption('blog_name'); + $commandParameters['blog_name'] = $input->getOption('blog-name'); // Blog template id - $commandParameters['blog_template'] = $input->getOption('blog_template'); + $commandParameters['blog_template'] = $input->getOption('blog-template'); // Blog parent id - $commandParameters['blog_parent_id'] = $input->getOption('blog_parent_id'); + $commandParameters['blog_parent_id'] = $input->getOption('blog-parent-id'); // Article Template - if (null !== $input->getOption('article_template_id')) { + if (null !== $input->getOption('article-template-id')) { $commandParameters['new_article_template'] = false; - $commandParameters['article_template_id'] = $input->getOption('article_template_id'); - $commandParameters['article_template_first_slot'] = $input->getOption('article_template_first_slot'); + $commandParameters['article_template_id'] = $input->getOption('article-template-id'); + $commandParameters['article_template_first_slot'] = $input->getOption('article-template-first-slot'); } else { $commandParameters['new_article_template'] = true; - $commandParameters['article_template_name'] = $input->getOption('article_template_name'); - $commandParameters['article_template_layout'] = $input->getOption('article_template_layout'); - $commandParameters['article_template_parent_id'] = $input->getOption('article_template_parent_id'); - $commandParameters['article_template_first_slot'] = $input->getOption('article_template_first_slot'); + $commandParameters['article_template_name'] = $input->getOption('article-template-name'); + $commandParameters['article_template_layout'] = $input->getOption('article-template-layout'); + $commandParameters['article_template_parent_id'] = $input->getOption('article-template-parent-id'); + $commandParameters['article_template_first_slot'] = $input->getOption('article-template-first-slot'); } if ($input->isInteractive()) { @@ -147,31 +147,31 @@ protected function interact(InputInterface $input, OutputInterface $output) /////////////////////// // blog name - $question = new Question($questionHelper->getQuestion('blog name', $input->getOption('blog_name'))); + $question = new Question($questionHelper->getQuestion('blog name', $input->getOption('blog-name'))); $question->setValidator(function ($answer) { return self::validateBlogName($answer); }); $blogName = (string) $questionHelper->ask($input, $output, $question); - $input->setOption('blog_name', $blogName); + $input->setOption('blog-name', $blogName); // blog template id - $question = new Question($questionHelper->getQuestion('blog template id', $input->getOption('blog_template'))); + $question = new Question($questionHelper->getQuestion('blog template id', $input->getOption('blog-template'))); $question->setValidator(function ($answer) { return self::validateTemplateId($answer); }); $blogTemplateId = (int) $questionHelper->ask($input, $output, $question); - $input->setOption('blog_template', $blogTemplateId); + $input->setOption('blog-template', $blogTemplateId); // blog parent id - $question = new Question($questionHelper->getQuestion('blog parent id', $input->getOption('blog_parent_id'))); + $question = new Question($questionHelper->getQuestion('blog parent id', $input->getOption('blog-parent-id'))); $question->setValidator(function ($answer) { return self::validateView($answer); }); $blogTemplateId = (int) $questionHelper->ask($input, $output, $question); - $input->setOption('blog_parent_id', $blogTemplateId); + $input->setOption('blog-parent-id', $blogTemplateId); // path to dump $question = new Question($questionHelper->getQuestion('path to dump', $input->getOption('dump'))); @@ -188,46 +188,46 @@ protected function interact(InputInterface $input, OutputInterface $output) if (!$questionHelper->ask($input, $output, $question)) { // ArticleTemplate name - $question = new Question($questionHelper->getQuestion('Article template name', $input->getOption('article_template_name'))); + $question = new Question($questionHelper->getQuestion('Article template name', $input->getOption('article-template-name'))); $articleTemplateName = (string) $questionHelper->ask($input, $output, $question); - $input->setOption('article_template_name', $articleTemplateName); + $input->setOption('article-template-name', $articleTemplateName); // ArticleTemplate layout - $question = new Question($questionHelper->getQuestion('Article template layout', $input->getOption('article_template_layout'))); + $question = new Question($questionHelper->getQuestion('Article template layout', $input->getOption('article-template-layout'))); $question->setValidator(function ($answer) { return self::validateLayout($answer); }); $articleTemplateLayout = (string) $questionHelper->ask($input, $output, $question); - $input->setOption('article_template_layout', $articleTemplateLayout); + $input->setOption('article-template-layout', $articleTemplateLayout); // ArticleTemplate parent_id - $question = new Question($questionHelper->getQuestion('Article template parent id', $input->getOption('article_template_parent_id'))); + $question = new Question($questionHelper->getQuestion('Article template parent id', $input->getOption('article-template-parent-id'))); $question->setValidator(function ($answer) { return self::validateTemplateId($answer); }); $articleTemplateParentId = (int) $questionHelper->ask($input, $output, $question); - $input->setOption('article_template_parent_id', $articleTemplateParentId); + $input->setOption('article-template-parent-id', $articleTemplateParentId); // ArticleTemplate slot - $question = new Question($questionHelper->getQuestion('Article Template first slot', $input->getOption('article_template_first_slot'))); + $question = new Question($questionHelper->getQuestion('Article Template first slot', $input->getOption('article-template-first-slot'))); $articleTemplateFirstSlot = (string) $questionHelper->ask($input, $output, $question); - $input->setOption('article_template_first_slot', $articleTemplateFirstSlot); + $input->setOption('article-template-first-slot', $articleTemplateFirstSlot); } else { // ArticleTemplate Id - $question = new Question($questionHelper->getQuestion('Article Template id', $input->getOption('article_template_id'))); + $question = new Question($questionHelper->getQuestion('Article Template id', $input->getOption('article-template-id'))); $question->setValidator(function ($answer) { return self::validateArticleTemplateId($answer); }); $articleTemplateId = (int) $questionHelper->ask($input, $output, $question); - $input->setOption('article_template_id', $articleTemplateId); + $input->setOption('article-template-id', $articleTemplateId); // ArticleTemplate slot - $question = new Question($questionHelper->getQuestion('Article Template first slot', $input->getOption('article_template_first_slot'))); + $question = new Question($questionHelper->getQuestion('Article Template first slot', $input->getOption('article-template-first-slot'))); $articleTemplateFirstSlot = (string) $questionHelper->ask($input, $output, $question); - $input->setOption('article_template_first_slot', $articleTemplateFirstSlot); + $input->setOption('article-template-first-slot', $articleTemplateFirstSlot); } } diff --git a/Pipeline/PipelineInterface.php b/Pipeline/PipelineInterface.php index cdc40c4..7032be9 100644 --- a/Pipeline/PipelineInterface.php +++ b/Pipeline/PipelineInterface.php @@ -12,4 +12,13 @@ interface PipelineInterface extends StageInterface * @return static */ public function pipe(callable $operation); + + /** + * Execute the processor process method + * + * @param $payload + * + * @return mixed + */ + public function process($payload); } diff --git a/README.md b/README.md index 8742afa..23ff892 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,40 @@ # VacuumBundle -Converts a wordpress dump into Victoire Blog +The VacuumBundle offer an Implementation for the import of external data +to populate a new or an existing Victoire Blog. + +## Installation + +Install it with composer: + + php composer.phar require victoire/vacuum-bundle + +Then add it to your AppKernel: + + class AppKernel extends Kernel + { + public function registerBundles() + { + $bundles = array( + ... + new Victoire\DevTools\VacuumBundle\VictoireVacuumBundle(), + ); + + return $bundles; + } + } + +Finally update your schema: + + php bin/console doctrine:schema:update --force + +#### Import available + +| Source | Format | +|-----------|--------| +| WordPress | XML | + +### Doc + +1. [Basic usage](doc/basic_usage.md) +1. [How it Works](doc/how_it_works.md) diff --git a/circle.yml b/circle.yml index 61150a9..dd4c5d0 100644 --- a/circle.yml +++ b/circle.yml @@ -16,7 +16,7 @@ checkout: dependencies: override: - - bash victoire-test-suite/dependencies.sh user/repo + - bash victoire-test-suite/dependencies.sh victoire/vacuumbundle cache_directories: - ~/.composer/cache @@ -24,7 +24,7 @@ test: override: - bash victoire-test-suite/circle.sh user/repo: parallel: true - - bash victoire-test-suite/test.sh user/repo + - bash victoire-test-suite/test.sh victoire/vacuumbundle general: artifacts: diff --git a/doc/basic_usage.md b/doc/basic_usage.md new file mode 100644 index 0000000..a827ad9 --- /dev/null +++ b/doc/basic_usage.md @@ -0,0 +1,48 @@ +# Usage + +The bundle provide a new command + + php bin/console victoire:blog-import + +When using it, the command will start in interactive mod. +You just have to follows th instruction. + +No interact mod is also available (param: --no-interact) +It require some parameter: + +## Using an existing Article Template + +| option | shortcut | definition | required | +|-----------------------------|----------|-----------------------------------------------------------------------------------------------------------|----------| +| blog-name | -b | define the new victoire blog name | true | +| blog-template | -bt | id of the base template for the new blog | true | +| blog-parent-id | -bpi | id of the blog parent pages | true | +| dump | -d | Path to the xml source file | true | +| article-template-id | -ati | If you want to use an existing ArticleTemplate Id | false | +| article-template-first-slot | -atfs | In every case you have to define the lot definition for your article content | true | + +## Without an Existing Article Template + +| option | shortcut | definition | required | +|-----------------------------|----------|-----------------------------------------------------------------------------------------------------------|----------| +| blog-name | -b | define the new victoire blog name | true | +| blog-template | -bt | id of the base template for the new blog | true | +| blog-parent-id | -bpi | id of the blog parent pages | true | +| dump | -d | Path to the xml source file | true | +| article-template-name | -atn | If you dont use an existing ArticleTemplate you have to provide a name for the new one | false | +| article-template-layout | -atl | If you dont have an existing ArticleTemplate, you have to provide the layout designation for the new one | false | +| article-template-parent-id | -atpid | If you dont have an existing ArticleTemplate, you have to provide the parent id for the new one. | false | +| article-template-first-slot | -atfs | In every case you have to define the lot definition for your article content | true | + + +When the command is execute if you have some blog author link to your article in your +dump, and they have no equivalent in your bdd (an equivalent would be an user with the same email +or username than your blog author). + +Then you will get an error associate with array containing every missing author from you bdd, you have to add it +in your bdd to execute a successful import. + +Add the end of the command if every stages has return a success then you have to +regenerate your view references manually + + php bin/console victoire:viewReference:generate \ No newline at end of file diff --git a/doc/how_it_works.md b/doc/how_it_works.md new file mode 100644 index 0000000..8879ed5 --- /dev/null +++ b/doc/how_it_works.md @@ -0,0 +1,78 @@ +# Principle + +The general id behind this bundle is to offer an flexible +base implementation to help in the transformation of data coming +from multiple source into Victoire Blog. + +It's based on an php implementation of the pattern design known has +pipeline. You can find this implementation [there](https://github.com/thephpleague/pipeline) + +A pipeline is a class implementing the following interface: + + interface PipelineInterface extends StageInterface + { + /** + * Create a new pipeline with an appended stage. + * + * @param callable $operation + * + * @return static + */ + public function pipe(callable $operation); + + /** + * Execute the processor process method + * + * @param $payload + * + * @return mixed + */ + public function process($payload); + } + +When a new Pipeline is instantiate it require a Processor. The processor is +the class in charge of executing the pipeline stages chain. Basically it's just +a loop who exec any callable method in the stages, passing an immutable object +called a Payload from stage to stage. + +A processor is build based on the following interface + + interface ProcessorInterface + { + /** + * @param array $stages + * @param $payload + * + * @return mixed + */ + public function process(array $stages, $payload); + } + +The Stages is where the business is done. It consist in a simple class using any +callable method you want, who receive a payload in param and return it when is job is done. + +Is create by implementing the following interface + + interface StageInterface + { + /** + * @param CommandPayloadInterface $payload + * + * @return $payload + */ + public function __invoke(CommandPayloadInterface $payload); + } + +So once I have some stage a pipeline an a processor we can build an execution chain + + $pipeline = new Pipeline(new Processor()); + + $payload = new Payload(); + + $pipeline + ->pipe(new Stage1) + ->pipe(new Stage2) + ->pipe(new Stage3) + ->process($payload) + + \ No newline at end of file diff --git a/phpunit.xml b/phpunit.xml index 1bd0b7c..f8b80c1 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -7,7 +7,7 @@ bootstrap="./vendor/autoload.php"> - +