1 | <?php |
||
2 | |||
3 | namespace SCI; |
||
4 | |||
5 | use Onoi\Cache\Cache; |
||
6 | use SMW\DIWikiPage; |
||
7 | use SMW\DIProperty; |
||
8 | use SMW\SemanticData; |
||
9 | |||
10 | /** |
||
11 | * @license GNU GPL v2+ |
||
12 | * @since 1.0 |
||
13 | * |
||
14 | * @author mwjames |
||
15 | */ |
||
16 | class CitationReferencePositionJournal { |
||
17 | |||
18 | /** |
||
19 | * @var Cache |
||
20 | */ |
||
21 | private $cache = null; |
||
22 | |||
23 | /** |
||
24 | * @var CacheKeyProvider |
||
25 | */ |
||
26 | private $cacheKeyProvider; |
||
27 | |||
28 | /** |
||
29 | * @var array |
||
30 | */ |
||
31 | private static $citationReferenceJournal = []; |
||
32 | |||
33 | /** |
||
34 | * @since 1.0 |
||
35 | * |
||
36 | * @param Cache $cache |
||
37 | * @param CacheKeyProvider $cacheKeyProvider |
||
38 | */ |
||
39 | 18 | public function __construct( Cache $cache, CacheKeyProvider $cacheKeyProvider ) { |
|
40 | 18 | $this->cache = $cache; |
|
41 | 18 | $this->cacheKeyProvider = $cacheKeyProvider; |
|
42 | 18 | } |
|
43 | |||
44 | /** |
||
45 | * @since 1.0 |
||
46 | * |
||
47 | * @param DIWikiPage $subject |
||
48 | * |
||
49 | * @return boolean |
||
50 | */ |
||
51 | 14 | public function hasCitationReference( SemanticData $semanticData ) { |
|
52 | 14 | return $semanticData->getPropertyValues( new DIProperty( PropertyRegistry::SCI_CITE_REFERENCE ) ) !== []; |
|
53 | } |
||
54 | |||
55 | /** |
||
56 | * @since 1.0 |
||
57 | * |
||
58 | * @param DIWikiPage $subject |
||
59 | * |
||
60 | * @return array|null |
||
61 | */ |
||
62 | 9 | public function getJournalBySubject( DIWikiPage $subject ) { |
|
63 | 9 | return $this->hasJournalForHash( $subject->getHash() ) ? self::$citationReferenceJournal[$subject->getHash()] : null; |
|
64 | } |
||
65 | |||
66 | /** |
||
67 | * @note Build a journal from unbound references (loose from the subject invoked |
||
68 | * citation references), the position isn't important because those will not |
||
69 | * be linked to any CiteRef anchors. |
||
70 | * |
||
71 | * @since 1.0 |
||
72 | * |
||
73 | * @param array $referenceList |
||
74 | * |
||
75 | * @return array|null |
||
76 | */ |
||
77 | 3 | public function buildJournalForUnboundReferenceList( array $referenceList ) { |
|
78 | |||
79 | 3 | if ( $referenceList === [] ) { |
|
80 | 1 | return null; |
|
81 | } |
||
82 | |||
83 | $journal = [ |
||
84 | 3 | 'total' => 0, |
|
85 | 'reference-list' => [], |
||
86 | 'reference-pos' => [] |
||
87 | ]; |
||
88 | |||
89 | 3 | $journal['total'] = count( $referenceList ); |
|
90 | |||
91 | 3 | foreach ( $referenceList as $reference ) { |
|
92 | 3 | $journal['reference-pos'][$reference] = []; |
|
93 | 3 | $journal['reference-list'][$reference] = $reference; |
|
94 | } |
||
95 | |||
96 | 3 | return $journal; |
|
97 | } |
||
98 | |||
99 | /** |
||
100 | * @since 1.0 |
||
101 | * |
||
102 | * @param DIWikiPage|null $subject |
||
103 | * @param string $reference |
||
104 | * |
||
105 | * @return string|null |
||
106 | */ |
||
107 | 7 | public function findLastReferencePositionEntryFor( DIWikiPage $subject = null, $reference ) { |
|
108 | |||
109 | 7 | if ( $subject === null ) { |
|
110 | return; |
||
111 | } |
||
112 | |||
113 | 7 | $referenceHash = md5( $reference ); |
|
114 | 7 | $hash = $subject->getHash(); |
|
115 | |||
116 | // Tracks the current parser run invoked by the InTextAnnotationParser |
||
117 | 7 | $uniqid = $subject->getContextReference(); |
|
118 | |||
119 | 7 | if ( $this->hasJournalForHash( $hash ) && |
|
120 | 7 | self::$citationReferenceJournal[$hash]['uniqid'] === $uniqid && |
|
121 | 7 | isset( self::$citationReferenceJournal[$hash]['reference-pos'][$referenceHash] ) ) { |
|
122 | 7 | return end( self::$citationReferenceJournal[$hash]['reference-pos'][$referenceHash] ); |
|
123 | } |
||
124 | |||
125 | return null; |
||
126 | } |
||
127 | |||
128 | /** |
||
129 | * @since 1.0 |
||
130 | * |
||
131 | * @param DIWikiPage|null $subject |
||
132 | * @param string $reference |
||
133 | */ |
||
134 | 9 | public function addJournalEntryFor( DIWikiPage $subject = null, $reference ) { |
|
135 | |||
136 | 9 | if ( $subject === null ) { |
|
137 | 1 | return; |
|
138 | } |
||
139 | |||
140 | 8 | $referenceHash = md5( $reference ); |
|
141 | 8 | $hash = $subject->getHash(); |
|
142 | |||
143 | // Tracks the current parser run invoked by the InTextAnnotationParser |
||
144 | 8 | $uniqid = $subject->getContextReference(); |
|
145 | |||
146 | 8 | if ( !$this->hasJournalForHash( $hash ) || self::$citationReferenceJournal[$hash]['uniqid'] !== $uniqid ) { |
|
147 | $journal = [ |
||
148 | 8 | 'uniqid' => $uniqid, |
|
149 | 8 | 'total' => 0, |
|
150 | 'reference-list' => [], |
||
151 | 'reference-pos' => [] |
||
152 | ]; |
||
153 | } else { |
||
154 | 6 | $journal = self::$citationReferenceJournal[$hash]; |
|
155 | } |
||
156 | |||
157 | // Caching the hash -> human readable key so that it can be reused |
||
158 | // without any additional DB/Store access by the ReferenceListOutputRenderer |
||
159 | 8 | $journal['reference-list'][$referenceHash] = $reference; |
|
160 | |||
161 | // New reference, increase the total of existing citations for this |
||
162 | // subject and set the position level to 'a' |
||
163 | 8 | if ( !isset( $journal['reference-pos'][$referenceHash] ) || $journal['reference-pos'][$referenceHash] === [] ) { |
|
164 | 8 | $journal['total']++; |
|
165 | 8 | $journal['reference-pos'][$referenceHash][] = $journal['total'] . '-' . 'a'; |
|
166 | } else { |
||
167 | // Found a citation with the same reference but for a different in-text |
||
168 | // location. |
||
169 | // |
||
170 | // Increment the minor to a -> b -> c in order to create a map of |
||
171 | // locations like 1-a, 1-b, 2-a etc. |
||
172 | // |
||
173 | // The exact position is specified by something like |
||
174 | // like 57d0dc056f9e5d5c6cfc77fc27091f60-1-a and to be used within |
||
175 | // html as link anchor |
||
176 | 6 | list( $major, $minor ) = explode( '-', end( $journal['reference-pos'][$referenceHash] ) ); |
|
177 | 6 | $journal['reference-pos'][$referenceHash][] = $major . '-' . ++$minor; |
|
178 | } |
||
179 | |||
180 | 8 | self::$citationReferenceJournal[$hash] = $journal; |
|
181 | |||
182 | // Safeguard against a repeated call to the hashlist for when the static |
||
183 | // cache is empty |
||
184 | 8 | $this->cache->save( |
|
185 | 8 | $this->cacheKeyProvider->getCacheKeyForCitationReference( $hash ), |
|
186 | 8 | self::$citationReferenceJournal |
|
187 | ); |
||
188 | 8 | } |
|
189 | |||
190 | 10 | private function hasJournalForHash( $hash ) { |
|
191 | |||
192 | 10 | if ( self::$citationReferenceJournal === [] ) { |
|
193 | 1 | self::$citationReferenceJournal = $this->cache->fetch( |
|
0 ignored issues
–
show
|
|||
194 | 1 | $this->cacheKeyProvider->getCacheKeyForCitationReference( $hash ) |
|
195 | ); |
||
196 | } |
||
197 | |||
198 | 10 | return isset( self::$citationReferenceJournal[$hash] ); |
|
199 | } |
||
200 | |||
201 | } |
||
202 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.