BulkIndexingHelper::bulkIndex()   C
last analyzed

Complexity

Conditions 12
Paths 80

Size

Total Lines 101
Code Lines 54

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 54
c 1
b 0
f 0
dl 0
loc 101
rs 6.9666
cc 12
nc 80
nop 3

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php declare(strict_types = 1);
2
3
/**
4
 * Created by PhpStorm.
5
 * User: gordon
6
 * Date: 25/3/2561
7
 * Time: 17:01 น.
8
 */
9
10
namespace Suilven\FreeTextSearch\Helper;
11
12
use League\CLImate\CLImate;
13
use SilverStripe\Core\Config\Config;
14
use SilverStripe\ORM\DB;
15
use SilverStripe\SiteConfig\SiteConfig;
16
use SilverStripe\Versioned\Versioned;
17
use Suilven\FreeTextSearch\Factory\BulkIndexerFactory;
18
use Suilven\FreeTextSearch\Indexes;
19
20
class BulkIndexingHelper
21
{
22
    /**
23
     * Bulk index all or just the 'dirty' items
24
     *
25
     * @param bool $dirty Set this to true to only index 'dirty' DataObjects, false to reindex all
26
     * @return int the number of documents indexed
27
     */
28
    public function bulkIndex(string $indexName, bool $dirty = false, ?CLImate $climate = null): int
29
    {
30
        $indexes = new Indexes();
31
        $index = $indexes->getIndex($indexName);
32
33
        /** @var string $clazz */
34
        $clazz = $index->getClass();
35
36
        /** @var \SilverStripe\ORM\DataObject $singleton */
37
        $singleton = \singleton($clazz);
38
39
        $startTime = \microtime(true);
40
41
        if (!(\is_null($climate))) {
42
            $climate->border('*');
43
            $climate->green()->bold('Indexing sitetree');
44
            $climate->border();
45
        }
46
47
        // @TODO this needs applied when appropriate, doesn't work with for example random dataobjects outside of
48
        // the sitetree paradigm
49
        //$filters = ['ShowInSearch' => true];
50
51
        $filters = [];
52
        if ($dirty) {
53
            $filters['IsDirtyFreeTextSearch'] = true;
54
        }
55
56
        $nDocuments = $singleton::get()->filter($filters)->count();
57
58
        if ($nDocuments > 0) {
59
            $config = SiteConfig::current_site_config();
60
61
            // * @phpstan-ignore-next-line
62
            $bulkSize = $config->BulkSize;
63
64
            $pages = 1+\round($nDocuments / $bulkSize);
65
            $progress = !\is_null($climate)
66
                ? $climate->progress()->total($nDocuments)
67
                : null;
68
69
            if (!\is_null($climate)) {
70
                $climate->green('Pages: ' . $pages);
71
                $climate->green()->info('Indexing ' . $nDocuments .' objects');
72
            }
73
74
            $factory = new BulkIndexerFactory();
75
            $bulkIndexer = $factory->getBulkIndexer();
76
            $bulkIndexer->setIndex($indexName);
77
78
            for ($i = 0; $i < $pages; $i++) {
79
                $dataObjects = $clazz::get()->limit($bulkSize, $i*$bulkSize)->filter($filters);
80
                foreach ($dataObjects as $do) {
81
                    // Note this adds data to the payload, doesn't actually indexing against the 3rd party search engine
82
                    $bulkIndexer->addDataObject($do);
83
                }
84
85
                // index objects up to configured bulk size
86
                $bulkIndexer->indexDataObjects();
87
                $current = $bulkSize * ($i+1);
88
                if ($current > $nDocuments) {
89
                    $current = $nDocuments;
90
                }
91
                if (\is_null($progress)) {
92
                    continue;
93
                }
94
95
                $progress->current($current);
96
            }
97
        }
98
99
100
        $endTime = \microtime(true);
101
        $delta = $endTime-$startTime;
102
103
        $rate = \round($nDocuments / $delta, 2);
104
105
        $elapsedStr = \round($delta, 2);
106
107
        if (!\is_null($climate)) {
108
            $climate->bold()->blue()->inline("{$nDocuments}");
109
            $climate->blue()->inline(' objects indexed in ');
110
            $climate->bold()->blue()->inline("{$elapsedStr}");
111
            $climate->blue()->inline('s, ');
112
            $climate->bold()->blue()->inline("{$rate}");
113
            $climate->blue(' per second ');
114
        }
115
116
        // assert this as a string, as it can initially be null
117
        /** @var string $clazz */
118
        $clazz = $index->getClass();
119
        $table = Config::inst()->get($clazz, 'table_name');
120
121
122
        if ($singleton->hasExtension(Versioned::class)) {
123
            DB::query("UPDATE \"{$table}_Live\" SET \"IsDirtyFreeTextSearch\" = 0");
124
        }
125
126
        DB::query("UPDATE \"{$table}\" SET \"IsDirtyFreeTextSearch\" = 0");
127
128
        return $nDocuments;
129
    }
130
}
131