Test Failed
Push — master ( e3c39f...fe570d )
by Mihail
07:20
created

Apps/Model/Admin/Content/FormContentUpdate.php (2 issues)

Checks property assignments for possibly missing type casts.

Bug Documentation Minor
1
<?php
2
3
namespace Apps\Model\Admin\Content;
4
5
use Apps\ActiveRecord\CommentPost;
6
use Apps\ActiveRecord\Content;
7
use Apps\ActiveRecord\ContentCategory;
8
use Apps\ActiveRecord\ContentTag;
9
use Apps\ActiveRecord\User;
10
use Ffcms\Core\App;
11
use Ffcms\Core\Arch\Model;
12
use Ffcms\Core\Helper\Crypt;
13
use Ffcms\Core\Helper\Date;
14
use Ffcms\Core\Helper\FileSystem\Directory;
15
use Ffcms\Core\Helper\FileSystem\File;
16
use Ffcms\Core\Helper\Type\Any;
17
use Ffcms\Core\Helper\Type\Integer;
18
use Ffcms\Core\Helper\Type\Str;
19
use Illuminate\Support\Collection;
20
21
/**
22
 * Class FormContentUpdate. Create and update content items business model
23
 * @package Apps\Model\Admin\Content
24
 */
25
class FormContentUpdate extends Model
26
{
27
    public $title = [];
28
    public $text = [];
29
    public $path;
30
    public $poster;
31
    public $categoryId;
32
    public $authorId;
33
    public $metaTitle;
34
    public $metaKeywords = [];
35
    public $metaDescription = [];
36
    public $display = 1;
37
    public $source;
38
    public $addRating = 0;
39
    public $createdAt;
40
    public $important;
41
42
    public $galleryFreeId;
43
44
    private $_content;
45
    private $cloneId;
46
    private $_new = false;
47
48
    /**
49
     * FormContentUpdate constructor. Pass content active record inside
50
     * @param Content|Collection $content
51
     * @param int $cloneId
52
     */
53
    public function __construct(Content $content, int $cloneId = 0)
54
    {
55
        $this->_content = $content;
56
        $this->cloneId = $cloneId;
57
        parent::__construct();
58
    }
59
60
    /**
61
     * Set model properties from active record data
62
     */
63
    public function before()
64
    {
65
        // is new item?
66
        if (!$this->_content->id) {
67
            $this->_new = true;
68
            if (!$this->galleryFreeId) {
69
                $this->galleryFreeId = '_tmp_' . Str::randomLatin(mt_rand(16, 32));
70
            }
71
72
            if (!$this->authorId) {
73
                $this->authorId = App::$User->identity()->getId();
74
            }
75
76
            if (!$this->categoryId) {
77
                $this->categoryId = 1;
78
            }
79
            if (!$this->path) {
80
                $this->path = Integer::random(8) . '-' . date('d-m-Y');
81
            }
82
83
            if ($this->cloneId > 0) {
84
                $template = Content::find($this->cloneId);
85
                if ($template) {
86
                    $this->title = $template->title;
87
                    $this->text = $template->text;
88
                    $this->metaTitle = $template->meta_title;
89
                    $this->metaDescription = $template->meta_description;
90
                    $this->metaKeywords = $template->meta_keywords;
91
                }
92
            }
93
        } else { // is edit of exist item? define available data
94
            $this->title = $this->_content->title;
95
            $this->text = $this->_content->text;
96
            $this->path = $this->_content->path;
97
            $this->poster = $this->_content->poster;
98
            $this->categoryId = $this->_content->category_id;
99
            $this->authorId = $this->_content->author_id;
100
            $this->metaTitle = $this->_content->meta_title;
101
            $this->metaKeywords = $this->_content->meta_keywords;
102
            $this->metaDescription = $this->_content->meta_description;
103
            $this->display = $this->_content->display;
104
            $this->source = $this->_content->source;
105
            $this->createdAt = Date::convertToDatetime($this->_content->created_at, Date::FORMAT_TO_HOUR);
106
            $this->galleryFreeId = $this->_content->id;
107
            $this->important = $this->_content->important;
108
        }
109
    }
110
111
    /**
112
     * Validation rules
113
     * @return array
114
     */
115
    public function rules(): array
116
    {
117
        $res = [
118
            ['title.' . App::$Request->getLanguage(), 'required'],
119
            ['text.' . App::$Request->getLanguage(), 'required'],
120
            ['text', 'used'],
121
            ['path', 'reverse_match', '/[\/\'~`\[email protected]#\$%\^&\*\(\)+=\{\}\[\]\|;:"\<\>,\?\\\]/'],
122
            [['path', 'categoryId', 'authorId', 'display', 'galleryFreeId', 'title', 'important'], 'required'],
123
            [['metaTitle', 'metaKeywords', 'metaDescription', 'poster', 'source', 'addRating', 'createdAt'], 'used'],
124
            [['addRating', 'authorId', 'display'], 'int'],
125
            [['important', 'display'], 'boolean'],
126
            ['categoryId', 'in', $this->categoryIds()],
127
            ['path', '\Apps\Model\Admin\Content\FormContentUpdate::validatePath'],
128
            ['authorId', '\App::$User::isExist']
129
        ];
130
131
        foreach (App::$Properties->get('languages') as $lang) {
132
            $res[] = ['title.' . $lang, 'length_max', 120, null, true, true];
133
            $res[] = ['keywords.' . $lang, 'length_max', 150];
134
            $res[] = ['description.' . $lang, 'length_max', 250];
135
        }
136
137
        return $res;
138
    }
139
140
    /**
141
     * Filtering attribute types
142
     * @return array
143
     */
144
    public function types(): array
145
    {
146
        return [
147
            'text' => '!secure'
148
        ];
149
    }
150
151
    /**
152
     * Form display labels
153
     * @return array
154
     */
155
    public function labels(): array
156
    {
157
        return [
158
            'title' => __('Content title'),
159
            'text' => __('Content text'),
160
            'path' => __('Path slug'),
161
            'categoryId' => __('Category'),
162
            'metaTitle' => __('Meta title'),
163
            'metaKeywords' => __('Meta keywords'),
164
            'metaDescription' => __('Meta description'),
165
            'display' => __('Public display'),
166
            'important' => __('Make important'),
167
            'createdAt' => __('Publish date'),
168
            'authorId' => __('Author identity'),
169
            'source' => __('Source URL'),
170
            'addRating' => __('Change rating'),
171
            'poster' => __('Poster')
172
        ];
173
    }
174
175
    /**
176
     * Save changes in database
177
     */
178
    public function save()
179
    {
180
        $this->_content->title = $this->title;
181
        $this->_content->text = $this->text;
182
        $this->_content->path = $this->path;
183
        $this->_content->category_id = $this->categoryId;
184
        $this->_content->author_id = $this->authorId;
185
        $this->_content->display = $this->display;
0 ignored issues
show
Documentation Bug introduced by Mihail
The property $display was declared of type boolean, but $this->display is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
186
        $this->_content->meta_title = $this->metaTitle;
187
        $this->_content->meta_keywords = $this->metaKeywords;
188
        $this->_content->meta_description = $this->metaDescription;
189
        $this->_content->source = $this->source;
190
        $this->_content->important = (int)$this->important;
0 ignored issues
show
Documentation Bug introduced by zenn
The property $important was declared of type boolean, but (int)$this->important is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
191
        // check if rating is changed
192
        if ((int)$this->addRating !== 0) {
193
            $this->_content->rating += (int)$this->addRating;
194
        }
195
196
        // check if date is updated
197
        if (!Str::likeEmpty($this->createdAt) && !Str::startsWith('0000', Date::convertToDatetime($this->createdAt, Date::FORMAT_SQL_TIMESTAMP))) {
198
            $this->_content->created_at = Date::convertToDatetime($this->createdAt, Date::FORMAT_SQL_TIMESTAMP);
199
        }
200
201
        // save poster data
202
        $posterPath = '/upload/gallery/' . $this->galleryFreeId . '/orig/' . $this->poster;
203
        if (File::exist($posterPath)) {
204
            $this->_content->poster = $this->poster;
205
        }
206
207
        // get temporary gallery id
208
        $tmpGalleryId = $this->galleryFreeId;
209
210
        // save row
211
        $this->_content->save();
212
        
213
        // update tags data in special table (relation: content->content_tags = oneToMany)
214
        ContentTag::where('content_id', $this->_content->id)->delete();
215
        $insertData = [];
216
        foreach ($this->metaKeywords as $lang => $keys) {
217
            // split keywords to tag array
218
            $tags = explode(',', $keys);
219
            foreach ($tags as $tag) {
220
                // cleanup tag from white spaces
221
                $tag = trim($tag);
222
                // prepare data to insert
223
                if (Str::length($tag) > 0) {
224
                    $insertData[] = [
225
                        'content_id' => $this->_content->id,
226
                        'lang' => $lang,
227
                        'tag' => $tag
228
                    ];
229
                }
230
            }
231
        }
232
        // insert tags
233
        ContentTag::insert($insertData);
234
235
        // move files
236
        if ($tmpGalleryId !== $this->_content->id) {
237
            Directory::rename('/upload/gallery/' . $tmpGalleryId, $this->_content->id);
238
        }
239
    }
240
241
    /**
242
     * Get allowed category ids as array
243
     * @return array
244
     */
245
    public function categoryIds(): ?array
246
    {
247
        $data = ContentCategory::getSortedCategories();
248
        return array_keys($data);
249
    }
250
251
    /**
252
     * Validate path filter
253
     * @return bool
254
     */
255
    public function validatePath(): bool
256
    {
257
        // try to find this item
258
        $find = Content::where('path', $this->path);
259
        // exclude self id
260
        if ($this->_content->id && Any::isInt($this->_content->id)) {
261
            $find->where('id', '!=', $this->_content->id);
262
        }
263
264
        // limit only current category id
265
        $find->where('category_id', $this->categoryId);
266
        return $find->count() < 1;
267
    }
268
269
    /**
270
     * Get users id->nick+mail list
271
     * @return array|null
272
     */
273
    public function getUserIdName(): ?array
274
    {
275
        $users = [];
276
        User::with('profile')->get()->each(function ($user) use (&$users) {
277
            /** @var User $user */
278
            $users[$user->id] = ($user->profile->nick ?? 'id' . $user->id) . ' (' . $user->email . ')';
279
        });
280
281
        return $users;
282
    }
283
284
    /**
285
     * Check if news is new
286
     * @return bool
287
     */
288
    public function isNew(): bool
289
    {
290
        return $this->_new;
291
    }
292
293
    /**
294
     * Get content comments
295
     * @return CommentPost[]|\Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection|null
296
     */
297
    public function getComments()
298
    {
299
        if ($this->isNew()) {
300
            return null;
301
        }
302
303
        return $this->_content->commentPosts;
304
305
        /**return CommentPost::with(['user', 'user.profile'])
306
            ->where('app_name', 'content')
307
            ->where('app_relation_id', $this->_content->id)
308
            ->get();*/
309
    }
310
}
311