Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
36.97% covered (danger)
36.97%
44 / 119
35.62% covered (danger)
35.62%
26 / 73
CRAP
0.00% covered (danger)
0.00%
0 / 1
Tool
36.97% covered (danger)
36.97%
44 / 119
35.62% covered (danger)
35.62%
26 / 73
2452.52
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
1 / 1
1
 __toString
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 getId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setName
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getType
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setType
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getEditor
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setEditor
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getArchival
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setArchival
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getEncrypted
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setEncrypted
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getAccessControl
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setAccessControl
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getUpdate
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setUpdate
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getBackup
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setBackup
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDeletion
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setDeletion
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getHasComment
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setHasComment
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getOther
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setOther
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getTracking
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setTracking
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getManager
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setManager
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getDescription
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setDescription
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getProdDate
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setProdDate
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getCountryType
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setCountryType
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getCountryName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setCountryName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getCountryGuarantees
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setCountryGuarantees
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getOtherInfo
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setOtherInfo
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getTreatments
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setTreatments
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 addTreatment
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 removeTreatment
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
20
 getContractors
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setContractors
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 addContractor
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 removeContractor
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
20
 getProofs
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setProofs
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 addProof
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 removeProof
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
20
 getMesurements
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setMesurements
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 addMesurement
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 removeMesurement
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
20
 getRequests
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setRequests
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 addRequest
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 removeRequest
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
20
 getViolations
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setViolations
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 addViolation
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 removeViolation
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
20
 generateLinkedDataColumn
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
20
 getUpdatedBy
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setUpdatedBy
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getClonedFrom
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setClonedFrom
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getTools
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setTools
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 addTool
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3/**
4 * This file is part of the MADIS - RGPD Management application.
5 *
6 * @copyright Copyright (c) 2018-2019 Soluris - Solutions Numériques Territoriales Innovantes
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Affero General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22declare(strict_types=1);
23
24namespace App\Domain\Registry\Model;
25
26use App\Application\Interfaces\CollectivityRelated;
27use App\Application\Traits\Model\CollectivityTrait;
28use App\Application\Traits\Model\CreatorTrait;
29use App\Application\Traits\Model\HistoryTrait;
30use App\Application\Traits\Model\ServiceTrait;
31use App\Domain\Registry\Model\Embeddable\ComplexChoice;
32use App\Domain\Reporting\Model\LoggableSubject;
33use Doctrine\Common\Collections\ArrayCollection;
34use Doctrine\Common\Collections\Collection;
35use Ramsey\Uuid\Uuid;
36use Ramsey\Uuid\UuidInterface;
37
38/**
39 * Action de protection / Plan d'action.
40 */
41class Tool implements LoggableSubject, CollectivityRelated
42{
43    use CreatorTrait;
44    use HistoryTrait;
45    use CollectivityTrait;
46    use ServiceTrait;
47
48    public const COUNTRY_FRANCE = 'registry.tool.label.country.france';
49    public const COUNTRY_EU     = 'registry.tool.label.country.eu';
50    public const COUNTRY_OTHER  = 'registry.tool.label.country.other';
51
52    public const COUNTRY_FRANCE_TEXT = 'France';
53    public const COUNTRY_EU_TEXT     = 'Pays de l’Union Européenne ou pays adéquats';
54    public const COUNTRY_OTHER_TEXT  = 'Autre pays d’hébergement de la donnée';
55
56    public const COUNTRY_TYPES = [
57        self::COUNTRY_FRANCE_TEXT => self::COUNTRY_FRANCE,
58        self::COUNTRY_EU_TEXT     => self::COUNTRY_EU,
59        self::COUNTRY_OTHER_TEXT  => self::COUNTRY_OTHER,
60    ];
61
62    /**
63     * @var UuidInterface
64     */
65    private $id;
66
67    /**
68     * FR: Nom.
69     *
70     * @var string|null
71     */
72    private $name;
73
74    /**
75     * FR: Type.
76     *
77     * @var string|null
78     */
79    private $type;
80
81    /**
82     * FR: Editeur.
83     *
84     * @var string|null
85     */
86    private $editor;
87
88    /**
89     * FR: Personne en charge.
90     *
91     * @var string|null
92     */
93    private $manager;
94
95    /**
96     * FR: Description.
97     *
98     * @var string|null
99     */
100    private $description;
101
102    /**
103     * FR: Date de mise en production.
104     *
105     * @var \DateTime|null
106     */
107    private $prod_date;
108
109    /**
110     * FR: Pays d'hébergement ou de stockage.
111     *
112     * @var string|null
113     */
114    private $country_type;
115
116    /**
117     * FR: Pays d'hébergement ou de stockage.
118     *
119     * @var string|null
120     */
121    private $country_name;
122
123    /**
124     * FR: Garanties pour le transfert.
125     *
126     * @var string|null
127     */
128    private $country_guarantees;
129
130    /**
131     * FR: Autres informations.
132     *
133     * @var string|null
134     */
135    private $other_info;
136
137    /**
138     * FR: Archivage.
139     *
140     * @var ComplexChoice
141     */
142    private $archival;
143
144    /**
145     * FR: Traçabilité.
146     *
147     * @var ComplexChoice
148     */
149    private $tracking;
150
151    /**
152     * FR: Chiffrement.
153     *
154     * @var ComplexChoice
155     */
156    private $encrypted;
157
158    /**
159     * FR: Controle d'accès.
160     *
161     * @var ComplexChoice
162     */
163    private $access_control;
164
165    /**
166     * FR: Mise Ã  jour.
167     *
168     * @var ComplexChoice
169     */
170    private $update;
171
172    /**
173     * @var string|null
174     */
175    private $updatedBy;
176
177    /**
178     * FR: Sauvegarde.
179     *
180     * @var ComplexChoice
181     */
182    private $backup;
183
184    /**
185     * FR: Suppression.
186     *
187     * @var ComplexChoice
188     */
189    private $deletion;
190
191    /**
192     * FR: Zone de commentaire libre.
193     *
194     * @var ComplexChoice
195     */
196    private $has_comment;
197
198    /**
199     * FR: Autres.
200     *
201     * @var ComplexChoice
202     */
203    private $other;
204
205    /**
206     * FR: Autres.
207     *
208     * @var Tool
209     */
210    private $clonedFrom;
211
212    private Collection $treatments;
213    private Collection $contractors;
214    private Collection $proofs;
215    private Collection $mesurements;
216    private Collection $requests;
217    private Collection $violations;
218    private Collection $tools;
219
220    /**
221     * Mesurement constructor.
222     *
223     * @throws \Exception
224     */
225    public function __construct()
226    {
227        $this->id             = Uuid::uuid4();
228        $this->proofs         = new ArrayCollection();
229        $this->contractors    = new ArrayCollection();
230        $this->mesurements    = new ArrayCollection();
231        $this->treatments     = new ArrayCollection();
232        $this->requests       = new ArrayCollection();
233        $this->violations     = new ArrayCollection();
234        $this->tools          = new ArrayCollection();
235        $this->tracking       = new ComplexChoice();
236        $this->update         = new ComplexChoice();
237        $this->archival       = new ComplexChoice();
238        $this->other          = new ComplexChoice();
239        $this->has_comment    = new ComplexChoice();
240        $this->deletion       = new ComplexChoice();
241        $this->backup         = new ComplexChoice();
242        $this->update         = new ComplexChoice();
243        $this->access_control = new ComplexChoice();
244        $this->encrypted      = new ComplexChoice();
245        $this->creator        = null;
246    }
247
248    public function __toString(): string
249    {
250        if (\is_null($this->getName())) {
251            return '';
252        }
253
254        if (\mb_strlen($this->getName()) > 150) {
255            return \mb_substr($this->getName(), 0, 150) . '...';
256        }
257
258        return $this->getName();
259    }
260
261    public function getId(): UuidInterface
262    {
263        return $this->id;
264    }
265
266    public function getName(): ?string
267    {
268        return $this->name;
269    }
270
271    public function setName(?string $name): void
272    {
273        $this->name = $name;
274    }
275
276    public function getType(): ?string
277    {
278        return $this->type;
279    }
280
281    public function setType(?string $type): void
282    {
283        $this->type = $type;
284    }
285
286    public function getEditor(): ?string
287    {
288        return $this->editor;
289    }
290
291    public function setEditor(?string $editor): void
292    {
293        $this->editor = $editor;
294    }
295
296    public function getArchival(): ?ComplexChoice
297    {
298        return $this->archival;
299    }
300
301    public function setArchival(?ComplexChoice $archival): void
302    {
303        $this->archival = $archival;
304    }
305
306    public function getEncrypted(): ?ComplexChoice
307    {
308        return $this->encrypted;
309    }
310
311    public function setEncrypted(?ComplexChoice $encrypted): void
312    {
313        $this->encrypted = $encrypted;
314    }
315
316    public function getAccessControl(): ?ComplexChoice
317    {
318        return $this->access_control;
319    }
320
321    public function setAccessControl(?ComplexChoice $access_control): void
322    {
323        $this->access_control = $access_control;
324    }
325
326    public function getUpdate(): ?ComplexChoice
327    {
328        return $this->update;
329    }
330
331    public function setUpdate(?ComplexChoice $update): void
332    {
333        $this->update = $update;
334    }
335
336    public function getBackup(): ?ComplexChoice
337    {
338        return $this->backup;
339    }
340
341    public function setBackup(?ComplexChoice $backup): void
342    {
343        $this->backup = $backup;
344    }
345
346    public function getDeletion(): ?ComplexChoice
347    {
348        return $this->deletion;
349    }
350
351    public function setDeletion(?ComplexChoice $deletion): void
352    {
353        $this->deletion = $deletion;
354    }
355
356    public function getHasComment(): ?ComplexChoice
357    {
358        return $this->has_comment;
359    }
360
361    public function setHasComment(?ComplexChoice $has_comment): void
362    {
363        $this->has_comment = $has_comment;
364    }
365
366    public function getOther(): ?ComplexChoice
367    {
368        return $this->other;
369    }
370
371    public function setOther(?ComplexChoice $other): void
372    {
373        $this->other = $other;
374    }
375
376    public function getTracking(): ?ComplexChoice
377    {
378        return $this->tracking;
379    }
380
381    public function setTracking(?ComplexChoice $tracking): void
382    {
383        $this->tracking = $tracking;
384    }
385
386    public function getManager(): ?string
387    {
388        return $this->manager;
389    }
390
391    public function setManager(?string $manager): void
392    {
393        $this->manager = $manager;
394    }
395
396    public function getDescription(): ?string
397    {
398        return $this->description;
399    }
400
401    public function setDescription(?string $description): void
402    {
403        $this->description = $description;
404    }
405
406    public function getProdDate(): ?\DateTime
407    {
408        return $this->prod_date;
409    }
410
411    public function setProdDate(?\DateTime $prod_date): void
412    {
413        $this->prod_date = $prod_date;
414    }
415
416    public function getCountryType(): ?string
417    {
418        return $this->country_type;
419    }
420
421    public function setCountryType(?string $country_type): void
422    {
423        $this->country_type = $country_type;
424    }
425
426    public function getCountryName(): ?string
427    {
428        return $this->country_name;
429    }
430
431    public function setCountryName(?string $country_name): void
432    {
433        $this->country_name = $country_name;
434    }
435
436    public function getCountryGuarantees(): ?string
437    {
438        return $this->country_guarantees;
439    }
440
441    public function setCountryGuarantees(?string $country_guarantees): void
442    {
443        $this->country_guarantees = $country_guarantees;
444    }
445
446    public function getOtherInfo(): ?string
447    {
448        return $this->other_info;
449    }
450
451    public function setOtherInfo(?string $other_info): void
452    {
453        $this->other_info = $other_info;
454    }
455
456    public function getTreatments(): Collection
457    {
458        return $this->treatments;
459    }
460
461    public function setTreatments(Collection $treatments): void
462    {
463        $this->treatments = $treatments;
464    }
465
466    public function addTreatment(Treatment $treatment): void
467    {
468        $treatment->addTool($this);
469        $this->treatments->add($treatment);
470    }
471
472    public function removeTreatment(Treatment $treatment): void
473    {
474        $treatment->removeTool($this);
475        if ($this->treatments && $this->treatments->count() && $this->treatments->contains($treatment)) {
476            $this->treatments->removeElement($treatment);
477        }
478    }
479
480    public function getContractors(): Collection
481    {
482        return $this->contractors;
483    }
484
485    public function setContractors(Collection $contractors): void
486    {
487        $this->contractors = $contractors;
488    }
489
490    public function addContractor(Contractor $contractor): void
491    {
492        $this->contractors[] = $contractor;
493    }
494
495    public function removeContractor(Contractor $contractor): void
496    {
497        if ($this->contractors && $this->contractors->count() && $this->contractors->contains($contractor)) {
498            $this->contractors->removeElement($contractor);
499        }
500    }
501
502    public function getProofs(): Collection
503    {
504        return $this->proofs;
505    }
506
507    public function setProofs(Collection $proofs): void
508    {
509        $this->proofs = $proofs;
510    }
511
512    public function addProof(Proof $proof): void
513    {
514        $proof->addTool($this);
515        $this->proofs->add($proof);
516    }
517
518    public function removeProof(Proof $proof): void
519    {
520        $proof->removeTool($this);
521        if ($this->proofs && $this->proofs->count() && $this->proofs->contains($proof)) {
522            $this->proofs->removeElement($proof);
523        }
524    }
525
526    public function getMesurements(): Collection
527    {
528        return $this->mesurements;
529    }
530
531    public function setMesurements(Collection $mesurements): void
532    {
533        $this->mesurements = $mesurements;
534    }
535
536    public function addMesurement(Mesurement $mesurement): void
537    {
538        $mesurement->addTool($this);
539        $this->mesurements->add($mesurement);
540    }
541
542    public function removeMesurement(Mesurement $mesurement): void
543    {
544        $mesurement->removeTool($this);
545        if ($this->mesurements && $this->mesurements->count() && $this->mesurements->contains($mesurement)) {
546            $this->mesurements->removeElement($mesurement);
547        }
548    }
549
550    public function getRequests(): Collection
551    {
552        return $this->requests;
553    }
554
555    public function setRequests(Collection $requests): void
556    {
557        $this->requests = $requests;
558    }
559
560    public function addRequest(Request $request): void
561    {
562        $request->addTool($this);
563        $this->requests->add($request);
564    }
565
566    public function removeRequest(Request $request): void
567    {
568        $request->removeTool($this);
569        if ($this->requests && $this->requests->count() && $this->requests->contains($request)) {
570            $this->requests->removeElement($request);
571        }
572    }
573
574    public function getViolations(): Collection
575    {
576        return $this->violations;
577    }
578
579    public function setViolations(Collection $violations): void
580    {
581        $this->violations = $violations;
582    }
583
584    public function addViolation(Violation $violation): void
585    {
586        $violation->addTool($this);
587        $this->violations->add($violation);
588    }
589
590    public function removeViolation(Violation $violation): void
591    {
592        $violation->removeTool($this);
593        if ($this->violations && $this->violations->count() && $this->violations->contains($violation)) {
594            $this->violations->removeElement($violation);
595        }
596    }
597
598    public static function generateLinkedDataColumn(iterable|Collection|null $data)
599    {
600        if (is_null($data)) {
601            return '';
602        }
603        if (is_object($data) && method_exists($data, 'toArray')) {
604            $data = $data->toArray();
605        }
606
607        return join(', ', array_map(function ($object) {
608            return $object->getName();
609        }, (array) $data));
610    }
611
612    public function getUpdatedBy(): ?string
613    {
614        return $this->updatedBy;
615    }
616
617    public function setUpdatedBy(?string $updatedBy): void
618    {
619        $this->updatedBy = $updatedBy;
620    }
621
622    public function getClonedFrom(): Tool
623    {
624        return $this->clonedFrom;
625    }
626
627    public function setClonedFrom(Tool $clonedFrom): void
628    {
629        $this->clonedFrom = $clonedFrom;
630    }
631
632    public function getTools(): ArrayCollection|Collection
633    {
634        return $this->tools;
635    }
636
637    public function setTools(ArrayCollection|Collection $tools): void
638    {
639        $this->tools = $tools;
640        foreach ($tools as $tool) {
641            $tool->addTool($this);
642        }
643    }
644
645    public function addTool(Tool $tool): void
646    {
647        $this->tools->add($tool);
648    }
649}