Completed
Push — master ( 7afdbb...e391f2 )
by André
24:54
created

CreateIndexCommand::initialize()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 10
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 15
rs 9.4285
1
<?php
2
3
/**
4
 * This file is part of the eZ Publish Kernel package.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 */
9
namespace eZ\Bundle\EzPublishLegacySearchEngineBundle\Command;
10
11
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
12
use Symfony\Component\Console\Helper\ProgressHelper;
13
use Symfony\Component\Console\Input\InputInterface;
14
use Symfony\Component\Console\Output\OutputInterface;
15
use Symfony\Component\Console\Input\InputArgument;
16
use eZ\Publish\SPI\Persistence\Content;
17
use eZ\Publish\SPI\Persistence\Content\ContentInfo;
18
use eZ\Publish\Core\Persistence\Database\DatabaseHandler;
19
use eZ\Publish\Core\Base\Exceptions\NotFoundException;
20
use eZ\Publish\Core\Search\Legacy\Content\Handler as SearchHandler;
21
use RuntimeException;
22
use PDO;
23
24
/**
25
 * Console command ezplatform:create_sql_search_index indexes content objects for legacy search
26
 * engine.
27
 */
28
class CreateIndexCommand extends ContainerAwareCommand
29
{
30
    /**
31
     * @var \eZ\Publish\Core\Search\Legacy\Content\Handler
32
     */
33
    private $searchHandler;
34
35
    /**
36
     * @var \eZ\Publish\SPI\Persistence\Handler
37
     */
38
    private $persistenceHandler;
39
40
    /**
41
     * @var \eZ\Publish\Core\Persistence\Database\DatabaseHandler
42
     */
43
    private $databaseHandler;
44
45
    /**
46
     * @var \Psr\Log\LoggerInterface
47
     */
48
    private $logger;
49
50
    /**
51
     * Initialize objects required by {@see execute()}.
52
     *
53
     * @param InputInterface $input
54
     * @param OutputInterface $output
55
     */
56
    public function initialize(InputInterface $input, OutputInterface $output)
57
    {
58
        parent::initialize($input, $output);
59
        $this->logger = $this->getContainer()->get('logger');
60
        $this->searchHandler = $this->getContainer()->get('ezpublish.spi.search');
61
        $this->persistenceHandler = $this->getContainer()->get('ezpublish.api.persistence_handler');
62
        $this->databaseHandler = $this->getContainer()->get('ezpublish.connection');
63
64
        if (!$this->searchHandler instanceof SearchHandler) {
65
            throw new RuntimeException(
66
                'Expected to find Legacy Search Engine but found something else.' .
67
                "Did you forget to configure the repository with 'legacy' search engine?"
68
            );
69
        }
70
    }
71
72
    /**
73
     * {@inheritdoc}
74
     */
75
    protected function configure()
76
    {
77
        $this
78
            ->setName('ezplatform:create_sql_search_index')
79
            ->setDescription('Indexes the configured database for the legacy search engine')
80
            ->addArgument('bulk_count', InputArgument::OPTIONAL, 'Number of Content objects indexed at once', 5)
81
            ->setHelp(
82
                <<<EOT
83
The command <info>%command.name%</info> indexes content objects for the legacy search engine.
84
EOT
85
            );
86
    }
87
88
    /**
89
     * {@inheritdoc}
90
     */
91
    protected function execute(InputInterface $input, OutputInterface $output)
92
    {
93
        $bulkCount = $input->getArgument('bulk_count');
94
        // Indexing Content
95
        $totalCount = $this->getContentObjectsTotalCount(
96
            $this->databaseHandler, ContentInfo::STATUS_PUBLISHED
97
        );
98
99
        $query = $this->databaseHandler->createSelectQuery();
100
        $query->select('id', 'current_version')
101
            ->from('ezcontentobject')
102
            ->where($query->expr->eq('status', ContentInfo::STATUS_PUBLISHED));
103
104
        $stmt = $query->prepare();
105
        $stmt->execute();
106
107
        $this->searchHandler->purgeIndex();
108
109
        $output->writeln('Indexing Content...');
110
111
        /* @var \Symfony\Component\Console\Helper\ProgressHelper $progress */
112
        $progress = $this->getHelperSet()->get('progress');
113
        $progress->start($output, $totalCount);
114
        $i = 0;
115
        do {
116
            $contentObjects = [];
117
            for ($k = 0; $k <= $bulkCount; ++$k) {
118
                if (!$row = $stmt->fetch(PDO::FETCH_ASSOC)) {
119
                    break;
120
                }
121
                try {
122
                    $contentObjects[] = $this->persistenceHandler->contentHandler()->load(
123
                        $row['id'],
124
                        $row['current_version']
125
                    );
126
                } catch (NotFoundException $e) {
127
                    $this->logWarning($output, $progress, "Could not load current version of Content with id ${row['id']}, so skipped for indexing. Full exception: " . $e->getMessage());
128
                }
129
            }
130
131
            $this->searchHandler->bulkIndex(
132
                $contentObjects,
133
                function (Content $content, NotFoundException $e) use ($output, $progress) {
134
                    $this->logWarning($output, $progress, 'Content with id ' . $content->versionInfo->id . ' has missing data, so skipped for indexing. Full exception: ' . $e->getMessage()
135
                    );
136
                }
137
            );
138
139
            $progress->advance($k);
140
        } while (($i += $bulkCount) < $totalCount);
141
142
        $progress->finish();
143
    }
144
145
    /**
146
     * Get content objects total count.
147
     *
148
     * @param \eZ\Publish\Core\Persistence\Database\DatabaseHandler $databaseHandler
149
     * @param int $contentObjectStatus ContentInfo constant
150
     *
151
     * @return int
152
     */
153
    private function getContentObjectsTotalCount(DatabaseHandler $databaseHandler, $contentObjectStatus)
154
    {
155
        $query = $databaseHandler->createSelectQuery();
156
        $query->select('count(id)')
157
            ->from('ezcontentobject')
158
            ->where($query->expr->eq('status', $contentObjectStatus));
159
        $stmt = $query->prepare();
160
        $stmt->execute();
161
        $totalCount = $stmt->fetchColumn();
162
163
        return $totalCount;
164
    }
165
166
    /**
167
     * Log warning while progress helper is running.
168
     *
169
     * @param \Symfony\Component\Console\Output\OutputInterface $output
170
     * @param \Symfony\Component\Console\Helper\ProgressHelper $progress
171
     * @param $message
172
     */
173
    private function logWarning(OutputInterface $output, ProgressHelper $progress, $message)
174
    {
175
        $progress->clear();
176
        // get rid of padding (side effect of displaying progress bar)
177
        $output->write("\r");
178
        $this->logger->warning($message);
179
        $progress->display();
180
    }
181
}
182