Completed
Push — non_purge_indexer ( f865fe )
by André
29:12 queued 11:33
created

IterativelyIndexer::createSearchIndex()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 36
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 23
nc 6
nop 3
dl 0
loc 36
rs 8.439
c 0
b 0
f 0
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\Publish\Core\Search\Common;
10
11
use Symfony\Component\Console\Output\OutputInterface;
12
use Symfony\Component\Console\Helper\ProgressBar;
13
use PDO;
14
15
/**
16
 * Base class for the Search Engine Indexer Service aimed to recreate Search Engine Index.
17
 * Each Search Engine has to extend it on its own.
18
 *
19
 * Extends indexer to allow for reindexing your install while it is in production by splitting indexing into tree tasks:
20
 * - Remove items in index no longer valid in database
21
 * - Making purge of index optional
22
 * - indexing by specifying id's, for purpose of supporting paralell indexing
23
 */
24
abstract class IterativelyIndexer extends Indexer
25
{
26
    /**
27
     * @deprecated Kept for compatibility with consumers of Indexer, performs purge first & recreate of index second.
28
     */
29
    final public function createSearchIndex(OutputInterface $output, $iterationCount, $commit)
30
    {
31
        $output->writeln('Purging Index..');
32
        $this->searchHandler->purgeIndex();
33
34
        $stmt = $this->getContentDbFieldsStmt(['count(id)']);
35
        $totalCount = intval($stmt->fetchColumn());
36
        $stmt = $this->getContentDbFieldsStmt(['id']);
37
38
        $output->writeln("Re-Creating Search Engine Index for {$totalCount} content items..");
39
        $progress = new ProgressBar($output);
40
        $progress->start($totalCount);
41
42
        $i = 0;
43
        do {
44
            $contentIds = [];
45
            for ($k = 0; $k <= $iterationCount; ++$k) {
46
                if (!$row = $stmt->fetch(PDO::FETCH_ASSOC)) {
47
                    break;
48
                }
49
50
                $contentIds[] = $row['id'];
51
            }
52
53
            $this->updateSearchIndex($contentIds);
54
            if ($commit && method_exists($this->searchHandler, 'commit')) {
55
                $this->searchHandler->commit();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface eZ\Publish\SPI\Search\Handler as the method commit() does only exist in the following implementations of said interface: eZ\Publish\Core\Search\Legacy\Content\Handler.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
56
            }
57
58
            $progress->advance($k);
59
        } while (($i += $iterationCount) < $totalCount);
60
61
        $progress->finish();
62
        $output->writeln('');
63
        //$output->writeln('Finished creating Search Engine Index');
64
    }
65
66
    /**
67
     * Updates search engine index based on Content id's.
68
     *
69
     * If content is:
70
     * - deleted (NotFoundException)
71
     * - not published (draft or trashed)
72
     * Then item is removed from index, if not it is added/updated.
73
     *
74
     * @param int[] $contentIds
75
     */
76
    abstract public function updateSearchIndex(array $contentIds);
77
78
79
80
}
81