Issues (98)

src/Model/HealthCheckItemProvider.php (16 issues)

1
<?php
2
3
namespace Sunnysideup\HealthCheckProvider\Model;
4
5
use Exception;
6
use SilverStripe\Core\ClassInfo;
7
8
use SilverStripe\Core\Injector\Injector;
9
10
use SilverStripe\Forms\ReadonlyField;
11
use SilverStripe\ORM\DataObject;
12
use SilverStripe\ORM\DB;
13
use SilverStripe\ORM\FieldType\DBField;
14
use SilverStripe\ORM\Filters\ExactMatchFilter;
15
use SilverStripe\ORM\Filters\PartialMatchFilter;
16
17
use Sunnysideup\HealthCheckProvider\Checks\HealthCheckItemRunner;
18
19
class HealthCheckItemProvider extends DataObject
20
{
21
    protected $runner;
22
23
    #######################
24
    ### Names Section
25
    #######################
26
27
    private static $singular_name = 'Piece of Info';
0 ignored issues
show
The private property $singular_name is not used, and could be removed.
Loading history...
28
29
    private static $plural_name = 'Pieces of Info';
0 ignored issues
show
The private property $plural_name is not used, and could be removed.
Loading history...
30
31
    private static $table_name = 'HealthCheckItemProvider';
0 ignored issues
show
The private property $table_name is not used, and could be removed.
Loading history...
32
33
    #######################
34
    ### Model Section
35
    #######################
36
37
    private static $belongs_many_many = [
0 ignored issues
show
The private property $belongs_many_many is not used, and could be removed.
Loading history...
38
        'HealthCheckProviders' => HealthCheckProvider::class,
39
    ];
40
41
    private static $db = [
0 ignored issues
show
The private property $db is not used, and could be removed.
Loading history...
42
        'Include' => 'Boolean',
43
        'RunnerClassName' => 'Varchar(255)',
44
    ];
45
46
    #######################
47
    ### Further DB Field Details
48
    #######################
49
50
    private static $defaults = [
0 ignored issues
show
The private property $defaults is not used, and could be removed.
Loading history...
51
        'Include' => false,
52
    ];
53
54
    private static $searchable_fields = [
0 ignored issues
show
The private property $searchable_fields is not used, and could be removed.
Loading history...
55
        'Include' => ExactMatchFilter::class,
56
        'RunnerClassName' => PartialMatchFilter::class,
57
    ];
58
59
    #######################
60
    ### Field Names and Presentation Section
61
    #######################
62
63
    private static $field_labels = [
0 ignored issues
show
The private property $field_labels is not used, and could be removed.
Loading history...
64
        'Include' => 'Are you happy to send this?',
65
        'RunnerClassName' => 'Code',
66
        'HealthCheckProviders' => 'Reports',
67
    ];
68
69
    private static $summary_fields = [
0 ignored issues
show
The private property $summary_fields is not used, and could be removed.
Loading history...
70
        'CodeNice' => 'Code',
71
        'Include.Nice' => 'Include',
72
        'AnswerSummary' => 'Data',
73
    ];
74
75
    #######################
76
    ### Casting Section
77
    #######################
78
79
    private static $casting = [
0 ignored issues
show
The private property $casting is not used, and could be removed.
Loading history...
80
        'AnswerSummary' => 'HTMLText',
81
        'AnswerAll' => 'HTMLText',
82
        'Title' => 'Varchar',
83
        'Code' => 'Varchar',
84
        'CodeNice' => 'Varchar',
85
    ];
86
87
    public function getTitle()
88
    {
89
        return DBField::create_field('HTMLText', $this->getCode());
90
    }
91
92
    public function getCode(): string
93
    {
94
        if (class_exists($this->RunnerClassName)) {
0 ignored issues
show
Bug Best Practice introduced by
The property RunnerClassName does not exist on Sunnysideup\HealthCheckP...HealthCheckItemProvider. Since you implemented __get, consider adding a @property annotation.
Loading history...
It seems like $this->RunnerClassName can also be of type null; however, parameter $class of class_exists() 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

94
        if (class_exists(/** @scrutinizer ignore-type */ $this->RunnerClassName)) {
Loading history...
95
            return ClassInfo::shortName($this->RunnerClassName);
96
        }
97
        return 'error';
98
    }
99
100
    public function getCodeNice(): string
101
    {
102
        return preg_replace('#([a-z])([A-Z])#s', '$1 $2', $this->getCode());
103
    }
104
105
    public function getAnswerAll()
106
    {
107
        $data = $this->findAnswer();
108
109
        return DBField::create_field('HTMLText', '<pre>' . json_encode($data, JSON_PRETTY_PRINT) . '</pre>');
110
    }
111
112
    public function getAnswerSummary()
113
    {
114
        $data = $this->findAnswer();
115
        $data = $this->summariseData($data);
116
117
        return DBField::create_field('HTMLText', '<pre>' . json_encode($data, JSON_PRETTY_PRINT) . '</pre>');
118
    }
119
120
    #######################
121
    ### can Section
122
    #######################
123
124
    public function canCreate($member = null, $context = null)
125
    {
126
        return false;
127
    }
128
129
    public function canDelete($member = null)
130
    {
131
        return class_exists($this->RunnerClassName) ? false : parent::canDelete($member);
0 ignored issues
show
Bug Best Practice introduced by
The property RunnerClassName does not exist on Sunnysideup\HealthCheckP...HealthCheckItemProvider. Since you implemented __get, consider adding a @property annotation.
Loading history...
It seems like $this->RunnerClassName can also be of type null; however, parameter $class of class_exists() 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

131
        return class_exists(/** @scrutinizer ignore-type */ $this->RunnerClassName) ? false : parent::canDelete($member);
Loading history...
132
    }
133
134
    #######################
135
    ### write Section
136
    #######################
137
138
    public function requireDefaultRecords()
139
    {
140
        parent::requireDefaultRecords();
141
        foreach (HealthCheckItemProvider::get() as $item) {
142
            if (! class_exists($item->RunnerClassName)) {
143
                DB::alteration_message('Deleting superfluous: ' . $item->RunnerClassName, 'deleted');
144
                $item->delete();
145
            }
146
        }
147
148
        $classes = ClassInfo::subclassesFor(HealthCheckItemRunner::class, false);
149
        $ids = [0 => 0];
150
        foreach ($classes as $className) {
151
            $filter = ['RunnerClassName' => $className];
152
            $obj = DataObject::get_one(HealthCheckItemProvider::class, $filter);
153
            if (! $obj) {
154
                $obj = HealthCheckItemProvider::create($filter);
155
                DB::alteration_message('Creating Health Check: ' . $obj->getTitle(), 'created');
156
            }
157
            $id = $obj->write();
158
            if (! $id) {
159
                $id = $obj->ID;
160
            }
161
            $ids[$id] = $id;
162
        }
163
        $badOnes = HealthCheckItemProvider::get()->where('HealthCheckItemProvider.ID NOT IN (' . implode(',', $ids) . ')');
164
        foreach ($badOnes as $badOne) {
165
            DB::alteration_message('Deleting superfluous: ' . $badOne->getTitle(), 'deleted');
166
            $badOne->delete();
167
        }
168
    }
169
170
    public function getCMSFields()
171
    {
172
        $fields = parent::getCMSFields();
173
        $fields->removeByName('HealthCheckProviders');
174
        $fields->removeByName('RunnerClassName');
175
        $fields->addFieldsToTab(
176
            'Root.Main',
177
            [
178
                ReadonlyField::create('CodeNice', 'Code'),
179
                ReadonlyField::create('AnswerAll', 'Answer'),
180
            ]
181
        );
182
183
        return $fields;
184
    }
185
186
    public function getRunner()
187
    {
188
        if (! $this->runner) {
189
            $class = $this->RunnerClassName;
0 ignored issues
show
Bug Best Practice introduced by
The property RunnerClassName does not exist on Sunnysideup\HealthCheckP...HealthCheckItemProvider. Since you implemented __get, consider adding a @property annotation.
Loading history...
190
            if (class_exists($class)) {
0 ignored issues
show
It seems like $class can also be of type null; however, parameter $class of class_exists() 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

190
            if (class_exists(/** @scrutinizer ignore-type */ $class)) {
Loading history...
191
                $this->runner = Injector::inst()->get($this->RunnerClassName, $asSingleton = true, [$this]);
192
            }
193
        }
194
        return $this->runner;
195
    }
196
197
    public function findAnswer(): array
198
    {
199
        $answer = 'error';
200
        $isInstalled = false;
201
        $isEnabled = false;
202
        if ($this->getRunner()) {
203
            try {
204
                $answer = $this->getRunner()->getCalculatedAnswer();
205
                $isInstalled = $this->getRunner()->IsInstalled();
206
                $isEnabled = $this->getRunner()->IsEnabled();
207
            } catch (Exception $exception) {
208
                $answer = 'Caught exception: ' . $exception->getMessage();
209
            }
210
        }
211
        return [
212
            'Answer' => $answer,
213
            'IsInstalled' => $isInstalled,
214
            'IsEnabled' => $isEnabled,
215
        ];
216
    }
217
218
    private function summariseData($mixed)
219
    {
220
        if (is_string($mixed)) {
221
            if (strlen($mixed) > 50) {
222
                return substr($mixed, 0, 50) . '...';
223
            }
224
        } elseif (is_array($mixed)) {
225
            $returnArray = [];
226
            $count = 0;
227
            foreach ($mixed as $key => $item) {
228
                ++$count;
229
                $returnArray[$this->summariseData($key)] = $this->summariseData($item);
230
                if ($count > 3) {
231
                    $returnArray[] = ' + ' . count($mixed) . ' MORE ...';
232
                    break;
233
                }
234
            }
235
            return $returnArray;
236
        }
237
        return $mixed;
238
    }
239
}
240