Passed
Pull Request — main (#5145)
by
unknown
07:31
created

UidParser   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 135
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 17
eloc 55
c 2
b 0
f 0
dl 0
loc 135
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A getMatchDefinition() 0 5 1
C parse() 0 75 12
A firstMatchingUidRecord() 0 11 3
1
<?php
2
3
/**
4
 * webtrees: online genealogy
5
 * Copyright (C) 2025 webtrees development team
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
 * GNU General Public License for more details.
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16
 */
17
18
declare(strict_types=1);
19
20
namespace Fisharebest\Webtrees\CommonMark;
21
22
use Fisharebest\Webtrees\Auth;
0 ignored issues
show
Bug introduced by
The type Fisharebest\Webtrees\Auth was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
23
use Fisharebest\Webtrees\Gedcom;
24
use Fisharebest\Webtrees\GedcomRecord;
0 ignored issues
show
Bug introduced by
The type Fisharebest\Webtrees\GedcomRecord was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
25
use Fisharebest\Webtrees\Registry;
26
use Fisharebest\Webtrees\Tree;
27
use Fisharebest\Webtrees\Services\GedcomImportService;
28
use Fisharebest\Webtrees\Services\TreeService;
0 ignored issues
show
Bug introduced by
The type Fisharebest\Webtrees\Services\TreeService was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
29
use Fisharebest\Webtrees\Services\SearchService;
0 ignored issues
show
Bug introduced by
The type Fisharebest\Webtrees\Services\SearchService was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
30
use League\CommonMark\Parser\Inline\InlineParserInterface;
31
use League\CommonMark\Parser\Inline\InlineParserMatch;
32
use League\CommonMark\Parser\InlineParserContext;
33
use Illuminate\Support\Collection;
34
35
/**
36
 * Convert UIDs within markdown text to links
37
 */
38
class UidParser implements InlineParserInterface
39
{
40
    private Tree $tree;
41
    private SearchService $search_service;
42
43
    /**
44
     * @param Tree $tree Match UIDs in this tree
45
     */
46
    public function __construct(Tree $tree)
47
    {
48
        $this->tree = $tree;
49
        $this->search_service = new SearchService(new TreeService(new GedcomImportService($this->tree)));
0 ignored issues
show
Unused Code introduced by
The call to Fisharebest\Webtrees\Ser...tService::__construct() has too many arguments starting with $this->tree. ( Ignorable by Annotation )

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

49
        $this->search_service = new SearchService(new TreeService(/** @scrutinizer ignore-call */ new GedcomImportService($this->tree)));

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
50
    }
51
52
    /**
53
     * We are only interested in text that begins with '@'.
54
     *
55
     * @return InlineParserMatch
56
     */
57
    public function getMatchDefinition(): InlineParserMatch
58
    {
59
        #This one permits escaping a # sign inside the text to be shown in the link and is ungreedy
60
        # so there can be more than one reference in one line
61
        return InlineParserMatch::regex('#(' . Gedcom::REGEX_UID . ')(?::(.+?[^\\\]))?#');
62
63
        // TESTED IN PHP 7.4
64
        //
65
        // #                  literal # (start ancor)
66
        // (                  start 1st capturing group
67
        // Gedcom::REGEX_UID  regex to match an UID
68
        // )                  end 1st capturing group
69
        // (?:                begin 1st non-capturing group
70
        //   :                a literal :
71
        //   (                start 2nd capturing group (without first :)
72
        //     .+?            any character one or more times NON GREEDY
73
        //     [^\\\]         any character that is not a \
74
        //   )                end 2nd capturing group
75
        // )                  end 1st non-capturing group
76
        // ?                  1st non-capturing group can be there or not
77
        // #                  literal # (end ancor)
78
    }
79
80
    private function firstMatchingUidRecord(String $pUid, Collection $pCollection): ?Object
81
    {
82
        foreach ($pCollection as $recTmp) {
83
            $regexTmp = '/\n1 _?UID ' . $pUid . '(:?\n|$)/';
84
            if (preg_match($regexTmp, $recTmp->gedcom())) {
85
                return $recTmp;
86
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
87
            }
88
        }
89
90
        return null;
91
    }
92
93
    /**
94
     * @param InlineParserContext $inlineContext
95
     *
96
     * @return bool
97
     */
98
    public function parse(InlineParserContext $inlineContext): bool
99
    {
100
        $cursor = $inlineContext->getCursor();
101
        $subm = $inlineContext->getSubMatches();
102
        $uid = [$subm[0]];
103
        $firstFoundRecord = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $firstFoundRecord is dead and can be removed.
Loading history...
104
        if (isset($subm[1])) {
105
            #Unescape character's #
106
107
            #NOTE: It should use only one \\, but it's using two because it get's escaped again in the regex processing.
108
            $linkText = preg_replace("/\\\\#/", "#", $subm[1]);
109
        } else {
110
            $linkText = '';
111
        }
112
113
        // Do the search
114
        $result = new Collection();
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
115
116
        // Log search requests for visitors
117
        if (Auth::id() === null) {
118
            Log::addSearchLog('General: ' . $query, $search_trees->all());
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $search_trees seems to be never defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable $query seems to be never defined.
Loading history...
Bug introduced by
The type Fisharebest\Webtrees\CommonMark\Log was not found. Did you mean Log? If so, make sure to prefix the type with \.
Loading history...
119
        }
120
121
        $result = $this->search_service->searchIndividuals([$this->tree], $uid);
122
        $firstFoundRecord = $this->firstMatchingUidRecord($uid[0], $result);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $firstFoundRecord is correct as $this->firstMatchingUidRecord($uid[0], $result) targeting Fisharebest\Webtrees\Com...irstMatchingUidRecord() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
123
124
        if ($firstFoundRecord === null) {
0 ignored issues
show
introduced by
The condition $firstFoundRecord === null is always true.
Loading history...
125
            $result = $this->search_service->searchFamilies([$this->tree], $uid);
126
            $firstFoundRecord = $this->firstMatchingUidRecord($uid[0], $result);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $firstFoundRecord is correct as $this->firstMatchingUidRecord($uid[0], $result) targeting Fisharebest\Webtrees\Com...irstMatchingUidRecord() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
127
128
            if ($firstFoundRecord === null) {
0 ignored issues
show
introduced by
The condition $firstFoundRecord === null is always true.
Loading history...
129
                $result = $this->search_service->searchFamilyNames([$this->tree], $uid);
130
                $firstFoundRecord = $this->firstMatchingUidRecord($uid[0], $result);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $firstFoundRecord is correct as $this->firstMatchingUidRecord($uid[0], $result) targeting Fisharebest\Webtrees\Com...irstMatchingUidRecord() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
131
132
                if ($firstFoundRecord === null) {
0 ignored issues
show
introduced by
The condition $firstFoundRecord === null is always true.
Loading history...
133
                    $result = $this->search_service->searchRepositories([$this->tree], $uid);
134
                    $firstFoundRecord = $this->firstMatchingUidRecord($uid[0], $result);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $firstFoundRecord is correct as $this->firstMatchingUidRecord($uid[0], $result) targeting Fisharebest\Webtrees\Com...irstMatchingUidRecord() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
135
136
                    if ($firstFoundRecord === null) {
0 ignored issues
show
introduced by
The condition $firstFoundRecord === null is always true.
Loading history...
137
                        $result = $this->search_service->searchSources([$this->tree], $uid);
138
                        $firstFoundRecord = $this->firstMatchingUidRecord($uid[0], $result);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $firstFoundRecord is correct as $this->firstMatchingUidRecord($uid[0], $result) targeting Fisharebest\Webtrees\Com...irstMatchingUidRecord() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
139
140
                        if ($firstFoundRecord === null) {
0 ignored issues
show
introduced by
The condition $firstFoundRecord === null is always true.
Loading history...
141
                            $result = $this->search_service->searchNotes([$this->tree], $uid);
142
                            $firstFoundRecord = $this->firstMatchingUidRecord($uid[0], $result);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $firstFoundRecord is correct as $this->firstMatchingUidRecord($uid[0], $result) targeting Fisharebest\Webtrees\Com...irstMatchingUidRecord() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
143
144
                            if ($firstFoundRecord === null) {
0 ignored issues
show
introduced by
The condition $firstFoundRecord === null is always true.
Loading history...
145
                                $result = $this->search_service->searchLocations([$this->tree], $uid);
146
                                $firstFoundRecord = $this->firstMatchingUidRecord($uid[0], $result);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $firstFoundRecord is correct as $this->firstMatchingUidRecord($uid[0], $result) targeting Fisharebest\Webtrees\Com...irstMatchingUidRecord() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
147
148
                                if ($firstFoundRecord === null) {
0 ignored issues
show
introduced by
The condition $firstFoundRecord === null is always true.
Loading history...
149
                                    $result = $this->search_service->searchMedia([$this->tree], $uid);
150
                                    $firstFoundRecord = $this->firstMatchingUidRecord($uid[0], $result);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $firstFoundRecord is correct as $this->firstMatchingUidRecord($uid[0], $result) targeting Fisharebest\Webtrees\Com...irstMatchingUidRecord() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
151
                                }
152
                            }
153
                        }
154
                    }
155
                }
156
            }
157
        }
158
159
        if ($firstFoundRecord === null) {
0 ignored issues
show
introduced by
The condition $firstFoundRecord === null is always true.
Loading history...
160
            return false;
161
        } else {
162
            $record = $firstFoundRecord;
163
164
            if ($record instanceof GedcomRecord) {
165
                $cursor->advanceBy($inlineContext->getFullMatchLength());
166
167
                $inlineContext->getContainer()->appendChild(new UidNode($record, $linkText));
168
169
                return true;
170
            }
171
172
            return false;
173
        }
174
    }
175
}
176