Test Failed
Push — master ( 1994ba...c08f7b )
by Davide
36:24
created

Event   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 424
Duplicated Lines 0 %

Test Coverage

Coverage 93.02%

Importance

Changes 22
Bugs 5 Features 1
Metric Value
wmc 43
eloc 188
c 22
b 5
f 1
dl 0
loc 424
ccs 160
cts 172
cp 0.9302
rs 8.96

11 Methods

Rating   Name   Duplication   Size   Complexity  
A teachers() 0 3 1
A user() 0 3 1
A eventRepetitions() 0 3 1
A organizers() 0 3 1
A getActiveEvents() 0 23 1
A getActiveEventsMapMarkersDataFromDb() 0 35 1
A getActiveEventsMapGeoJSON() 0 56 5
C getEvents() 0 79 12
B setEventRepeatFields() 0 22 7
A isActive() 0 8 2
C preSave() 0 59 11

How to fix   Complexity   

Complex Class

Complex classes like Event often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Event, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace DavideCasiraghi\LaravelEventsCalendar\Models;
4
5
use Carbon\Carbon;
6
use DavideCasiraghi\LaravelEventsCalendar\Facades\LaravelEventsCalendar;
7
use Illuminate\Database\Eloquent\Model;
8
use Illuminate\Support\Facades\Cache; // to remove
9
use Illuminate\Support\Str;
10
11
class Event extends Model
12
{
13
    /***************************************************************************/
14
    /**
15
     * The table associated with the model.
16
     *
17
     * @var string
18
     */
19
    protected $table = 'events';
20
21
    /***************************************************************************/
22
23
    protected $fillable = [
24
        'title',
25
        'description',
26
        'organized_by',
27
        'category_id',
28
        'venue_id',
29
        'image',
30
        'facebook_event_link',
31
        'website_event_link',
32
        'status',
33
        'repeat_type',
34
        'repeat_until',
35
        'repeat_weekly_on',
36
        'repeat_monthly_on',
37
        'on_monthly_kind',
38
        'multiple_dates',
39
    ];
40
41
    /***************************************************************************/
42
43
    /**
44
     * Get the user that owns the event. eg. $event->user.
45
     */
46
    public function user()
47
    {
48
        return $this->belongsTo('\Illuminate\Foundation\Auth\User', 'created_by');
49
    }
50
51
    /***************************************************************************/
52
53
    /**
54
     * Get the teachers for the event.
55
     */
56 33
    public function teachers()
57
    {
58 33
        return $this->belongsToMany('DavideCasiraghi\LaravelEventsCalendar\Models\Teacher', 'event_has_teachers', 'event_id', 'teacher_id');
59
    }
60
61
    /***************************************************************************/
62
63
    /**
64
     * Get the organizers for the event.
65
     */
66 33
    public function organizers()
67
    {
68 33
        return $this->belongsToMany('DavideCasiraghi\LaravelEventsCalendar\Models\Organizer', 'event_has_organizers', 'event_id', 'organizer_id');
69
    }
70
71
    /***************************************************************************/
72
73
    /**
74
     * Get the organizers for the event.
75
     */
76 1
    public function eventRepetitions()
77
    {
78 1
        return $this->hasMany('DavideCasiraghi\LaravelEventsCalendar\Models\EventRepetition', 'event_id');
79
    }
80
81
    /***************************************************************************/
82
83
    /**
84
     * Return an array with active events datas.
85
     *
86
     * @return array
87
     */
88 2
    public static function getActiveEvents()
89
    {
90 2
        $seconds = 86400; // One day (this cache tag get invalidates also on event save)
91
92
        $ret = Cache::remember('active_events', $seconds, function () {
93 2
            date_default_timezone_set('Europe/Rome');
94 2
            $searchStartDate = date('Y-m-d', time());
95 2
            $lastestEventsRepetitionsQuery = EventRepetition::getLastestEventsRepetitionsQuery($searchStartDate, null);
96
97
            return self::
98 2
                    select('events.id as id', 'title', 'countries.name AS country_name', 'countries.id AS country_id', 'countries.continent_id AS continent_id', 'event_venues.city AS city', 'events.repeat_until', 'events.category_id', 'events.created_by', 'events.repeat_type')
99 2
                    ->join('event_venues', 'event_venues.id', '=', 'events.venue_id')
100 2
                    ->join('countries', 'countries.id', '=', 'event_venues.country_id')
101
                    ->joinSub($lastestEventsRepetitionsQuery, 'event_repetitions', function ($join) {
102 2
                        $join->on('events.id', '=', 'event_repetitions.event_id');
103 2
                    })
104 2
                    ->get();
105
106
            /* EVERY TIME THIS QUERY CHANGE REMEMBER TO FLUSH THE CACHE
107
            (php artisan cache:clear) */
108 2
        });
109
110 2
        return $ret;
111
    }
112
113
    /***************************************************************************/
114
115
    /**
116
     * Return the active events based on the search keys provided.
117
     *
118
     * @param array $filters
119
     * @param int $itemPerPage
120
     * @return \DavideCasiraghi\LaravelEventsCalendar\Models\Event
121
     */
122
    //$keywords, $category, $city, $country, $continent, $teacher, $venue, $startDate, $endDate,
123 2
    public static function getEvents(array $filters, $itemPerPage)
124
    {
125 2
        if (! array_key_exists('startDate', $filters) || ! $filters['startDate']) {
126 2
            $filters['startDate'] = Carbon::now()->format('Y-m-d');
127
        }
128
129
        // Sub-Query Joins - https://laravel.com/docs/5.7/queries
130 2
        $lastestEventsRepetitionsQuery = EventRepetition::getLastestEventsRepetitionsQuery($filters['startDate'], $filters['endDate']);
131
132
        // Retrieve the events that correspond to the selected filters
133 2
        if ($filters['keywords'] || $filters['category'] || $filters['city'] || $filters['country'] || $filters['region'] || $filters['continent'] || $filters['teacher'] || $filters['venue'] || $filters['endDate']) {
134
135
        //$start = microtime(true);
136
            //DB::enableQueryLog();
137
            $ret = self::
138 1
                    select('events.title', 'events.category_id', 'events.slug', 'event_venues.name as venue_name', 'event_venues.city as city_name', 'countries.name as country_name', 'events.sc_teachers_names', 'event_repetitions.start_repeat', 'event_repetitions.end_repeat')
139
                    ->when($filters['keywords'], function ($query, $keywords) {
140 1
                        return $query->where('title', 'like', '%'.$keywords.'%');
141 1
                    })
142
                    ->when($filters['category'], function ($query, $category) {
143 1
                        return $query->where('category_id', '=', $category);
144 1
                    })
145
                    ->when($filters['teacher'], function ($query, $teacher) {
146
                        return $query->whereRaw('json_contains(sc_teachers_id, \'["'.$teacher.'"]\')');
147 1
                    })
148
                    ->when($filters['country'], function ($query, $country) {
149 1
                        return $query->where('event_venues.country_id', '=', $country);
150 1
                    })
151
                    ->when($filters['region'], function ($query, $region) {
152 1
                        return $query->where('event_venues.region_id', '=', $region);
153 1
                    })
154
                    ->when($filters['continent'], function ($query, $continent) {
155 1
                        return $query->where('event_venues.continent_id', '=', $continent);  //sc_continent_id
156 1
                    })
157
                    ->when($filters['city'], function ($query, $city) {
158 1
                        return $query->where('event_venues.city', 'like', '%'.$city.'%');
159 1
                    })
160
                    ->when($filters['venue'], function ($query, $venue) {
161 1
                        return $query->where('event_venues.name', 'like', '%'.$venue.'%');
162 1
                    })
163
                    ->joinSub($lastestEventsRepetitionsQuery, 'event_repetitions', function ($join) {
164 1
                        $join->on('events.id', '=', 'event_repetitions.event_id');
165 1
                    })
166
167 1
                    ->leftJoin('event_venues', 'events.venue_id', '=', 'event_venues.id')
168 1
                    ->leftJoin('continents', 'event_venues.continent_id', '=', 'continents.id')
169 1
                    ->leftJoin('countries', 'event_venues.country_id', '=', 'countries.id')
170 1
                    ->leftJoin('regions', 'event_venues.region_id', '=', 'regions.id')
171
172 1
                    ->orderBy('event_repetitions.start_repeat', 'asc')
173 1
                    ->paginate($itemPerPage);
174
        //dd(DB::getQueryLog());
175
176
        //$time = microtime(true) - $start;
177
        //dd($time);
178
        }
179
        // If no filter selected retrieve all the events
180
        else {
181
            $ret = self::
182 1
                        select('events.title', 'events.category_id', 'events.slug', 'event_venues.name as venue_name', 'event_venues.city as city_name', 'countries.name as country_name', 'events.sc_teachers_names', 'event_repetitions.start_repeat', 'event_repetitions.end_repeat')
183
                        ->joinSub($lastestEventsRepetitionsQuery, 'event_repetitions', function ($join) {
184 1
                            $join->on('events.id', '=', 'event_repetitions.event_id');
185 1
                        })
186 1
                        ->leftJoin('event_venues', 'events.venue_id', '=', 'event_venues.id')
187 1
                        ->leftJoin('continents', 'event_venues.continent_id', '=', 'continents.id')
188 1
                        ->leftJoin('countries', 'event_venues.country_id', '=', 'countries.id')
189 1
                        ->leftJoin('regions', 'event_venues.region_id', '=', 'regions.id')
190
191 1
                        ->orderBy('event_repetitions.start_repeat', 'asc')
192 1
                        ->paginate($itemPerPage);
193
194
            // It works, but I don't use it now to develop
195
                /*$cacheExpireMinutes = 15;
196
                $events = Cache::remember('all_events', $cacheExpireTime, function () {
197
                    return DB::table('events')->latest()->paginate(20);
198
                });*/
199
        }
200
201 2
        return $ret;
202
    }
203
204
    /***************************************************************************/
205
206
    /**
207
     * Return a cached JSON with active events map markers.
208
     *
209
     * @return array
210
     */
211 2
    public static function getActiveEventsMapGeoJSON()
212
    {
213 2
        $cacheExpireMinutes = 1440; // Set the duration time of the cache (1 day - 1440 minutes) - this cache tag get invalidates also on event save
214
215
        $eventsMapGeoJSONArrayCached = Cache::remember('active_events_map_markers_json', $cacheExpireMinutes, function () {
216 2
            $eventsData = self::getActiveEventsMapMarkersDataFromDb();
217 2
            $eventsMapGeoJSONArray = [];
218 2
            foreach ($eventsData as $key => $eventData) {
219
                //dd($eventData);
220
221
                // Generates event link
222 2
                $nextEventRepetitionId = EventRepetition::getFirstEventRpIdByEventId($eventData->id);
223 2
                $eventLinkformat = 'event/%s/%s';   //event/{{$event->slug}}/{{$event->rp_id}}
224 2
                $eventLink = sprintf($eventLinkformat, $eventData->event_slug, $nextEventRepetitionId);
225
226
                // Get Next event occurrence date
227 2
                $nextDateOccurence = EventRepetition::getFirstFutureEventRpDatesByEventId($eventData->id);
228 2
                if (! empty($nextDateOccurence)) {
229 2
                    $nextDate = Carbon::parse($nextDateOccurence->start_repeat)->isoFormat('D MMM YYYY');
230
                } else {
231
                    $nextDate = '';
232
                }
233
234 2
                $address = (! empty($eventData->address)) ? ', '.$eventData->address : '';
235 2
                $city = (! empty($eventData->city)) ? $eventData->city : '';
236
237
                // Add one element to the Geo array
238 2
                $eventsMapGeoJSONArray[] = [
239 2
                    'type' => 'Feature',
240 2
                    'id' => $eventData->id,
241
                    'properties' => [
242 2
                        'Title' => $eventData->title,
243 2
                        'Category' => EventCategory::getCategoryName($eventData->category_id),
244 2
                        'VenueName' => EventVenue::getVenueName($eventData->venue_id),
245 2
                        'City' => $city,
246 2
                        'Address' => $address,
247 2
                        'Link' => $eventLink,
248 2
                        'NextDate' => $nextDate,
249 2
                        'IconColor' => LaravelEventsCalendar::getMapMarkerIconColor($eventData->category_id),
0 ignored issues
show
Bug introduced by
The method getMapMarkerIconColor() does not exist on DavideCasiraghi\LaravelE...s\LaravelEventsCalendar. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

249
                        'IconColor' => LaravelEventsCalendar::/** @scrutinizer ignore-call */ getMapMarkerIconColor($eventData->category_id),
Loading history...
250
                    ],
251
                    'geometry' => [
252 2
                        'type' => 'Point',
253 2
                        'coordinates' => [$eventData->lng, $eventData->lat],
254
                    ],
255
                ];
256
            }
257
258
            /* EVERY TIME THIS CHANGE REMEMBER TO FLUSH THE CACHE
259
            (php artisan cache:clear) */
260
261 2
            return $eventsMapGeoJSONArray;
262 2
        });
263
264 2
        $ret = json_encode($eventsMapGeoJSONArrayCached);
265
266 2
        return $ret;
267
    }
268
269
    /***************************************************************************/
270
271
    /**
272
     * Return an array with active events map markers.
273
     *
274
     * @return array
275
     */
276 4
    public static function getActiveEventsMapMarkersDataFromDb()
277
    {
278 4
        $seconds = 86400; // One day (this cache tag get invalidates also on event save)
279
280
        $ret = Cache::remember('active_events_map_markers_db_data', $seconds, function () {
281 4
            date_default_timezone_set('Europe/Rome');
282 4
            $searchStartDate = Carbon::now()->format('Y-m-d');
283 4
            $lastestEventsRepetitionsQuery = EventRepetition::getLastestEventsRepetitionsQuery($searchStartDate, null);
284
285
            return self::
286 4
                    select('events.id AS id',
287 4
                    'events.title AS title',
288 4
                    'events.slug AS event_slug',
289 4
                    'event_venues.id AS venue_id',
290 4
                    'event_venues.city AS city',
291 4
                    'event_venues.address AS address',
292 4
                    'event_venues.lat AS lat',
293 4
                    'event_venues.lng AS lng',
294 4
                    'events.repeat_until',
295 4
                    'events.category_id',
296 4
                    'events.created_by',
297 4
                    'events.repeat_type'
298
                    )
299 4
            ->join('event_venues', 'event_venues.id', '=', 'events.venue_id')
300 4
            ->join('countries', 'countries.id', '=', 'event_venues.country_id')
301
            ->joinSub($lastestEventsRepetitionsQuery, 'event_repetitions', function ($join) {
302 4
                $join->on('events.id', '=', 'event_repetitions.event_id');
303 4
            })
304 4
            ->get();
305
306
            /* EVERY TIME THIS QUERY CHANGE REMEMBER TO FLUSH THE CACHE
307
            (php artisan cache:clear) */
308 4
        });
309
310 4
        return $ret;
311
    }
312
313
    /***************************************************************************/
314
315
    /**
316
     * Return true if an event is in the future.
317
     *
318
     * @return bool
319
     */
320 2
    public function isActive(): bool
321
    {
322 2
        $firstEventRepetitionIdInFuture = EventRepetition::getFirstEventRpIdByEventId($this->id);
323
324 2
        if (! empty($firstEventRepetitionIdInFuture)) {
325 2
            return true;
326
        } else {
327 1
            return false;
328
        }
329
    }
330
331
    // **********************************************************************
332
333
    /**
334
     * Prepare the record to be saved on DB.
335
     *
336
     * @param  array  $requestArray
337
     * @param  \Illuminate\Http\UploadedFile  $eventPicture
338
     * @return void
339
     */
340 33
    public function preSave(array $requestArray, $eventPicture): void
341
    {
342 33
        $teachers = Teacher::pluck('name', 'id');
343
344 33
        $this->title = $requestArray['title'];
345 33
        $this->description = clean($requestArray['description']);
346
347 33
        if ($requestArray['created_by']) {
348 33
            $this->created_by = $requestArray['created_by'];
349
        }
350
351 33
        if (! $this->slug) {
352 33
            $this->slug = Str::slug($this->title, '-').'-'.rand(100000, 1000000);
353
        }
354 33
        $this->category_id = $requestArray['category_id'];
355 33
        $this->venue_id = $requestArray['venue_id'];
356 33
        $this->contact_email = $requestArray['contact_email'];
357 33
        $this->website_event_link = $requestArray['website_event_link'];
358 33
        $this->facebook_event_link = $requestArray['facebook_event_link'];
359 33
        $this->status = (array_key_exists('status', $requestArray)) ? $requestArray['status'] : null;
360 33
        $this->on_monthly_kind = (array_key_exists('on_monthly_kind', $requestArray)) ? $requestArray['on_monthly_kind'] : null;
361
        //$this->on_monthly_kind = $requestArray['on_monthly_kind'];
362 33
        $this->multiple_dates = (array_key_exists('multiple_dates', $requestArray)) ? $requestArray['multiple_dates'] : null;
363
364
        // Event teaser image upload
365
        //if ($request->file('image')) {
366 33
        if (! empty($eventPicture)) {
367
            $imageFile = $eventPicture;
368
            $imageName = time().'.'.'jpg';  //$imageName = $teaserImageFile->hashName();
369
            $imageSubdir = 'events_teaser';
370
            $imageWidth = 968;
371
            $thumbWidth = 310;
372
373
            LaravelEventsCalendar::uploadImageOnServer($imageFile, $imageName, $imageSubdir, $imageWidth, $thumbWidth);
0 ignored issues
show
Bug introduced by
The method uploadImageOnServer() does not exist on DavideCasiraghi\LaravelE...s\LaravelEventsCalendar. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

373
            LaravelEventsCalendar::/** @scrutinizer ignore-call */ 
374
                                   uploadImageOnServer($imageFile, $imageName, $imageSubdir, $imageWidth, $thumbWidth);
Loading history...
374
            $this->image = $imageName;
375
        } else {
376
            //$this->image = $request->get('image');
377 33
            if (array_key_exists('image', $requestArray)) {
378
                $this->image = $requestArray['image'];
379
            }
380
        }
381
382
        // Multiple teachers - populate support column field
383 33
        $this->sc_teachers_names = '';
384 33
        if (isset($requestArray['multiple_teachers']) && array_key_exists('multiple_teachers', $requestArray)) {
385 2
            $multiple_teachers = explode(',', $requestArray['multiple_teachers']);
386
387 2
            $multiple_teachers_names = [];
388 2
            foreach ($multiple_teachers as $key => $teacher_id) {
389 2
                $multiple_teachers_names[] = $teachers[$teacher_id];
390
            }
391
392
            // Support columns for homepage search (we need this to show events in HP with less use of resources)
393 2
            $this->sc_teachers_names .= LaravelEventsCalendar::getStringFromArraySeparatedByComma($multiple_teachers_names); //@todo find an alternative to this
0 ignored issues
show
Bug introduced by
The method getStringFromArraySeparatedByComma() does not exist on DavideCasiraghi\LaravelE...s\LaravelEventsCalendar. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

393
            $this->sc_teachers_names .= LaravelEventsCalendar::/** @scrutinizer ignore-call */ getStringFromArraySeparatedByComma($multiple_teachers_names); //@todo find an alternative to this
Loading history...
394 2
            $this->sc_teachers_id = json_encode(explode(',', $requestArray['multiple_teachers'])); //@todo find an alternative to this
395
        }
396
397
        // Set the Event attributes about repeating (repeat until field and multiple days)
398 33
        $this->setEventRepeatFields($requestArray);
399
400
        // Save event and repetitions
401
         //$this->save();
402
         //$this->saveEventRepetitions($request, $this->id);
403 33
    }
404
405
    /***************************************************************************/
406
407
    /**
408
     * Set the Event attributes about repeating before store or update (repeat until field and multiple days).
409
     *
410
     * @param  array  $requestArray
411
     * @return void
412
     */
413 33
    public function setEventRepeatFields(array $requestArray)
414
    {
415
        // Set Repeat Until
416 33
        $this->repeat_type = $requestArray['repeat_type'];
417 33
        if (isset($requestArray['repeat_until']) && array_key_exists('repeat_until', $requestArray)) {
418 7
            $dateRepeatUntil = implode('-', array_reverse(explode('/', $requestArray['repeat_until'])));
419 7
            $this->repeat_until = $dateRepeatUntil.' 00:00:00';
420
        }
421
422
        // Weekely - Set multiple week days
423
        //if (array_key_exists("repeat_weekly_on_day",$requestArray)) {
424 33
        if (isset($requestArray['repeat_weekly_on_day']) && array_key_exists('repeat_weekly_on_day', $requestArray)) {
425 2
            $repeat_weekly_on_day = $requestArray['repeat_weekly_on_day'];
426 2
            $i = 0;
427 2
            $len = count($repeat_weekly_on_day); // to put "," to all items except the last
428 2
            $this->repeat_weekly_on = '';
429 2
            foreach ($repeat_weekly_on_day as $key => $weeek_day) {
430 2
                $this->repeat_weekly_on .= $weeek_day;
431 2
                if ($i != $len - 1) {  // not last
432 2
                    $this->repeat_weekly_on .= ',';
433
                }
434 2
                $i++;
435
            }
436
        }
437 33
    }
438
439
    /***************************************************************************/
440
}
441