Test Failed
Push — master ( e3c39f...fe570d )
by Mihail
07:20
created

Apps/Controller/Admin/Main/Boot.php (6 issues)

1
<?php
2
3
namespace Apps\Controller\Admin\Main;
4
5
6
use Apps\Controller\Admin\Main;
7
use Apps\Model\Admin\Main\AbstractSearchItem;
8
use Apps\Model\Admin\Main\CollectionSearchResults;
9
use Ffcms\Core\App;
10
use Ffcms\Core\Helper\FileSystem\File;
11
use Ffcms\Core\Helper\Type\Any;
12
use Ffcms\Core\Helper\Type\Arr;
13
use Ffcms\Core\Helper\Type\Str;
14
use Illuminate\Support\Collection;
15
16
trait Boot
17
{
18
    /**
19
     * Hook boot for search features
20
     */
21
    public static function boot(): void
22
    {
23
        App::$Event->on(Main::SEARCH_EVENT_NAME, function ($model) {
24
            /** @var CollectionSearchResults $model */
25
            $records = \Apps\ActiveRecord\App::search($model->getQuery())
26
                ->take($model->getLimit())
27
                ->get();
28
29
            /** @var \Apps\ActiveRecord\App[]|Collection $records */
30
            $records->each(function($item) use ($model) {
31
                /** @var \Apps\ActiveRecord\App $item */
32
                $text = App::$Translate->get('Main', 'Type: %type%, system name: %sys%, version: %version%', [
33
                    'type' => $item->type,
34
                    'sys' => $item->sys_name,
35
                    'version' => $item->version
36
                ]);
37
38
                // initialize abstract response pattern
39
                $res = new AbstractSearchItem();
40
                $res->setTitle($item->getLocaled('name'));
0 ignored issues
show
It seems like $item->getLocaled('name') can also be of type array; however, parameter $value of Apps\Model\Front\Search\...earchResult::setTitle() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

40
                $res->setTitle(/** @scrutinizer ignore-type */ $item->getLocaled('name'));
Loading history...
41
                $res->setSnippet($text);
42
                $res->setDate($item->created_at);
43
                $res->setRelevance((int)$item->relevance);
0 ignored issues
show
Bug Best Practice introduced by zenn
The property relevance does not exist on Apps\ActiveRecord\App. Since you implemented __get, consider adding a @property annotation.
Loading history...
44
                $res->setUrl(Str::lowerCase($item->sys_name) . '/index');
45
                $res->setMarker('App');
46
47
                $model->add($res);
48
            });
49
50
            // search in translation files
51
            $usedLanguage = App::$Request->getLanguage();
52
            $onlyKeys = false;
53
            if ($usedLanguage === 'en') {
54
                $usedLanguage = 'ru'; // use "ru" locale with keys as default
55
                $onlyKeys = true;
56
            }
57
58
            // prepare search words for input query
59
            $searchWords = explode(' ', $model->getQuery());
60
            $usedWords = array_filter($searchWords, function($value) {
61
                return Str::length($value) > 2;
62
            });
63
64
            if (!$usedWords || count($usedWords) < 1) {
0 ignored issues
show
Bug Best Practice introduced by zenn
The expression $usedWords of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
65
                return;
66
            }
67
68
            $files = File::listFiles('/I18n/Admin/' . $usedLanguage, ['.php']);
69
            // each translation files
70
            foreach ($files as $file) {
71
                // prepare file name and route target
72
                $name = Str::lastIn($file, DIRECTORY_SEPARATOR, true);
73
                $route = Str::lowerCase(Str::firstIn($name, '.'));
74
                if (Arr::in($name, ['Main.php', 'Default.php'])) { // do not process main & defaults
75
                    continue;
76
                }
77
                $lines = File::inc($file, true, false);
78
                if (!Any::isArray($lines) && count($lines) < 1) {
0 ignored issues
show
It seems like $lines can also be of type boolean; however, parameter $var of count() does only seem to accept Countable|array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

78
                if (!Any::isArray($lines) && count(/** @scrutinizer ignore-type */ $lines) < 1) {
Loading history...
79
                    continue;
80
                }
81
                // list i18n file translation lines and search for entries
82
                $filter = array_filter($lines, function($target, $en) use ($usedWords, $onlyKeys) {
0 ignored issues
show
It seems like $lines can also be of type boolean; however, parameter $input of array_filter() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

82
                $filter = array_filter(/** @scrutinizer ignore-type */ $lines, function($target, $en) use ($usedWords, $onlyKeys) {
Loading history...
83
                    $enWords = explode(' ', $en);
84
                    foreach ($enWords as $enWord) {
85
                        if(Arr::in($enWord, $usedWords)) {
86
                            return true;
87
                        }
88
                    }
89
90
                    if (!$onlyKeys) {
91
                        $targetWords = explode(' ', $target);
92
                        foreach ($targetWords as $targetWord) {
93
                            if (Arr::in($targetWord, $usedWords)) {
94
                                return true;
95
                            }
96
                        }
97
                    }
98
99
                    return false;
100
                }, ARRAY_FILTER_USE_BOTH);
101
102
                if (!$filter || count($filter) < 1) {
0 ignored issues
show
Bug Best Practice introduced by zenn
The expression $filter of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
103
                    continue;
104
                }
105
106
                $relevance = 10 * (count($filter) / count($files));
107
                // initialize abstract response pattern
108
                $res = new AbstractSearchItem();
109
                $res->setTitle(ucfirst($route));
110
                $res->setSnippet(implode('; ', $filter));
111
                $res->setDate(time());
112
                $res->setRelevance($relevance);
113
                $res->setUrl($route . '/index');
114
                $res->setMarker('i18n');
115
116
                $model->add($res);
117
            }
118
        });
119
    }
120
}