eZ Community » Forums » eZ Publish 5 Platform » Export Content to CSV command line....
expandshrink

Export Content to CSV command line. Looking for a better solution.

Export Content to CSV command line. Looking for a better solution.

Wednesday 09 September 2015 10:47:41 am - 1 reply

Hy. 

I just dev a AbstractExportContentCommand class for exporting ez content to csv. 

I'm not sur my solution is a best practice. So I looking for a better solution.

Here my AbstractExportContentCommand class : 

 abstract class AbstractExportContentCommand extends ContainerAwareCommand
{
    // Command parameters
 
 
    protected $dry_run = false;
    protected $no_mail = false;
    protected $page_size = 200;
    protected $delimiter = ';';
    protected $encosure = '"';
 
 
    // Internal data
 
 
    protected $data = array();
    protected $matrice = array(
        'content_id' => '',
        'main_location_id' => '',
        // + fields of ContentType
    );
    protected $contentTypeFields = array();
    /** @var Logger     */
    protected $logger;
 
 
    /** @return Pagerfanta     */
    abstract protected function getPager();
 
 
    abstract protected function getContentTypeIdentifier();
    abstract protected function getPath();
    abstract protected function getFileNameBase();
    abstract protected function getProjectName();
 
 
    protected function configure()
    {
        $this
            ->addOption('dry-run', null, InputOption::VALUE_NONE, 'Mode dry-run')
            ->addOption('page-size', null, InputOption::VALUE_OPTIONAL, "Nombre d'éléments par page.", $this->page_size)
            ->addOption('delimiter', null, InputOption::VALUE_OPTIONAL, "Le paramètre optionnel delimiter spécifie le délimiteur CSV.", $this->delimiter)
            ->addOption('encosure', null, InputOption::VALUE_OPTIONAL, "Le paramètre enclosure spécifie le caractère d'encadrement CSV.", $this->encosure)
            ->addOption('no-mail', null, InputOption::VALUE_NONE, "Ne pas envoyer de mail.")
        ;
    }
 
 
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $this->dry_run = (bool)$input->getOption('dry-run');
        $this->no_mail = (bool)$input->getOption('no-mail');
        $this->page_size = $input->getOption('page-size');
        $this->delimiter = $input->getOption('delimiter');
        $this->encosure = $input->getOption('encosure');
 
 
        $this->logger = new Logger($this->getName());
        // Subsidiary question. Why 'ConsoleHandler' does not exist?
//        $this->logger->pushHandler(new ConsoleHandler($output, true, array(
//            OutputInterface::VERBOSITY_VERY_VERBOSE => Logger:big-smile.gif EmoticonEBUG,
//            OutputInterface::VERBOSITY_VERBOSE => Logger::INFO,
//            OutputInterface::VERBOSITY_NORMAL => Logger::NOTICE,
//            OutputInterface::VERBOSITY_QUIET => Logger::CRITICAL,
//        )));
        $this->logger->pushHandler(new StreamHandler('php://stdout'));
        $this->logger->notice("START ".$this->getName());
 
 
        $emailFrom = array($this->getContainer()->getParameter('email_from') => $this->getContainer()->getParameter('company_name'));
        $emailBCC = array($this->getContainer()->getParameter('email_admin') => $this->getContainer()->getParameter('company_name'));
        $emailTo = array($this->getContainer()->getParameter('email_admin') => $this->getContainer()->getParameter('company_name'));
 
 
        /** @var \Swift_Mailer $mailer */
        $mailer = $this->getContainer()->get('mailer') ;
        $message = $mailer->createMessage();
        /** @var \Swift_Message $message */
        $message->setFrom($emailFrom);
        $message->setBcc($emailBCC);
        $message->setTo($emailTo);
 
 
        try {
            $path = getcwd() . $this->getPath();
            if (!is_dir($path)) {
                $this->logger->notice("Dir '$path' does not existe. Create it.");
                if (!mkdir($path, 0644, true)) {
                    throw new \Exception("Impossible de créer le dossier '$path'");
                }
            }
            $filename = $this->getFileNameBase() . '-' . date('Y-m-d') . '.csv';
            $file = $path . '/' . $filename;
            $fp = fopen($file, 'w');
            if (!$fp) {
                throw new \Exception("fopen Error. File='$file'");
            }
            $this->logger->notice('File : '.$file);
 
 
            /** @var \eZ\Publish\API\Repository\Repository $repository */
            $repository = $this->getContainer()->get('ezpublish.api.repository');
            $contentType = $repository->getContentTypeService()->loadContentTypeByIdentifier($this->getContentTypeIdentifier());
            foreach ($contentType->getFieldDefinitions() as $fieldDefinition) {
                $this->contentTypeFields[$fieldDefinition->identifier] = $fieldDefinition->fieldTypeIdentifier;
                $this->matrice[$fieldDefinition->identifier] = '';
            }
 
 
            # Add header csv line
            $this->data[] = array_keys($this->matrice);
 
 
            $pager = $this->getPager();
 
 
            $page = 1;
            $i = 1;
            $pager->setMaxPerPage($this->page_size);
            $nb_pages = $pager->getNbPages();
            $nb_item = $pager->getNbResults();
            $this->logger->info($nb_item . " {$this->getContentTypeIdentifier()} à exporter");
 
 
            do {
                if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE) {
                    $this->logger->info("Page $page / $nb_pages");
                }
                $pager->setCurrentPage($page++);
                foreach ($pager as $item) {
                    if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) {
                        $this->logger->info('[' . $i++ . '/' . $nb_item . '] id:' . $item->id . ' "' . $item->contentInfo->name . '"');
                    }
                    $this->_processItem($item);
                }
            } while ($pager->hasNextPage());
 
 
            foreach ($this->data as $line) {
                if (fputcsv($fp, $line, $this->delimiter, $this->encosure) === false) {
                    throw new \Exception("fputcsv Error. File='$file'");
                }
            }
 
 
            # Send Success mail
            if (!$this->no_mail) {
                $body = "<p>$nb_item exported</p>";
                $body .= "see file '$file'";
                $message->setSubject("[{$this->getProjectName()}][CRON] " . $this->getName());
                $message->setBody($body);
                $message->attach(\Swift_Attachment::fromPath($file, 'txt/csv'));
                $mailer->send($message);
            }
        } catch (\Exception $e) {
            # Send ERROR mail
            if (!$this->no_mail) {
                $body = '<pre>' . $e->getTraceAsString() . '</pre>';
                $message->setSubject("[{$this->getProjectName()}][CRON][ERROR] " . $this->getName());
                $message->setBody($body);
                // TODO Attach log file
                $mailer->send($message);
            }
            throw $e;
        }
        $this->logger->notice("END ".$this->getName());
    }
 
 
    public function _processItem(Content $content)
    {
        $line = $this->matrice;
        $line['content_id'] = $content->id;
        $line['main_location_id'] = $content->contentInfo->mainLocationId;
        foreach ($this->contentTypeFields as $identifier => $fieldTypeIdentifier) {
            if (isset($line[$identifier])) {
                /** @var \eZ\Publish\Core\FieldType\Value $field_value */
                $field_value = $content->getFieldValue($identifier);
                if ($field_value) {
                    //$class = is_object($field_value) ? get_class($field_value) : gettype($field_value);
                    //$this->logger->debug($identifier . '     ' . $fieldTypeIdentifier . '    ' . $class. '    ' .$field_value->__toString());
                    $line[$identifier] = $field_value->__toString();
                }
            }
        }
        $this->data[] = $line;
    }
}

And here is an implementation of this abstract class.

class ExportAdherentsCommand extends AbstractExportContentCommand
{
    protected function configure()
    {
        parent::configure();
        $this
            ->setName('my_client:export:adherents')
            ->setDescription('')
        ;
    }
 
 
    protected function getPager()
    {
        $helper = $this->getContainer()->get('my_client.adherant_helper');
        return $helper->getAdherentList(/*some filters*/);
    }
 
 
    protected function getContentTypeIdentifier() { return 'adherant'; }
    protected function getPath() { return '/web/var/storage/export-adherants'; }
    protected function getFileNameBase() { return 'export-adherants'; }
    protected function getProjectName() { return 'my_client'; }
}

I think we can do better.

Surely using the service and dependencies injections.

What do you think ?

Modified on Wednesday 09 September 2015 11:42:48 am by Rémy PHP

Wednesday 09 September 2015 11:33:59 am

I love <span> .....  And disrespect of newline. It's so convenient!

 

eZ Publish Community Project 2014.07 (5.3)

(Symfony version 2.3.18)

PHP 5.3.3-7+squeeze19

Modified on Wednesday 09 September 2015 11:47:27 am by Rémy PHP

expandshrink

You must be logged in to post messages in this topic!

36 542 Users on board!

Forums menu

Proudly Developed with from