Passed
Push — master ( fbc61a...4022cc )
by Davide
73:49 queued 40:24
created

Event::preSave()   C

Complexity

Conditions 10
Paths 192

Size

Total Lines 59
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 27
CRAP Score 11.1946

Importance

Changes 0
Metric Value
eloc 35
c 0
b 0
f 0
dl 0
loc 59
ccs 27
cts 35
cp 0.7714
rs 6.9
cc 10
nc 192
nop 2
crap 11.1946

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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

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

374
            LaravelEventsCalendar::/** @scrutinizer ignore-call */ 
375
                                   uploadImageOnServer($imageFile, $imageName, $imageSubdir, $imageWidth, $thumbWidth);
Loading history...
375
            $this->image = $imageName;
376
        } else {
377
            //$this->image = $request->get('image');
378 33
            if (array_key_exists('image', $requestArray)) {
379
                $this->image = $requestArray['image'];
380
            }
381
        }
382
        
383
         // Multiple teachers - populate support column field
384 33
        $this->sc_teachers_names = '';
385 33
        if (array_key_exists("multiple_teachers",$requestArray)) {
386 2
            $multiple_teachers = explode(',', $requestArray['multiple_teachers']);
387
388 2
            $multiple_teachers_names = [];
389 2
            foreach ($multiple_teachers as $key => $teacher_id) {
390 2
                $multiple_teachers_names[] = $teachers[$teacher_id];
391
            }
392
            
393
            // Support columns for homepage search (we need this to show events in HP with less use of resources)
394 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

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