Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 102 |
|
0.00% |
0 / 7 |
CRAP | |
0.00% |
0 / 1 |
TipLoader | |
0.00% |
0 / 102 |
|
0.00% |
0 / 7 |
702 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
loadTipNodes | |
0.00% |
0 / 15 |
|
0.00% |
0 / 1 |
2 | |||
buildExtraData | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
getTipTreeForTaskType | |
0.00% |
0 / 17 |
|
0.00% |
0 / 1 |
110 | |||
getTipNodesForStep | |
0.00% |
0 / 34 |
|
0.00% |
0 / 1 |
56 | |||
getMessageKeyWithFallback | |
0.00% |
0 / 22 |
|
0.00% |
0 / 1 |
30 | |||
buildMessageKey | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace GrowthExperiments\HelpPanel\Tips; |
4 | |
5 | use GrowthExperiments\NewcomerTasks\ConfigurationLoader\ConfigurationLoader; |
6 | use GrowthExperiments\NewcomerTasks\TaskType\TaskType; |
7 | use LogicException; |
8 | use MessageLocalizer; |
9 | |
10 | class TipLoader { |
11 | |
12 | /** |
13 | * @var ConfigurationLoader |
14 | */ |
15 | private $configurationLoader; |
16 | |
17 | private const DEFAULT_EDITOR = 'visualeditor'; |
18 | |
19 | private const DEFAULT_SKIN = 'vector'; |
20 | /** |
21 | * @var MessageLocalizer |
22 | */ |
23 | private $messageLocalizer; |
24 | |
25 | /** |
26 | * @param ConfigurationLoader $configurationLoader |
27 | * @param MessageLocalizer $messageLocalizer |
28 | */ |
29 | public function __construct( |
30 | ConfigurationLoader $configurationLoader, MessageLocalizer $messageLocalizer |
31 | ) { |
32 | $this->configurationLoader = $configurationLoader; |
33 | $this->messageLocalizer = $messageLocalizer; |
34 | } |
35 | |
36 | /** |
37 | * Get an array of TipNode objects, each of which contain the step name |
38 | * and a TipNode tree to render. |
39 | * |
40 | * @param string $skinName |
41 | * @param string $editor |
42 | * @param TaskType[] $taskTypes |
43 | * @param string $taskTypeId |
44 | * @return array |
45 | */ |
46 | public function loadTipNodes( |
47 | string $skinName, string $editor, array $taskTypes, string $taskTypeId ): array { |
48 | $tipTree = $this->getTipTreeForTaskType( |
49 | $taskTypeId, |
50 | $this->buildExtraData( $taskTypes ) |
51 | ); |
52 | return array_filter( array_map( function ( $stepName ) use ( |
53 | $skinName, $editor, $tipTree, $taskTypeId |
54 | ) { |
55 | return $this->getTipNodesForStep( |
56 | $stepName, |
57 | $skinName, |
58 | $editor, |
59 | $taskTypeId, |
60 | $tipTree |
61 | ); |
62 | }, $tipTree->getStepNames() ) ); |
63 | } |
64 | |
65 | /** |
66 | * @param array $taskTypes |
67 | * @return array |
68 | */ |
69 | private function buildExtraData( array $taskTypes ): array { |
70 | return array_map( static function ( TaskType $taskType ) { |
71 | return [ 'learnMoreLink' => $taskType->getLearnMoreLink() ]; |
72 | }, $taskTypes ); |
73 | } |
74 | |
75 | /** |
76 | * @param string $taskTypeId |
77 | * @param array $extraData |
78 | * @throws LogicException |
79 | * @return TipTree |
80 | */ |
81 | private function getTipTreeForTaskType( string $taskTypeId, array $extraData ): TipTree { |
82 | switch ( $taskTypeId ) { |
83 | case 'copyedit': |
84 | return new CopyeditTipTree( $extraData ); |
85 | case 'image-recommendation': |
86 | return new ImageRecommendationTipTree( $extraData ); |
87 | case 'section-image-recommendation': |
88 | return new SectionImageRecommendationTipTree( $extraData ); |
89 | case 'links': |
90 | return new LinkTipTree( $extraData ); |
91 | case 'link-recommendation': |
92 | return new LinkRecommendationTipTree( $extraData ); |
93 | case 'update': |
94 | return new UpdateTipTree( $extraData ); |
95 | case 'references': |
96 | return new ReferencesTipTree( $extraData ); |
97 | case 'expand': |
98 | return new ExpandTipTree( $extraData ); |
99 | default: |
100 | throw new LogicException( $taskTypeId . ' does not have tip steps defined.' ); |
101 | } |
102 | } |
103 | |
104 | /** |
105 | * Get an array of TipNodes for a single step. |
106 | * |
107 | * @param string $stepName |
108 | * @param string $skinName |
109 | * @param string $editor |
110 | * @param string $taskTypeId |
111 | * @param TipTree $tipSteps |
112 | * @return TipNode[] |
113 | */ |
114 | private function getTipNodesForStep( |
115 | string $stepName, string $skinName, string $editor, string $taskTypeId, TipTree $tipSteps |
116 | ): array { |
117 | $nodesPerTip = array_filter( array_map( function ( $tipTypeId ) use ( |
118 | $tipSteps, $stepName, $editor, $taskTypeId, $skinName |
119 | ) { |
120 | $messageKey = null; |
121 | $steps = $tipSteps->getTree(); |
122 | if ( !isset( $steps[$stepName][$tipTypeId] ) ) { |
123 | return null; |
124 | } |
125 | if ( $tipTypeId === "main-multiple" ) { |
126 | $nodes = []; |
127 | $i = 1; |
128 | while ( $messageKey !== "" && $i <= TipTree::TIP_TYPE_MAIN_MULTIPLE_MAX_NODES ) { |
129 | $messageKey = $this->getMessageKeyWithFallback( |
130 | $skinName, |
131 | $editor, |
132 | $taskTypeId, |
133 | $tipTypeId . "-" . $i, |
134 | $stepName |
135 | ); |
136 | if ( $messageKey ) { |
137 | $nodes[] = new TipNode( $tipTypeId, $messageKey, $steps[$stepName][$tipTypeId] ?? [] ); |
138 | } |
139 | $i++; |
140 | } |
141 | return $nodes; |
142 | } |
143 | $messageKey = $this->getMessageKeyWithFallback( |
144 | $skinName, |
145 | $editor, |
146 | $taskTypeId, |
147 | $tipTypeId, |
148 | $stepName |
149 | ); |
150 | if ( !$messageKey ) { |
151 | return null; |
152 | } |
153 | return [ new TipNode( $tipTypeId, $messageKey, $steps[$stepName][$tipTypeId] ?? [] ) ]; |
154 | }, $tipSteps->getTipTypes() ) ); |
155 | |
156 | return array_merge( ...array_values( $nodesPerTip ) ); |
157 | } |
158 | |
159 | /** |
160 | * Get a Message for a particular skin, editor, task type, tip type, and step. |
161 | * |
162 | * If the message is disabled or doesn't exist, check variants in the |
163 | * following order: |
164 | * - Default editor with requested skin |
165 | * - Default skin with requested editor |
166 | * - Default skin and default editor |
167 | * |
168 | * @param string $skinName |
169 | * @param string $editor |
170 | * @param string $taskTypeId |
171 | * @param string $tipTypeId |
172 | * @param string $step |
173 | * @return string |
174 | */ |
175 | private function getMessageKeyWithFallback( |
176 | string $skinName, |
177 | string $editor, |
178 | string $taskTypeId, |
179 | string $tipTypeId, |
180 | string $step |
181 | ): string { |
182 | $msg = $this->messageLocalizer->msg( $this->buildMessageKey( |
183 | $skinName, $editor, $taskTypeId, $tipTypeId, $step ) |
184 | ); |
185 | if ( $msg->isDisabled() ) { |
186 | $msg = $this->messageLocalizer->msg( |
187 | $this->buildMessageKey( $skinName, self::DEFAULT_EDITOR, $taskTypeId, $tipTypeId, $step ) |
188 | ); |
189 | } |
190 | if ( $msg->isDisabled() ) { |
191 | $msg = $this->messageLocalizer->msg( |
192 | $this->buildMessageKey( self::DEFAULT_SKIN, $editor, $taskTypeId, $tipTypeId, $step ) |
193 | ); |
194 | } |
195 | if ( $msg->isDisabled() ) { |
196 | $msg = $this->messageLocalizer->msg( |
197 | $this->buildMessageKey( |
198 | self::DEFAULT_SKIN, |
199 | self::DEFAULT_EDITOR, |
200 | $taskTypeId, |
201 | $tipTypeId, |
202 | $step |
203 | ) |
204 | ); |
205 | } |
206 | return $msg->isDisabled() ? '' : $msg->getKey(); |
207 | } |
208 | |
209 | /** |
210 | * @param string $skinName |
211 | * @param string $editor |
212 | * @param string $taskTypeId |
213 | * @param string $tipTypeId |
214 | * @param string $step |
215 | * @return string |
216 | */ |
217 | private function buildMessageKey( |
218 | string $skinName, string $editor, string $taskTypeId, string $tipTypeId, string $step |
219 | ): string { |
220 | return sprintf( |
221 | '%s-%s-%s-%s-%s-%s', |
222 | 'growthexperiments-help-panel-suggestededits-tips', |
223 | $skinName, |
224 | $editor, |
225 | $taskTypeId, |
226 | $tipTypeId, |
227 | $step |
228 | ); |
229 | } |
230 | |
231 | } |