Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 878
0.00% covered (danger)
0.00%
0 / 18
CRAP
0.00% covered (danger)
0.00%
0 / 1
zbsDAL_events
0.00% covered (danger)
0.00%
0 / 878
0.00% covered (danger)
0.00%
0 / 18
87912
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
56
 add_listview_filters
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
12
 getSingle
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getIDList
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 getAll
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
 getFullCount
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 getEvent
0.00% covered (danger)
0.00%
0 / 109
0.00% covered (danger)
0.00%
0 / 1
1190
 getEvents
0.00% covered (danger)
0.00%
0 / 225
0.00% covered (danger)
0.00%
0 / 1
9312
 getEventCount
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 1
56
 addUpdateEvent
0.00% covered (danger)
0.00%
0 / 329
0.00% covered (danger)
0.00%
0 / 1
10712
 addUpdateEventTags
0.00% covered (danger)
0.00%
0 / 31
0.00% covered (danger)
0.00%
0 / 1
90
 setEventCompleteness
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
6
 deleteEvent
0.00% covered (danger)
0.00%
0 / 43
0.00% covered (danger)
0.00%
0 / 1
110
 tidy_event
0.00% covered (danger)
0.00%
0 / 21
0.00% covered (danger)
0.00%
0 / 1
132
 getEventMeta
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
6
 getEventOwner
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
6
 db_ready_event
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 listViewObj
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
30
1<?php
2/*
3 * Jetpack CRM
4 * https://jetpackcrm.com
5 * V3.0+
6 *
7 * Copyright 2020 Automattic
8 *
9 * Date: 14/01/19
10 */
11
12defined( 'ZEROBSCRM_PATH' ) || exit( 0 );
13
14/**
15 * ZBS DAL >> Events (tasks)
16 *
17 * @author   Woody Hayday <hello@jetpackcrm.com>
18 * @version  2.0
19 * @access   public
20 * @see      https://jetpackcrm.com/kb
21 */
22class zbsDAL_events extends zbsDAL_ObjectLayer {
23
24    protected $objectType            = ZBS_TYPE_TASK;
25    protected $objectDBPrefix        = 'zbse_';
26    protected $include_in_templating = true;
27    protected $objectModel           = array(
28
29        // ID
30        'ID'             => array(
31            'fieldname' => 'ID',
32            'format'    => 'int',
33        ),
34
35        // site + team generics
36        'zbs_site'       => array(
37            'fieldname' => 'zbs_site',
38            'format'    => 'int',
39        ),
40        'zbs_team'       => array(
41            'fieldname' => 'zbs_team',
42            'format'    => 'int',
43        ),
44        'zbs_owner'      => array(
45            'fieldname' => 'zbs_owner',
46            'format'    => 'int',
47        ),
48
49        // other fields
50        'title'          => array(
51            'fieldname' => 'zbse_title',
52            'format'    => 'str',
53            'max_len'   => 255,
54        ),
55        'desc'           => array(
56            'fieldname' => 'zbse_desc',
57            'format'    => 'str',
58            'dal1key'   => 'notes',
59                            // max_len = LONGTEXT, unlikely to breach
60        ),
61        'start'          => array(
62            'fieldname' => 'zbse_start',
63            'format'    => 'uts',
64            'dal1key'   => 'from',
65        ),
66        'end'            => array(
67            'fieldname' => 'zbse_end',
68            'format'    => 'uts',
69            'dal1key'   => 'to',
70        ),
71        'complete'       => array(
72            'fieldname' => 'zbse_complete',
73            'format'    => 'bool',
74        ),
75        'show_on_portal' => array(
76            'fieldname' => 'zbse_show_on_portal',
77            'format'    => 'bool',
78        ),
79        'show_on_cal'    => array(
80            'fieldname' => 'zbse_show_on_cal',
81            'format'    => 'bool',
82        ),
83        'created'        => array(
84            'fieldname' => 'zbse_created',
85            'format'    => 'uts',
86        ),
87        'lastupdated'    => array(
88            'fieldname' => 'zbse_lastupdated',
89            'format'    => 'uts',
90        ),
91
92    );
93
94    function __construct( $args = array() ) {
95
96        #} =========== LOAD ARGS ==============
97        $defaultArgs = array(
98
99            // 'tag' => false,
100
101        );
102        foreach ( $defaultArgs as $argK => $argV ) {
103            $this->$argK = $argV;
104            if ( is_array( $args ) && isset( $args[ $argK ] ) ) {
105                if ( is_array( $args[ $argK ] ) ) {
106                    $newData = $this->$argK;
107                    if ( ! is_array( $newData ) ) {
108                        $newData = array();
109                    } foreach ( $args[ $argK ] as $subK => $subV ) {
110                        $newData[ $subK ] = $subV;
111                    }$this->$argK = $newData;
112                } else {
113                    $this->$argK = $args[ $argK ]; }
114            }
115        }
116        #} =========== / LOAD ARGS =============
117
118        add_filter( 'jpcrm_listview_filters', array( $this, 'add_listview_filters' ) );
119    }
120
121    /**
122     * Adds items to listview filter using `jpcrm_listview_filters` hook.
123     *
124     * @param array $listview_filters Listview filters.
125     */
126    public function add_listview_filters( $listview_filters ) {
127        global $zbs;
128
129        $listview_filters[ ZBS_TYPE_TASK ]['general']['next30'] = __( 'Next 30 Days', 'zero-bs-crm' );
130        $listview_filters[ ZBS_TYPE_TASK ]['general']['last30'] = __( 'Past 30 Days', 'zero-bs-crm' );
131        $listview_filters[ ZBS_TYPE_TASK ]['general']['next7']  = __( 'Next 7 Days', 'zero-bs-crm' );
132        $listview_filters[ ZBS_TYPE_TASK ]['general']['last7']  = __( 'Past 7 Days', 'zero-bs-crm' );
133
134        // Add statuses if enabled.
135        if ( $zbs->settings->get( 'filtersfromstatus' ) === 1 ) {
136
137            $statuses = array(
138                'incomplete' => __( 'Incomplete', 'zero-bs-crm' ),
139                'completed'  => __( 'Completed', 'zero-bs-crm' ),
140            );
141            foreach ( $statuses as $status_slug => $status_label ) {
142                $listview_filters[ ZBS_TYPE_TASK ]['status'][ 'status_' . $status_slug ] = $status_label;
143            }
144        }
145        return $listview_filters;
146    }
147
148    // ===============================================================================
149    // ===========   EVENT  =======================================================
150
151    // generic get Company (by ID)
152    // Super simplistic wrapper used by edit page etc. (generically called via dal->contacts->getSingle etc.)
153    public function getSingle( $ID = -1 ) {
154
155        return $this->getEvent( $ID );
156    }
157
158    // generic get (by ID list)
159    // Super simplistic wrapper used by MVP Export v3.0
160    public function getIDList( $IDs = false ) {
161
162        return $this->getEvents(
163            array(
164                'inArr'   => $IDs,
165                'page'    => -1,
166                'perPage' => -1,
167            )
168        );
169    }
170
171    // generic get (EVERYTHING)
172    // expect heavy load!
173    public function getAll( $IDs = false ) {
174
175        return $this->getEvents(
176            array(
177                'sortByField' => 'ID',
178                'sortOrder'   => 'ASC',
179                'page'        => -1,
180                'perPage'     => -1,
181            )
182        );
183    }
184
185    // generic get count of (EVERYTHING)
186    public function getFullCount() {
187
188        return $this->getEvents(
189            array(
190                'count'   => true,
191                'page'    => -1,
192                'perPage' => -1,
193            )
194        );
195    }
196
197    /**
198     * returns full event line +- details
199     *
200     * @param int id        event id
201     * @param array                  $args   Associative array of arguments
202     *
203     * @return array event object
204     */
205    public function getEvent( $id = -1, $args = array() ) {
206
207        global $zbs;
208
209        #} =========== LOAD ARGS ==============
210        $defaultArgs = array(
211
212            // if theset wo passed, will search based on these
213            'externalSource'    => false,
214            'externalSourceUID' => false,
215
216            // with what?
217            'withReminders'     => true,
218            'withCustomFields'  => true,
219            'withTags'          => true,
220            'withAssigned'      => true, // return ['contact'] & ['company'] objs if has link
221
222            // permissions
223            'ignoreowner'       => zeroBSCRM_DAL2_ignoreOwnership( ZBS_TYPE_TASK ), // this'll let you not-check the owner of obj
224
225            // returns scalar ID of line
226            'onlyID'            => false,
227
228            'fields'            => false, // false = *, array = fieldnames
229
230        );
231        foreach ( $defaultArgs as $argK => $argV ) {
232            $$argK = $argV;
233            if ( is_array( $args ) && isset( $args[ $argK ] ) ) {
234                if ( is_array( $args[ $argK ] ) ) {
235                    $newData = $$argK;
236                    if ( ! is_array( $newData ) ) {
237                        $newData = array();
238                    } foreach ( $args[ $argK ] as $subK => $subV ) {
239                        $newData[ $subK ] = $subV;
240                    }$$argK = $newData;
241                } else {
242                    $$argK = $args[ $argK ]; }
243            }
244        }
245        #} =========== / LOAD ARGS =============
246
247        #} Check ID
248        $id = (int) $id;
249        if (
250            ( ! empty( $id ) && $id > 0 )
251            ||
252            ( ! empty( $email ) )
253            ||
254            ( ! empty( $externalSource ) && ! empty( $externalSourceUID ) )
255            ) {
256
257            global $ZBSCRM_t, $wpdb;
258            $wheres          = array( 'direct' => array() );
259            $whereStr        = '';
260            $additionalWhere = '';
261            $params          = array();
262            $res             = array();
263            $extraSelect     = '';
264
265            #} ============= PRE-QUERY ============
266
267                #} Custom Fields
268            if ( $withCustomFields && ! $onlyID ) {
269
270                #} Retrieve any cf
271                $custFields = $this->DAL()->getActiveCustomFields( array( 'objtypeid' => ZBS_TYPE_TASK ) );
272
273                #} Cycle through + build into query
274                if ( is_array( $custFields ) ) {
275                    foreach ( $custFields as $cK => $cF ) {
276
277                        // add as subquery
278                        $extraSelect .= ',(SELECT zbscf_objval FROM ' . $ZBSCRM_t['customfields'] . " WHERE zbscf_objid = event.ID AND zbscf_objkey = %s AND zbscf_objtype = %d LIMIT 1) '" . $cK . "'";
279
280                        // add params
281                        $params[] = $cK;
282                        $params[] = ZBS_TYPE_TASK;
283
284                    }
285                }
286            }
287
288                $selector = 'event.*';
289            if ( is_array( $fields ) ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
290                    $selector = '';
291
292                    // always needs id, so add if not present
293                if ( ! in_array( 'ID', $fields ) ) {
294                    $selector = 'event.ID';
295                }
296
297                foreach ( $fields as $f ) {
298                    if ( ! empty( $selector ) ) {
299                        $selector .= ',';
300                    }
301                    $selector .= 'event.' . $f;
302                }
303            } elseif ( $onlyID ) {
304                $selector = 'event.ID';
305            }
306
307            #} ============ / PRE-QUERY ===========
308
309            #} Build query
310            $query = 'SELECT ' . $selector . $extraSelect . ' FROM ' . $ZBSCRM_t['events'] . ' as event';
311            #} ============= WHERE ================
312
313            if ( ! empty( $id ) && $id > 0 ) {
314
315                #} Add ID
316                $wheres['ID'] = array( 'ID', '=', '%d', $id );
317
318            }
319
320            if ( ! empty( $externalSource ) && ! empty( $externalSourceUID ) ) {
321
322                $wheres['extsourcecheck'] = array( 'ID', 'IN', '(SELECT DISTINCT zbss_objid FROM ' . $ZBSCRM_t['externalsources'] . ' WHERE zbss_objtype = ' . ZBS_TYPE_TASK . ' AND zbss_source = %s AND zbss_uid = %s)', array( $externalSource, $externalSourceUID ) );
323
324            }
325
326            #} ============ / WHERE ==============
327
328            #} Build out any WHERE clauses
329            $wheresArr = $this->buildWheres( $wheres, $whereStr, $params );
330            $whereStr  = $wheresArr['where'];
331            $params    = $params + $wheresArr['params'];
332            #} / Build WHERE
333
334            #} Ownership v1.0 - the following adds SITE + TEAM checks, and (optionally), owner
335            $params = array_merge( $params, $this->ownershipQueryVars( $ignoreowner ) ); // merges in any req.
336            $ownQ   = $this->ownershipSQL( $ignoreowner );
337            if ( ! empty( $ownQ ) ) {
338                $additionalWhere = $this->spaceAnd( $additionalWhere ) . $ownQ; // adds str to query
339            }
340            #} / Ownership
341
342            #} Append to sql (this also automatically deals with sortby and paging)
343            $query .= $this->buildWhereStr( $whereStr, $additionalWhere ) . $this->buildSort( 'ID', 'DESC' ) . $this->buildPaging( 0, 1 );
344
345            try {
346
347                #} Prep & run query
348                $queryObj     = $this->prepare( $query, $params );
349                $potentialRes = $wpdb->get_row( $queryObj, OBJECT );
350
351            } catch ( Exception $e ) {
352
353                #} General SQL Err
354                $this->catchSQLError( $e );
355
356            }
357
358            #} Interpret Results (ROW)
359            if ( isset( $potentialRes ) && isset( $potentialRes->ID ) ) {
360
361                #} Has results, tidy + return
362
363                    #} Only ID? return it directly
364                if ( $onlyID ) {
365                    return $potentialRes->ID;
366                }
367
368                    // tidy
369                if ( is_array( $fields ) ) {
370                    // guesses fields based on table col names
371                    $res = $this->lazyTidyGeneric( $potentialRes );
372                } else {
373                    // proper tidy
374                    $res = $this->tidy_event( $potentialRes, $withCustomFields );
375                }
376
377                if ( $withReminders ) {
378
379                    // add all event reminder lines
380                    $res['reminders'] = $this->DAL()->eventreminders->getEventreminders(
381                        array(
382                            'eventID'     => $potentialRes->ID,
383                            'perPage'     => 1000,
384                            'ignoreowner' => zeroBSCRM_DAL2_ignoreOwnership( ZBS_TYPE_TASK ),
385                        )
386                    );
387
388                }
389
390                if ( $withTags ) {
391
392                    // add all tags lines
393                    $res['tags'] = $this->DAL()->getTagsForObjID(
394                        array(
395                            'objtypeid' => ZBS_TYPE_TASK,
396                            'objid'     => $potentialRes->ID,
397                        )
398                    );
399
400                }
401
402                if ( $withAssigned ) {
403
404                    /*
405                        This is for MULTIPLE (e.g. multi contact/companies assigned to an inv)
406
407                        // add all assigned contacts/companies
408                        $res['contacts'] = $this->DAL()->contacts->getContacts(array(
409                            'hasObjTypeLinkedTo'=>ZBS_TYPE_INVOICE,
410                            'hasObjIDLinkedTo'=>$resDataLine->ID,
411                            'perPage'=>-1,
412                            'ignoreowner'=>zeroBSCRM_DAL2_ignoreOwnership(ZBS_TYPE_CONTACT)));
413
414                        $res['companies'] = $this->DAL()->companies->getCompanies(array(
415                            'hasObjTypeLinkedTo'=>ZBS_TYPE_INVOICE,
416                            'hasObjIDLinkedTo'=>$resDataLine->ID,
417                            'perPage'=>-1,
418                            'ignoreowner'=>zeroBSCRM_DAL2_ignoreOwnership(ZBS_TYPE_COMPANY)));
419
420                    .. but we use 1:1, at least now: */
421
422                        // add all assigned contacts/companies
423                        $res['contact'] = $this->DAL()->contacts->getContacts(
424                            array(
425                                'hasObjTypeLinkedTo' => ZBS_TYPE_TASK,
426                                'hasObjIDLinkedTo'   => $potentialRes->ID,
427                                'page'               => 0,
428                                'perPage'            => 1, // FORCES 1
429                                'ignoreowner'        => zeroBSCRM_DAL2_ignoreOwnership( ZBS_TYPE_CONTACT ),
430                            )
431                        );
432
433                        $res['company'] = $this->DAL()->companies->getCompanies(
434                            array(
435                                'hasObjTypeLinkedTo' => ZBS_TYPE_TASK,
436                                'hasObjIDLinkedTo'   => $potentialRes->ID,
437                                'page'               => 0,
438                                'perPage'            => 1, // FORCES 1
439                                'ignoreowner'        => zeroBSCRM_DAL2_ignoreOwnership( ZBS_TYPE_COMPANY ),
440                            )
441                        );
442
443                }
444
445                    return $res;
446
447            }
448        } // / if ID
449
450        return false;
451    }
452
453    /**
454     * returns event detail lines
455     *
456     * @param array $args Associative array of arguments
457     *
458     * @return array of event lines
459     */
460    public function getEvents( $args = array() ) {
461
462        global $zbs;
463
464        #} ============ LOAD ARGS =============
465        $defaultArgs = array(
466
467            // Search/Filtering (leave as false to ignore)
468            'searchPhrase'      => '', // searches which fields?
469            'inArr'             => false,
470            'isTagged'          => false, // 1x INT OR array(1,2,3)
471            'isNotTagged'       => false, // 1x INT OR array(1,2,3)
472            'ownedBy'           => false,
473            'externalSource'    => false, // e.g. paypal
474            'olderThan'         => false, // uts (on CREATED)
475            'newerThan'         => false, // uts (on CREATED)
476            'assignedContact'   => false, // assigned to contact id (int)
477            'assignedCompany'   => false, // assigned to company id (int)
478            'isComplete'        => false, // if true, only returns completed
479            'isIncomplete'      => false, // if true, only returns tasks which are not completed
480
481            // dated
482            'datedBefore'       => false, // uts (on date start)
483            'datedAfter'        => false, // uts (on date start)
484
485            // reminder checks (use either, not both)
486            'hasReminder'       => 0, // (if set as bool) (has any state of reminder attached)
487            'hasUnsentReminder' => 0, // (if set as bool) (has reminder attached which has not been sent)
488
489            // returns
490            'count'             => false,
491            'withReminders'     => true,
492            'withCustomFields'  => true,
493            'withTags'          => false,
494            'withAssigned'      => false, // return ['contact'] & ['company'] objs if has link
495            'withOwner'         => false,
496            'onlyColumns'       => false, // if passed (array('fname','lname')) will return only those columns (overwrites some other 'return' options). NOTE: only works for base fields (not custom fields)
497
498            'sortByField'       => 'ID',
499            'sortOrder'         => 'ASC',
500            'page'              => 0, // this is what page it is (gets * by for limit)
501            'perPage'           => 100,
502            'whereCase'         => 'AND', // DEFAULT = AND
503
504            // permissions
505            'ignoreowner'       => zeroBSCRM_DAL2_ignoreOwnership( ZBS_TYPE_TASK ), // this'll let you not-check the owner of obj
506
507        );
508        foreach ( $defaultArgs as $argK => $argV ) {
509            $$argK = $argV;
510            if ( is_array( $args ) && isset( $args[ $argK ] ) ) {
511                if ( is_array( $args[ $argK ] ) ) {
512                    $newData = $$argK;
513                    if ( ! is_array( $newData ) ) {
514                        $newData = array();
515                    } foreach ( $args[ $argK ] as $subK => $subV ) {
516                        $newData[ $subK ] = $subV;
517                    }$$argK = $newData;
518                } else {
519                    $$argK = $args[ $argK ]; }
520            }
521        }
522        #} =========== / LOAD ARGS =============
523
524        global $ZBSCRM_t, $wpdb, $zbs;
525        $wheres          = array( 'direct' => array() );
526        $whereStr        = '';
527        $additionalWhere = '';
528        $params          = array();
529        $res             = array();
530        $joinQ           = '';
531        $extraSelect     = '';
532
533        #} ============= PRE-QUERY ============
534
535            #} Capitalise this
536            $sortOrder = strtoupper( $sortOrder );
537
538            #} If just count, turn off any extra gumpf
539        if ( $count ) {
540            $withCustomFields = false;
541            $withTags         = false;
542            $withAssigned     = false;
543            $withOwner        = false;
544        }
545
546            #} If onlyColumns, validate
547        if ( $onlyColumns ) {
548
549            #} onlyColumns build out a field arr
550            if ( is_array( $onlyColumns ) && count( $onlyColumns ) > 0 ) {
551
552                $onlyColumnsFieldArr = array();
553                foreach ( $onlyColumns as $col ) {
554
555                    // find db col key from field key (e.g. fname => zbsc_fname)
556                    $dbCol = '';
557                    if ( isset( $this->objectModel[ $col ] ) && isset( $this->objectModel[ $col ]['fieldname'] ) ) {
558                        $dbCol = $this->objectModel[ $col ]['fieldname'];
559                    }
560
561                    if ( ! empty( $dbCol ) ) {
562
563                        $onlyColumnsFieldArr[ $dbCol ] = $col;
564
565                    }
566                }
567            }
568
569            // if legit cols:
570            if ( isset( $onlyColumnsFieldArr ) && is_array( $onlyColumnsFieldArr ) && count( $onlyColumnsFieldArr ) > 0 ) {
571
572                $onlyColumns = true;
573
574                // If onlyColumns, turn off extras
575                $withCustomFields = false;
576                $withTags         = false;
577                $withAssigned     = false;
578                $withOwner        = false;
579
580            } else {
581
582                // deny
583                $onlyColumns = false;
584
585            }
586        }
587
588            #} Custom Fields
589                        // @phan-suppress-next-line PhanImpossibleCondition -- Phan is confused; this var is initialized at the beginning of the function.
590        if ( $withCustomFields ) {
591
592            #} Retrieve any cf
593            $custFields = $this->DAL()->getActiveCustomFields( array( 'objtypeid' => ZBS_TYPE_TASK ) );
594
595            #} Cycle through + build into query
596            if ( is_array( $custFields ) ) {
597                foreach ( $custFields as $cK => $cF ) {
598
599                    // custom field (e.g. 'third name') it'll be passed here as 'third-name'
600                    // ... problem is mysql does not like that :) so we have to chage here:
601                    // in this case we prepend cf's with cf_ and we switch - for _
602                    $cKey = 'cf_' . str_replace( '-', '_', $cK );
603
604                    // we also check the $sortByField in case that's the same cf
605                    if ( $cK == $sortByField ) {
606
607                        // sort by
608                        $sortByField = $cKey;
609
610                        // check if sort needs any CAST (e.g. numeric):
611                        $sortByField = $this->DAL()->build_custom_field_order_by_str( $sortByField, $cF );
612
613                    }
614
615                    // add as subquery
616                    $extraSelect .= ',(SELECT zbscf_objval FROM ' . $ZBSCRM_t['customfields'] . ' WHERE zbscf_objid = event.ID AND zbscf_objkey = %s AND zbscf_objtype = %d) ' . $cKey;
617
618                    // add params
619                    $params[] = $cK;
620                    $params[] = ZBS_TYPE_TASK;
621
622                }
623            }
624        }
625
626        #} ============ / PRE-QUERY ===========
627
628        #} Build query
629        $query = 'SELECT event.*' . $extraSelect . ' FROM ' . $ZBSCRM_t['events'] . ' as event' . $joinQ;
630
631        #} Count override
632        if ( $count ) {
633            $query = 'SELECT COUNT(event.ID) FROM ' . $ZBSCRM_t['events'] . ' as event' . $joinQ;
634        }
635
636        #} onlyColumns override
637        if ( $onlyColumns && is_array( $onlyColumnsFieldArr ) && count( $onlyColumnsFieldArr ) > 0 ) {
638
639            $columnStr = '';
640            foreach ( $onlyColumnsFieldArr as $colDBKey => $colStr ) {
641
642                if ( ! empty( $columnStr ) ) {
643                    $columnStr .= ',';
644                }
645                // this presumes str is db-safe? could do with sanitation?
646                $columnStr .= $colDBKey;
647
648            }
649
650            $query = 'SELECT ' . $columnStr . ' FROM ' . $ZBSCRM_t['events'] . ' as event' . $joinQ;
651
652        }
653
654        #} ============= WHERE ================
655
656            #} Add Search phrase
657        if ( ! empty( $searchPhrase ) ) {
658
659            // search? - ALL THESE COLS should probs have index of FULLTEXT in db?
660            $searchWheres                 = array();
661            $searchWheres['search_title'] = array( 'zbse_title', 'LIKE', '%s', '%' . $searchPhrase . '%' );
662            $searchWheres['search_desc']  = array( 'zbse_desc', 'LIKE', '%s', '%' . $searchPhrase . '%' );
663
664            // 3.0.13 - Added ability to search custom fields (optionally)
665            $customFieldSearch = zeroBSCRM_getSetting( 'customfieldsearch' );
666            if ( $customFieldSearch == 1 ) {
667
668                // simplistic add
669                // NOTE: This IGNORES ownership of custom field lines.
670                $searchWheres['search_customfields'] = array( 'ID', 'IN', '(SELECT zbscf_objid FROM ' . $ZBSCRM_t['customfields'] . ' WHERE zbscf_objval LIKE %s AND zbscf_objtype = ' . ZBS_TYPE_TASK . ')', '%' . $searchPhrase . '%' );
671
672            }
673
674            // This generates a query like 'zbse_fname LIKE %s OR zbse_lname LIKE %s',
675            // which we then need to include as direct subquery (below) in main query :)
676            $searchQueryArr = $this->buildWheres( $searchWheres, '', array(), 'OR', false );
677
678            if ( is_array( $searchQueryArr ) && isset( $searchQueryArr['where'] ) && ! empty( $searchQueryArr['where'] ) ) {
679
680                // add it
681                $wheres['direct'][] = array( '(' . $searchQueryArr['where'] . ')', $searchQueryArr['params'] );
682
683            }
684        }
685
686            #} In array (if inCompany passed, this'll currently overwrite that?! (todo2.5))
687        if ( is_array( $inArr ) && count( $inArr ) > 0 ) {
688
689            // clean for ints
690            $inArrChecked = array();
691            foreach ( $inArr as $x ) {
692                $inArrChecked[] = (int) $x; }
693
694            // add where
695            $wheres['inarray'] = array( 'ID', 'IN', '(' . implode( ',', $inArrChecked ) . ')' );
696
697        }
698
699            #} Owned by
700        if ( ! empty( $ownedBy ) && $ownedBy > 0 ) {
701
702            // would never hard-type this in (would make generic as in buildWPMetaQueryWhere)
703            // but this is only here until MIGRATED to db2 globally
704            // $wheres['incompany'] = array('ID','IN','(SELECT DISTINCT post_id FROM '.$wpdb->prefix."postmeta WHERE meta_key = 'zbs_company' AND meta_value = %d)",$inCompany);
705            // Use obj links now
706            $wheres['ownedBy'] = array( 'zbs_owner', '=', '%s', $ownedBy );
707
708        }
709
710            // External sources
711        if ( ! empty( $externalSource ) ) {
712
713            // NO owernship built into this, check when roll out multi-layered ownsership
714            $wheres['externalsource'] = array( 'ID', 'IN', '(SELECT DISTINCT zbss_objid FROM ' . $ZBSCRM_t['externalsources'] . ' WHERE zbss_objtype = ' . ZBS_TYPE_TASK . ' AND zbss_source = %s)', $externalSource );
715
716        }
717
718            // phpcs:disable WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase,VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
719
720            // quick addition for mike
721            #} olderThan
722        if ( ! empty( $olderThan ) && $olderThan > 0 ) {
723            $wheres['olderThan'] = array( 'zbse_created', '<=', '%d', $olderThan );
724        }
725            #} newerThan
726        if ( ! empty( $newerThan ) && $newerThan > 0 ) {
727            $wheres['newerThan'] = array( 'zbse_created', '>=', '%d', $newerThan );
728        }
729            #} datedBefore
730        if ( ! empty( $datedBefore ) && $datedBefore > 0 ) {
731            $wheres['datedBefore'] = array( 'zbse_start', '<=', '%d', $datedBefore );
732        }
733            #} datedAfter
734        if ( ! empty( $datedAfter ) && $datedAfter > 0 ) {
735            $wheres['datedAfter'] = array( 'zbse_start', '>=', '%d', $datedAfter );
736        }
737
738            // assignedContact + assignedCompany
739        if ( ! empty( $assignedContact ) && $assignedContact > 0 ) {
740            $wheres['assignedContact'] = array( 'ID', 'IN', '(SELECT zbsol_objid_from FROM ' . $ZBSCRM_t['objlinks'] . ' WHERE zbsol_objtype_from = ' . ZBS_TYPE_TASK . ' AND zbsol_objtype_to = ' . ZBS_TYPE_CONTACT . ' AND zbsol_objid_to = %d)', $assignedContact );
741        }
742        if ( ! empty( $assignedCompany ) && $assignedCompany > 0 ) {
743            $wheres['assignedCompany'] = array( 'ID', 'IN', '(SELECT zbsol_objid_from FROM ' . $ZBSCRM_t['objlinks'] . ' WHERE zbsol_objtype_from = ' . ZBS_TYPE_TASK . ' AND zbsol_objtype_to = ' . ZBS_TYPE_COMPANY . ' AND zbsol_objid_to = %d)', $assignedCompany );
744        }
745            // phpcs:enable WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase,VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
746
747            // completed status
748        if ( $isComplete ) {
749            $wheres['status'] = array( 'zbse_complete', '=', '1' );
750        }
751        if ( $isIncomplete ) {
752            $wheres['status'] = array( 'zbse_complete', '<>', '1' );
753        }
754
755            #} Is Tagged (expects 1 tag ID OR array)
756
757                // catch 1 item arr
758        if ( is_array( $isTagged ) && count( $isTagged ) == 1 ) {
759            $isTagged = $isTagged[0];
760        }
761
762        if ( ! empty( $isTagged ) && ! is_array( $isTagged ) && $isTagged > 0 ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
763
764                // add where tagged
765                // 1 int:
766                $wheres['direct'][] = array( '((SELECT COUNT(ID) FROM ' . $ZBSCRM_t['taglinks'] . ' WHERE zbstl_objtype = %d AND zbstl_objid = event.ID AND zbstl_tagid = %d) > 0)', array( ZBS_TYPE_TASK, $isTagged ) );
767
768        } elseif ( is_array( $isTagged ) && count( $isTagged ) > 0 ) {
769
770            // foreach in array :)
771            $tagStr = '';
772            foreach ( $isTagged as $iTag ) {
773                $i = (int) $iTag;
774                if ( $i > 0 ) {
775
776                    if ( $tagStr !== '' ) {
777                        $tagStr . ',';
778                    }
779                    $tagStr .= $i;
780                }
781            }
782            if ( ! empty( $tagStr ) ) {
783
784                $wheres['direct'][] = array( '((SELECT COUNT(ID) FROM ' . $ZBSCRM_t['taglinks'] . ' WHERE zbstl_objtype = %d AND zbstl_objid = event.ID AND zbstl_tagid IN (%s)) > 0)', array( ZBS_TYPE_TASK, $tagStr ) );
785
786            }
787        }
788            #} Is NOT Tagged (expects 1 tag ID OR array)
789
790                // catch 1 item arr
791        if ( is_array( $isNotTagged ) && count( $isNotTagged ) == 1 ) {
792            $isNotTagged = $isNotTagged[0];
793        }
794
795        if ( ! empty( $isNotTagged ) && ! is_array( $isNotTagged ) && $isNotTagged > 0 ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
796
797                // add where tagged
798                // 1 int:
799                $wheres['direct'][] = array( '((SELECT COUNT(ID) FROM ' . $ZBSCRM_t['taglinks'] . ' WHERE zbstl_objtype = %d AND zbstl_objid = event.ID AND zbstl_tagid = %d) = 0)', array( ZBS_TYPE_TASK, $isNotTagged ) );
800
801        } elseif ( is_array( $isNotTagged ) && count( $isNotTagged ) > 0 ) {
802
803            // foreach in array :)
804            $tagStr = '';
805            foreach ( $isNotTagged as $iTag ) {
806                $i = (int) $iTag;
807                if ( $i > 0 ) {
808
809                    if ( $tagStr !== '' ) {
810                        $tagStr . ',';
811                    }
812                    $tagStr .= $i;
813                }
814            }
815            if ( ! empty( $tagStr ) ) {
816
817                $wheres['direct'][] = array( '((SELECT COUNT(ID) FROM ' . $ZBSCRM_t['taglinks'] . ' WHERE zbstl_objtype = %d AND zbstl_objid = event.ID AND zbstl_tagid IN (%s)) = 0)', array( ZBS_TYPE_TASK, $tagStr ) );
818
819            }
820        }
821
822            // reminders
823        if ( $hasReminder === true ) {
824
825            // has a reminder
826            $wheres['direct'][] = array( '((SELECT COUNT(ID) FROM ' . $ZBSCRM_t['eventreminders'] . ' WHERE zbser_event = event.ID) > 0)', array() );
827
828        } elseif ( $hasReminder === false ) {
829
830            // has no reminder
831            $wheres['direct'][] = array( '((SELECT COUNT(ID) FROM ' . $ZBSCRM_t['eventreminders'] . ' WHERE zbser_event = event.ID) = 0)', array() );
832
833        } elseif ( $hasUnsentReminder === true ) {
834
835            // has an unsent reminder
836            $wheres['direct'][] = array( '((SELECT COUNT(ID) FROM ' . $ZBSCRM_t['eventreminders'] . ' WHERE zbser_event = event.ID AND zbser_sent = -1) > 0)', array() );
837
838        } elseif ( $hasUnsentReminder === false ) {
839
840            // has no unsent reminder
841            $wheres['direct'][] = array( '((SELECT COUNT(ID) FROM ' . $ZBSCRM_t['eventreminders'] . ' WHERE zbser_event = event.ID AND zbser_sent = -1) = 0)', array() );
842
843        }
844
845        #} ============ / WHERE ===============
846
847        #} CHECK this + reset to default if faulty
848        if ( ! in_array( $whereCase, array( 'AND', 'OR' ) ) ) {
849            $whereCase = 'AND';
850        }
851
852        #} Build out any WHERE clauses
853        $wheresArr = $this->buildWheres( $wheres, $whereStr, $params, $whereCase );
854        $whereStr  = $wheresArr['where'];
855        $params    = $params + $wheresArr['params'];
856        #} / Build WHERE
857
858        #} Ownership v1.0 - the following adds SITE + TEAM checks, and (optionally), owner
859        $params = array_merge( $params, $this->ownershipQueryVars( $ignoreowner ) ); // merges in any req.
860        $ownQ   = $this->ownershipSQL( $ignoreowner, 'contact' );
861        if ( ! empty( $ownQ ) ) {
862            $additionalWhere = $this->spaceAnd( $additionalWhere ) . $ownQ; // adds str to query
863        }
864        #} / Ownership
865
866        #} Append to sql (this also automatically deals with sortby and paging)
867        $query .= $this->buildWhereStr( $whereStr, $additionalWhere ) . $this->buildSort( $sortByField, $sortOrder ) . $this->buildPaging( $page, $perPage );
868
869        try {
870
871            #} Prep & run query
872            $queryObj = $this->prepare( $query, $params );
873
874            #} Catch count + return if requested
875            if ( $count ) {
876                return $wpdb->get_var( $queryObj );
877            }
878
879            #} else continue..
880            $potentialRes = $wpdb->get_results( $queryObj, OBJECT );
881
882        } catch ( Exception $e ) {
883
884            #} General SQL Err
885            $this->catchSQLError( $e );
886
887        }
888
889        #} Interpret results (Result Set - multi-row)
890        if ( isset( $potentialRes ) && is_array( $potentialRes ) && count( $potentialRes ) > 0 ) {
891
892            #} Has results, tidy + return
893            foreach ( $potentialRes as $resDataLine ) {
894
895                    // using onlyColumns filter?
896                if ( $onlyColumns && is_array( $onlyColumnsFieldArr ) && count( $onlyColumnsFieldArr ) > 0 ) {
897
898                    // only coumns return.
899                    $resArr = array();
900                    foreach ( $onlyColumnsFieldArr as $colDBKey => $colStr ) {
901
902                        if ( isset( $resDataLine->$colDBKey ) ) {
903                            $resArr[ $colStr ] = $resDataLine->$colDBKey;
904                        }
905                    }
906                } else {
907
908                    // tidy
909                    $resArr = $this->tidy_event( $resDataLine, $withCustomFields );
910
911                }
912
913                if ( $withReminders ) {
914
915                    // add all event reminder lines
916                    $resArr['reminders'] = $this->DAL()->eventreminders->getEventreminders(
917                        array(
918                            'eventID'     => $resDataLine->ID,
919                            'perPage'     => 1000,
920                            'ignoreowner' => zeroBSCRM_DAL2_ignoreOwnership( ZBS_TYPE_TASK ),
921                        )
922                    );
923
924                }
925
926                if ( $withTags ) {
927
928                    // add all tags lines
929                    $resArr['tags'] = $this->DAL()->getTagsForObjID(
930                        array(
931                            'objtypeid' => ZBS_TYPE_TASK,
932                            'objid'     => $resDataLine->ID,
933                        )
934                    );
935
936                }
937                if ( $withAssigned ) {
938
939                    /*
940                        This is for MULTIPLE (e.g. multi contact/companies assigned to an inv)
941
942                        // add all assigned contacts/companies
943                        $res['contacts'] = $this->DAL()->contacts->getContacts(array(
944                            'hasObjTypeLinkedTo'=>ZBS_TYPE_INVOICE,
945                            'hasObjIDLinkedTo'=>$resDataLine->ID,
946                            'perPage'=>-1,
947                            'ignoreowner'=>zeroBSCRM_DAL2_ignoreOwnership(ZBS_TYPE_CONTACT)));
948
949                        $res['companies'] = $this->DAL()->companies->getCompanies(array(
950                            'hasObjTypeLinkedTo'=>ZBS_TYPE_INVOICE,
951                            'hasObjIDLinkedTo'=>$resDataLine->ID,
952                            'perPage'=>-1,
953                            'ignoreowner'=>zeroBSCRM_DAL2_ignoreOwnership(ZBS_TYPE_COMPANY)));
954
955                    .. but we use 1:1, at least now: */
956
957                        // add all assigned contacts/companies
958                        $resArr['contact'] = $this->DAL()->contacts->getContacts(
959                            array(
960                                'hasObjTypeLinkedTo' => ZBS_TYPE_TASK,
961                                'hasObjIDLinkedTo'   => $resDataLine->ID,
962                                'page'               => 0,
963                                'perPage'            => 1, // FORCES 1
964                                'ignoreowner'        => zeroBSCRM_DAL2_ignoreOwnership( ZBS_TYPE_CONTACT ),
965                            )
966                        );
967
968                        $resArr['company'] = $this->DAL()->companies->getCompanies(
969                            array(
970                                'hasObjTypeLinkedTo' => ZBS_TYPE_TASK,
971                                'hasObjIDLinkedTo'   => $resDataLine->ID,
972                                'page'               => 0,
973                                'perPage'            => 1, // FORCES 1
974                                'ignoreowner'        => zeroBSCRM_DAL2_ignoreOwnership( ZBS_TYPE_COMPANY ),
975                            )
976                        );
977
978                }
979
980                    #} With Assigned?
981                if ( $withOwner ) {
982
983                    $resArr['owner'] = zeroBS_getOwner( $resDataLine->ID, true, ZBS_TYPE_TASK, $resDataLine->zbs_owner );
984
985                }
986
987                    $res[] = $resArr;
988
989            }
990        }
991
992        return $res;
993    }
994
995    /**
996     * Returns a count of events (owned)
997     * .. inc by status
998     *
999     * @return int count
1000     */
1001    public function getEventCount( $args = array() ) {
1002
1003        #} ============ LOAD ARGS =============
1004        $defaultArgs = array(
1005
1006            // Search/Filtering (leave as false to ignore)
1007
1008            // permissions
1009            'ignoreowner' => true, // this'll let you not-check the owner of obj
1010
1011        );
1012        foreach ( $defaultArgs as $argK => $argV ) {
1013            $$argK = $argV;
1014            if ( is_array( $args ) && isset( $args[ $argK ] ) ) {
1015                if ( is_array( $args[ $argK ] ) ) {
1016                    $newData = $$argK;
1017                    if ( ! is_array( $newData ) ) {
1018                        $newData = array();
1019                    } foreach ( $args[ $argK ] as $subK => $subV ) {
1020                        $newData[ $subK ] = $subV;
1021                    }$$argK = $newData;
1022                } else {
1023                    $$argK = $args[ $argK ]; }
1024            }
1025        }
1026        #} =========== / LOAD ARGS =============
1027
1028        $whereArr = array();
1029
1030        return $this->DAL()->getFieldByWHERE(
1031            array(
1032                'objtype'     => ZBS_TYPE_TASK,
1033                'colname'     => 'COUNT(ID)',
1034                'where'       => $whereArr,
1035                'ignoreowner' => $ignoreowner,
1036            )
1037        );
1038    }
1039
1040    /**
1041     * adds or updates a event object
1042     *
1043     * @param array $args Associative array of arguments
1044     *              id (if update), owner, data (array of field data)
1045     *
1046     * @return int line ID
1047     */
1048    public function addUpdateEvent( $args = array() ) {
1049
1050        global $ZBSCRM_t, $wpdb, $zbs;
1051
1052        #} Retrieve any cf
1053        $customFields = $this->DAL()->getActiveCustomFields( array( 'objtypeid' => ZBS_TYPE_TASK ) );
1054
1055        #} ============ LOAD ARGS =============
1056        $defaultArgs = array(
1057
1058            'id'                   => -1,
1059            'owner'                => -1,
1060
1061            // fields (directly)
1062            'data'                 => array(
1063
1064                'title'           => '',
1065                'desc'            => '',
1066                'start'           => '',
1067                'end'             => '',
1068                'complete'        => '',
1069                'show_on_portal'  => '',
1070                'show_on_cal'     => true,
1071
1072                // obj links:
1073                'contacts'        => false, // array of id's
1074                'companies'       => false, // array of id's
1075
1076                // reminders:
1077                'reminders'       => false,
1078                // will be an array of eventreminder lines (as per matching eventreminder database model)
1079                // note:    if no change desired, pass "false"
1080                // if removal of all/change, pass array
1081
1082                // Note Custom fields may be passed here, but will not have defaults so check isset()
1083
1084                // tags
1085                'tags'            => -1, // pass an array of tag ids or tag strings
1086                'tag_mode'        => 'replace', // replace|append|remove
1087
1088                'externalSources' => -1, // if this is an array(array('source'=>src,'uid'=>uid),multiple()) it'll add :)
1089
1090                // allow this to be set for MS sync etc.
1091                'created'         => -1,
1092                'lastupdated'     => '',
1093
1094            ),
1095
1096            'limitedFields'        => -1, // if this is set it OVERRIDES data (allowing you to set specific fields + leave rest in tact)
1097            // ^^ will look like: array(array('key'=>x,'val'=>y,'type'=>'%s'))
1098
1099            // this function as DAL1 func did.
1100            'extraMeta'            => -1,
1101            'automatorPassthrough' => -1,
1102
1103            'silentInsert'         => false, // this was for init Migration - it KILLS all IA for newEvent (because is migrating, not creating new :) this was -1 before
1104
1105            'do_not_update_blanks' => false, // this allows you to not update fields if blank (same as fieldoverride for extsource -> in)
1106
1107        );
1108        foreach ( $defaultArgs as $argK => $argV ) {
1109            $$argK = $argV;
1110            if ( is_array( $args ) && isset( $args[ $argK ] ) ) {
1111                if ( is_array( $args[ $argK ] ) ) {
1112                    $newData = $$argK;
1113                    if ( ! is_array( $newData ) ) {
1114                        $newData = array();
1115                    } foreach ( $args[ $argK ] as $subK => $subV ) {
1116                        $newData[ $subK ] = $subV;
1117                    }$$argK = $newData;
1118                } else {
1119                    $$argK = $args[ $argK ]; }
1120            }
1121        }
1122
1123            // Needs this to grab custom fields (if passed) too :)
1124        if ( is_array( $customFields ) ) {
1125            foreach ( $customFields as $cK => $cF ) {
1126
1127                // only for data, limited fields below
1128                if ( is_array( $data ) ) {
1129
1130                    if ( isset( $args['data'][ $cK ] ) ) {
1131                        $data[ $cK ] = $args['data'][ $cK ];
1132                    }
1133                }
1134            }
1135        }
1136
1137            // this takes limited fields + checks through for custom fields present
1138            // (either as key zbse_source or source, for example)
1139            // then switches them into the $data array, for separate update
1140            // where this'll fall over is if NO normal contact data is sent to update, just custom fields
1141        if ( is_array( $limitedFields ) && is_array( $customFields ) ) {
1142
1143                // $customFieldKeys = array_keys($customFields);
1144                $newLimitedFields = array();
1145
1146                // cycle through
1147            foreach ( $limitedFields as $field ) {
1148
1149                // some weird case where getting empties, so added check
1150                if ( isset( $field['key'] ) && ! empty( $field['key'] ) ) {
1151
1152                    $dePrefixed = ''; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
1153                    if ( str_starts_with( $field['key'], 'zbse_' ) ) {
1154                        $dePrefixed = substr( $field['key'], strlen( 'zbse_' ) ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
1155                    }
1156
1157                    if ( isset( $customFields[ $field['key'] ] ) ) {
1158
1159                        // is custom, move to data
1160                        $data[ $field['key'] ] = $field['val'];
1161
1162                    } elseif ( ! empty( $dePrefixed ) && isset( $customFields[ $dePrefixed ] ) ) {
1163
1164                        // is custom, move to data
1165                        $data[ $dePrefixed ] = $field['val'];
1166
1167                    } else {
1168
1169                        // add it to limitedFields (it's not dealt with post-update)
1170                        $newLimitedFields[] = $field;
1171                    }
1172                }
1173            }
1174
1175                // move this back in
1176                $limitedFields = $newLimitedFields;
1177                unset( $newLimitedFields );
1178
1179        }
1180
1181            #} =========== / LOAD ARGS ============
1182
1183            #} ========== CHECK FIELDS ============
1184
1185            $id = (int) $id;
1186
1187            // here we check that the potential owner CAN even own
1188        if ( $owner > 0 && ! user_can( $owner, 'admin_zerobs_usr' ) ) {
1189            $owner = -1;
1190        }
1191
1192            // if owner = -1, add current
1193        if ( ! isset( $owner ) || $owner === -1 ) {
1194            $owner = zeroBSCRM_user(); }
1195
1196        if ( is_array( $limitedFields ) ) {
1197
1198            // LIMITED UPDATE (only a few fields.)
1199            if ( ! is_array( $limitedFields ) || count( $limitedFields ) <= 0 ) {
1200                return false;
1201            }
1202            // REQ. ID too (can only update)
1203            if ( empty( $id ) || $id <= 0 ) {
1204                return false;
1205            }
1206        } else {
1207
1208            // NORMAL, FULL UPDATE
1209
1210        }
1211
1212            #} If no status, and default is specified in settings, add that in :)
1213            /*
1214            if (is_null($data['status']) || !isset($data['status']) || empty($data['status'])){
1215
1216                // Default status for obj? -> this one gets for contacts -> $zbsCustomerMeta['status'] = zeroBSCRM_getSetting('defaultstatus');
1217
1218            }
1219            */
1220
1221            #} ========= / CHECK FIELDS ===========
1222
1223            #} ========= OVERRIDE SETTING (Deny blank overrides) ===========
1224
1225            // this only functions if externalsource is set (e.g. api/form, etc.)
1226        if ( isset( $data['externalSources'] ) && is_array( $data['externalSources'] ) && count( $data['externalSources'] ) > 0 ) {
1227            if ( zeroBSCRM_getSetting( 'fieldoverride' ) == '1' ) {
1228
1229                $do_not_update_blanks = true;
1230
1231            }
1232        }
1233
1234            // either ext source + setting, or set by the func call
1235        if ( $do_not_update_blanks ) {
1236
1237                // this setting says 'don't override filled-out data with blanks'
1238                // so here we check through any passed blanks + convert to limitedFields
1239                // only matters if $id is set (there is somt to update not add
1240            if ( isset( $id ) && ! empty( $id ) && $id > 0 ) {
1241
1242                // get data to copy over (for now, this is required to remove 'fullname' etc.)
1243                $dbData = $this->db_ready_event( $data );
1244
1245                $origData    = $data; // $data = array();
1246                $limitedData = array(); // array(array('key'=>'zbse_x','val'=>y,'type'=>'%s'))
1247
1248                // cycle through + translate into limitedFields (removing any blanks, or arrays (e.g. externalSources))
1249                // we also have to remake a 'faux' data (removing blanks for tags etc.) for the post-update updates
1250                foreach ( $dbData as $k => $v ) {
1251
1252                    $intV = (int) $v;
1253
1254                    // only add if valuenot empty
1255                    if ( ! is_array( $v ) && ! empty( $v ) && $v != '' && $v !== 0 && $v !== -1 && $intV !== -1 ) {
1256
1257                        // add to update arr
1258                        $limitedData[] = array(
1259                            'key'  => 'zbse_' . $k, // we have to add zbse_ here because translating from data -> limited fields
1260                            'val'  => $v,
1261                            'type' => $this->getTypeStr( 'zbse_' . $k ),
1262                        );
1263
1264                        // add to remade $data for post-update updates
1265                        $data[ $k ] = $v;
1266
1267                    }
1268                }
1269
1270                // copy over
1271                $limitedFields = $limitedData;
1272
1273            } // / if ID
1274
1275        } // / if do_not_update_blanks
1276
1277            #} ========= / OVERRIDE SETTING (Deny blank overrides) ===========
1278
1279            #} ========= BUILD DATA ===========
1280
1281            $update = false;
1282        $dataArr    = array();
1283        $typeArr    = array();
1284
1285        if ( is_array( $limitedFields ) ) {
1286
1287            // LIMITED FIELDS
1288            $update = true;
1289
1290            // cycle through
1291            foreach ( $limitedFields as $field ) {
1292
1293                // some weird case where getting empties, so added check
1294                if ( ! empty( $field['key'] ) ) {
1295                    $dataArr[ $field['key'] ] = $field['val'];
1296                    $typeArr[]                = $field['type'];
1297                }
1298            }
1299
1300            // add update time
1301            if ( ! isset( $dataArr['zbse_lastupdated'] ) ) {
1302                $dataArr['zbse_lastupdated'] = time();
1303                $typeArr[]                   = '%d'; }
1304        } else {
1305
1306                // contacts - avoid dupes
1307            if ( isset( $data['contacts'] ) && is_array( $data['contacts'] ) ) {
1308
1309                $coArr = array();
1310                foreach ( $data['contacts'] as $c ) {
1311                    $cI = (int) $c;
1312                    if ( $cI > 0 && ! in_array( $cI, $coArr ) ) {
1313                        $coArr[] = $cI;
1314                    }
1315                }
1316
1317                // reset the main
1318                if ( count( $coArr ) > 0 ) {
1319                    $data['contacts'] = $coArr;
1320                } else {
1321                    $data['contacts'] = 'unset';
1322                }
1323                unset( $coArr );
1324
1325            }
1326
1327                // companies - avoid dupes
1328            if ( isset( $data['companies'] ) && is_array( $data['companies'] ) ) {
1329
1330                $coArr = array();
1331                foreach ( $data['companies'] as $c ) {
1332                    $cI = (int) $c;
1333                    if ( $cI > 0 && ! in_array( $cI, $coArr ) ) {
1334                        $coArr[] = $cI;
1335                    }
1336                }
1337
1338                // reset the main
1339                if ( count( $coArr ) > 0 ) {
1340                    $data['companies'] = $coArr;
1341                } else {
1342                    $data['companies'] = 'unset';
1343                }
1344                unset( $coArr );
1345
1346            }
1347
1348                // FULL UPDATE/INSERT
1349
1350                    // UPDATE
1351                    $dataArr = array(
1352
1353                        // ownership
1354                        // no need to update these (as of yet) - can't move teams etc.
1355                        // 'zbs_site' => zeroBSCRM_installSite(),
1356                        // 'zbs_team' => zeroBSCRM_installTeam(),
1357                        // 'zbs_owner' => $owner,
1358
1359                        'zbse_title'          => $data['title'],
1360                        'zbse_desc'           => $data['desc'],
1361                        'zbse_start'          => $data['start'],
1362                        'zbse_end'            => $data['end'],
1363                        'zbse_complete'       => $data['complete'],
1364                        'zbse_show_on_portal' => $data['show_on_portal'],
1365                        'zbse_show_on_cal'    => $data['show_on_cal'],
1366                        'zbse_lastupdated'    => time(),
1367
1368                    );
1369
1370                    $typeArr = array( // field data types
1371                                // '%d',  // site
1372                                // '%d',  // team
1373                                // '%d',  // owner
1374
1375                        '%s',
1376                        '%s',
1377                        '%d',
1378                        '%d',
1379                        '%s',
1380                        '%d',
1381                        '%d',
1382                        '%d',
1383
1384                    );
1385
1386                    if ( ! empty( $id ) && $id > 0 ) {
1387
1388                        // is update
1389                        $update = true;
1390
1391                        // events can be re-assigned
1392                        if ( isset( $owner ) && ! empty( $owner ) && $owner !== -1 ) {
1393
1394                            $dataArr['zbs_owner'] = $owner;
1395                            $typeArr[]            = '%d';
1396
1397                        }
1398                    } else {
1399
1400                        // INSERT (get's few extra :D)
1401                        $update               = false;
1402                        $dataArr['zbs_site']  = zeroBSCRM_site();
1403                        $typeArr[]            = '%d';
1404                        $dataArr['zbs_team']  = zeroBSCRM_team();
1405                        $typeArr[]            = '%d';
1406                        $dataArr['zbs_owner'] = $owner;
1407                        $typeArr[]            = '%d';
1408                        if ( isset( $data['created'] ) && ! empty( $data['created'] ) && $data['created'] !== -1 ) {
1409                            $dataArr['zbse_created'] = $data['created'];
1410                            $typeArr[]               = '%d';
1411                        } else {
1412                            $dataArr['zbse_created'] = time();
1413                            $typeArr[]               = '%d';
1414                        }
1415                    }
1416        }
1417
1418            #} ========= / BUILD DATA ===========
1419
1420            #} ============================================================
1421            #} ========= CHECK force_uniques & not_empty & max_len ========
1422
1423            // if we're passing limitedFields we skip these, for now
1424            // #v3.1 - would make sense to unique/nonempty check just the limited fields. #gh-145
1425        if ( ! is_array( $limitedFields ) ) {
1426
1427            // verify uniques
1428            if ( ! $this->verifyUniqueValues( $data, $id ) ) {
1429                return false; // / fails unique field verify
1430            }
1431
1432            // verify not_empty
1433            if ( ! $this->verifyNonEmptyValues( $data ) ) {
1434                return false; // / fails empty field verify
1435            }
1436        }
1437
1438            // whatever we do we check for max_len breaches and abbreviate to avoid wpdb rejections
1439            $dataArr = $this->wpdbChecks( $dataArr );
1440
1441            #} ========= / CHECK force_uniques & not_empty ================
1442            #} ============================================================
1443
1444            #} Check if ID present
1445        if ( $update ) {
1446
1447            #} Attempt update
1448            if ( $wpdb->update(
1449                $ZBSCRM_t['events'],
1450                $dataArr,
1451                array( // where
1452                    'ID' => $id,
1453                ),
1454                $typeArr,
1455                array( // where data types
1456                    '%d',
1457                )
1458            ) !== false ) {
1459
1460                        // defaults for IA below
1461                        $approvedExternalSource = '';
1462                        $againstIDs             = array(
1463                            'contacts'  => array(),
1464                            'companies' => array(),
1465                        );
1466
1467                        // if passing limitedFields instead of data, we ignore the following
1468                            // this doesn't work, because data is in args default as arr
1469                            // if (isset($data) && is_array($data)){
1470                            // so...
1471                        if ( ! isset( $limitedFields ) || ! is_array( $limitedFields ) || $limitedFields == -1 ) {
1472
1473                            // OBJ LINKS - to contacts/companies
1474                            $this->addUpdateObjectLinks( $id, $data['contacts'], ZBS_TYPE_CONTACT );
1475                            $this->addUpdateObjectLinks( $id, $data['companies'], ZBS_TYPE_COMPANY );
1476                            // IA also gets 'againstid' historically, but we'll pass as 'against id's'
1477                            $againstIDs = array(
1478                                'contacts'  => $data['contacts'],
1479                                'companies' => $data['companies'],
1480                            );
1481
1482                            // Event Reminders ====
1483
1484                            // event reminder work?
1485                            if ( isset( $data['reminders'] ) && is_array( $data['reminders'] ) ) {
1486
1487                                // if array passed, update, even if removing
1488                                if ( count( $data['reminders'] ) > 0 ) {
1489
1490                                    // passed, for now this is BRUTAL and just clears old ones + readds
1491                                    // once live, discuss how to refactor to be less brutal.
1492                                    // for now will be fine if you LOAD reminders, edit, addUpdate, -> don't recreate them then rejam in expecting it to know how to deal with :)
1493                                    // (in which case reminders sent already might get resent, but that's if not following this note ^)
1494
1495                                    // delete all reminders
1496                                    $this->DAL()->eventreminders->deleteEventRemindersForEvent( array( 'eventID' => $id ) );
1497
1498                                    // addupdate each
1499                                    foreach ( $data['reminders'] as $reminder ) {
1500
1501                                            // no point in this:
1502                                            // slight rejig of passed so works cleanly with data array style
1503                                            // $reminderID = false; if (isset($reminder['ID'])) $reminderID = $reminder['ID'];
1504                                            $reminderID = false;
1505
1506                                            // if 'event' isn't set, add this event id
1507                                            // actually hard set. if (!isset($reminder['event']))
1508                                            $reminder['event'] = $id;
1509
1510                                            $this->DAL()->eventreminders->addUpdateEventreminder(
1511                                                array(
1512                                                    'id'   => $reminderID,
1513                                                    'data' => $reminder,
1514                                                )
1515                                            );
1516
1517                                    }
1518                                } else {
1519
1520                                                            // delete all reminders
1521                                                            $this->DAL()->eventreminders->deleteEventRemindersForEvent( array( 'eventID' => $id ) );
1522
1523                                }
1524                            }
1525
1526                            // / Event Reminders ====
1527
1528                            // tags
1529                            if ( isset( $data['tags'] ) && is_array( $data['tags'] ) ) {
1530
1531                                $this->addUpdateEventTags(
1532                                    array(
1533                                        'id'        => $id,
1534                                        'tag_input' => $data['tags'],
1535                                        'mode'      => $data['tag_mode'],
1536                                    )
1537                                );
1538
1539                            }
1540
1541                            // externalSources
1542                            $approvedExternalSource = $this->DAL()->addUpdateExternalSources(
1543                                array(
1544                                    'obj_id'           => $id,
1545                                    'obj_type_id'      => ZBS_TYPE_TASK,
1546                                    'external_sources' => isset( $data['externalSources'] ) ? $data['externalSources'] : array(),
1547                                )
1548                            ); // for IA below
1549
1550                            // Custom fields?
1551
1552                                #} Cycle through + add/update if set
1553                            if ( is_array( $customFields ) ) {
1554                                foreach ( $customFields as $cK => $cF ) {
1555
1556                                    // any?
1557                                    if ( isset( $data[ $cK ] ) ) {
1558
1559                                        // add update
1560                                        $cfID = $this->DAL()->addUpdateCustomField(
1561                                            array(
1562                                                'data' => array(
1563                                                    'objtype' => ZBS_TYPE_TASK,
1564                                                    'objid'   => $id,
1565                                                    'objkey'  => $cK,
1566                                                    'objval'  => $data[ $cK ],
1567                                                ),
1568                                            )
1569                                        );
1570
1571                                    }
1572                                }
1573                            }
1574
1575                            // / Custom Fields
1576
1577                        } // / if $data
1578
1579                        #} Any extra meta keyval pairs?
1580                        // BRUTALLY updates (no checking)
1581                        $confirmedExtraMeta = false;
1582                        if ( is_array( $extraMeta ) ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable,WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
1583
1584                                $confirmedExtraMeta = array();
1585
1586                            foreach ( $extraMeta as $k => $v ) {
1587
1588                                #} This won't fix stupid keys, just catch basic fails...
1589                                $cleanKey = strtolower( str_replace( ' ', '_', $k ) );
1590
1591                                #} Brutal update
1592                                // update_post_meta($postID, 'zbs_customer_extra_'.$cleanKey, $v);
1593                                $this->DAL()->updateMeta( ZBS_TYPE_TASK, $id, 'extra_' . $cleanKey, $v );
1594
1595                                #} Add it to this, which passes to IA
1596                                $confirmedExtraMeta[ $cleanKey ] = $v;
1597
1598                            }
1599                        }
1600
1601                        #} INTERNAL AUTOMATOR
1602                        #} &
1603                        #} FALLBACKS
1604                        // UPDATING CONTACT
1605                        if ( ! $silentInsert ) {
1606
1607                            // catch dirty flag (update of status) (note, after update_post_meta - as separate)
1608                            // if (isset($_POST['zbse_status_dirtyflag']) && $_POST['zbse_status_dirtyflag'] == "1"){
1609                            // actually here, it's set above
1610                            /*
1611                                WH not sure if used for this obj:
1612                            if (isset($statusChange) && is_array($statusChange)){
1613
1614                            // status has changed
1615
1616                            // IA
1617                            zeroBSCRM_FireInternalAutomator('event.status.update',array(
1618                                'id'=>$id,
1619                                'againstid' => $id,
1620                                'userMeta'=> $dataArr,
1621                                'from' => $statusChange['from'],
1622                                'to' => $statusChange['to']
1623                                ));
1624
1625                            } */
1626
1627                            // IA General event update (2.87+)
1628                            zeroBSCRM_FireInternalAutomator(
1629                                'event.update',
1630                                array(
1631                                    'id'                   => $id,
1632                                    'data'                 => $data,
1633                                    'extsource'            => $approvedExternalSource,
1634                                    'againstids'           => $againstIDs,
1635                                    'automatorpassthrough' => $automatorPassthrough, #} This passes through any custom log titles or whatever into the Internal automator recipe.
1636                                    'extraMeta'            => $confirmedExtraMeta, #} This is the "extraMeta" passed (as saved)
1637                                )
1638                            );
1639
1640                        }
1641
1642                        // Successfully updated - Return id
1643                        return $id;
1644
1645            } else {
1646
1647                $msg = __( 'DB Update Failed', 'zero-bs-crm' );
1648                $zbs->DAL->addError( 302, $this->objectType, $msg, $dataArr );
1649
1650                // FAILED update
1651                return false;
1652
1653            }
1654        } else {
1655
1656                #} No ID - must be an INSERT
1657            if ( $wpdb->insert(
1658                $ZBSCRM_t['events'],
1659                $dataArr,
1660                $typeArr
1661            ) > 0 ) {
1662
1663                #} Successfully inserted, lets return new ID
1664                $newID = $wpdb->insert_id;
1665
1666                // defaults for IA below
1667                $approvedExternalSource = '';
1668                $againstIDs             = array(
1669                    'contacts'  => array(),
1670                    'companies' => array(),
1671                );
1672
1673                // Event Reminders ====
1674
1675                // event reminder work?
1676                if ( isset( $data['reminders'] ) && is_array( $data['reminders'] ) ) {
1677
1678                    // if array passed, update, even if removing
1679                    if ( count( $data['reminders'] ) > 0 ) {
1680
1681                        // passed, for now this is BRUTAL and just clears old ones + readds
1682                        // once live, discuss how to refactor to be less brutal.
1683                        // for now will be fine if you LOAD reminders, edit, addUpdate, -> don't recreate them then rejam in expecting it to know how to deal with :)
1684                        // (in which case reminders sent already might get resent, but that's if not following this note ^)
1685
1686                            // delete all reminders
1687                            $this->DAL()->eventreminders->deleteEventRemindersForEvent( array( 'eventID' => $newID ) );
1688
1689                            // addupdate each
1690                        foreach ( $data['reminders'] as $reminder ) {
1691
1692                            // no point in this:
1693                            // slight rejig of passed so works cleanly with data array style
1694                            // $reminderID = false; if (isset($reminder['ID'])) $reminderID = $reminder['ID'];
1695                            $reminderID = false;
1696
1697                            // if 'event' isn't set, add this event id
1698                            // actually hard set.. if (!isset($reminder['event']))
1699                            $reminder['event'] = $newID;
1700
1701                            $this->DAL()->eventreminders->addUpdateEventreminder(
1702                                array(
1703                                    'id'   => $reminderID,
1704                                    'data' => $reminder,
1705                                )
1706                            );
1707
1708                        }
1709                    } else {
1710
1711                            // delete all reminders
1712                            $this->DAL()->eventreminders->deleteEventRemindersForEvent( array( 'eventID' => $newID ) );
1713
1714                    }
1715                }
1716
1717                // / Event Reminders ====
1718
1719                // OBJ LINKS - to contacts/companies
1720                $this->addUpdateObjectLinks( $newID, $data['contacts'], ZBS_TYPE_CONTACT );
1721                $this->addUpdateObjectLinks( $newID, $data['companies'], ZBS_TYPE_COMPANY );
1722                // IA also gets 'againstid' historically, but we'll pass as 'against id's'
1723                $againstIDs = array(
1724                    'contacts'  => $data['contacts'],
1725                    'companies' => $data['companies'],
1726                );
1727
1728                // tags
1729                if ( isset( $data['tags'] ) && is_array( $data['tags'] ) ) {
1730
1731                    $this->addUpdateEventTags(
1732                        array(
1733                            'id'        => $newID,
1734                            'tag_input' => $data['tags'],
1735                            'mode'      => $data['tag_mode'],
1736                        )
1737                    );
1738
1739                }
1740
1741                // externalSources
1742                $approvedExternalSource = $this->DAL()->addUpdateExternalSources(
1743                    array(
1744                        'obj_id'           => $newID,
1745                        'obj_type_id'      => ZBS_TYPE_TASK,
1746                        'external_sources' => isset( $data['externalSources'] ) ? $data['externalSources'] : array(),
1747                    )
1748                ); // for IA below
1749
1750                    // Custom fields?
1751
1752                    #} Cycle through + add/update if set
1753                if ( is_array( $customFields ) ) {
1754                    foreach ( $customFields as $cK => $cF ) {
1755
1756                        // any?
1757                        if ( isset( $data[ $cK ] ) ) {
1758
1759                            // add update
1760                            $cfID = $this->DAL()->addUpdateCustomField(
1761                                array(
1762                                    'data' => array(
1763                                        'objtype' => ZBS_TYPE_TASK,
1764                                        'objid'   => $newID,
1765                                        'objkey'  => $cK,
1766                                        'objval'  => $data[ $cK ],
1767                                    ),
1768                                )
1769                            );
1770
1771                        }
1772                    }
1773                }
1774
1775                    // / Custom Fields
1776
1777                    #} Any extra meta keyval pairs?
1778                    // BRUTALLY updates (no checking)
1779                    $confirmedExtraMeta = false;
1780                if ( is_array( $extraMeta ) ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable,WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
1781
1782                    $confirmedExtraMeta = array();
1783
1784                    foreach ( $extraMeta as $k => $v ) {
1785
1786                        #} This won't fix stupid keys, just catch basic fails...
1787                        $cleanKey = strtolower( str_replace( ' ', '_', $k ) );
1788
1789                        #} Brutal update
1790                        // update_post_meta($postID, 'zbs_customer_extra_'.$cleanKey, $v);
1791                        $this->DAL()->updateMeta( ZBS_TYPE_TASK, $newID, 'extra_' . $cleanKey, $v );
1792
1793                        #} Add it to this, which passes to IA
1794                        $confirmedExtraMeta[ $cleanKey ] = $v;
1795
1796                    }
1797                }
1798
1799                    #} INTERNAL AUTOMATOR
1800                    #} &
1801                    #} FALLBACKS
1802                    // NEW CONTACT
1803                if ( ! $silentInsert ) {
1804
1805                    #} Add to automator
1806                    zeroBSCRM_FireInternalAutomator(
1807                        'event.new',
1808                        array(
1809                            'id'                   => $newID,
1810                            'data'                 => $data,
1811                            'extsource'            => $approvedExternalSource,
1812                            'againstids'           => $againstIDs,
1813                            'automatorpassthrough' => $automatorPassthrough, #} This passes through any custom log titles or whatever into the Internal automator recipe.
1814                            'extraMeta'            => $confirmedExtraMeta, #} This is the "extraMeta" passed (as saved)
1815                        )
1816                    );
1817
1818                }
1819
1820                    return $newID;
1821
1822            } else {
1823
1824                $msg = __( 'DB Insert Failed', 'zero-bs-crm' );
1825                $zbs->DAL->addError( 303, $this->objectType, $msg, $dataArr );
1826
1827                #} Failed to Insert
1828                return false;
1829
1830            }
1831        }
1832
1833            return false;
1834    }
1835
1836    /**
1837     * adds or updates a event's tags
1838     * ... this is really just a wrapper for addUpdateObjectTags
1839     *
1840     * @param array $args Associative array of arguments
1841     *              id (if update), owner, data (array of field data)
1842     *
1843     * @return int line ID
1844     */
1845    public function addUpdateEventTags( $args = array() ) {
1846
1847        global $ZBSCRM_t, $wpdb;
1848
1849        #} ============ LOAD ARGS =============
1850        $defaultArgs = array(
1851
1852            'id'        => -1,
1853
1854            // generic pass-through (array of tag strings or tag IDs):
1855            'tag_input' => -1,
1856
1857            // or either specific:
1858            'tagIDs'    => -1,
1859            'tags'      => -1,
1860
1861            'mode'      => 'append',
1862
1863        );
1864        foreach ( $defaultArgs as $argK => $argV ) {
1865            $$argK = $argV;
1866            if ( is_array( $args ) && isset( $args[ $argK ] ) ) {
1867                if ( is_array( $args[ $argK ] ) ) {
1868                    $newData = $$argK;
1869                    if ( ! is_array( $newData ) ) {
1870                        $newData = array();
1871                    } foreach ( $args[ $argK ] as $subK => $subV ) {
1872                        $newData[ $subK ] = $subV;
1873                    }$$argK = $newData;
1874                } else {
1875                    $$argK = $args[ $argK ]; }
1876            }
1877        }
1878        #} =========== / LOAD ARGS ============
1879
1880        #} ========== CHECK FIELDS ============
1881
1882            // check id
1883            $id = (int) $id;
1884        if ( empty( $id ) || $id <= 0 ) {
1885            return false;
1886        }
1887
1888        #} ========= / CHECK FIELDS ===========
1889
1890        return $this->DAL()->addUpdateObjectTags(
1891            array(
1892                'objtype'   => ZBS_TYPE_TASK,
1893                'objid'     => $id,
1894                'tag_input' => $tag_input,
1895                'tags'      => $tags,
1896                'tagIDs'    => $tagIDs,
1897                'mode'      => $mode,
1898            )
1899        );
1900    }
1901
1902    /**
1903     * mark event as comoplete
1904     *
1905     * @param int id Event ID
1906     * @param int (Bool) completion status -1 or 1
1907     *
1908     * @return bool
1909     */
1910    public function setEventCompleteness( $id = -1, $status = -1 ) {
1911
1912        global $zbs;
1913
1914        $id = (int) $id;
1915
1916        if ( $id > 0 ) {
1917
1918            return $this->addUpdateEvent(
1919                array(
1920                    'id'            => $id,
1921                    'limitedFields' => array(
1922                        array(
1923                            'key'  => 'zbse_complete',
1924                            'val'  => $status,
1925                            'type' => '%d',
1926                        ),
1927                    ),
1928                )
1929            );
1930
1931        }
1932
1933        return false;
1934    }
1935
1936    /**
1937     * deletes a event object
1938     *
1939     * @param array $args Associative array of arguments
1940     *              id
1941     *
1942     * @return int success;
1943     */
1944    public function deleteEvent( $args = array() ) {
1945
1946        global $ZBSCRM_t, $wpdb, $zbs;
1947
1948        #} ============ LOAD ARGS =============
1949        $defaultArgs = array(
1950
1951            'id'          => -1,
1952            'saveOrphans' => false,
1953
1954        );
1955        foreach ( $defaultArgs as $argK => $argV ) {
1956            $$argK = $argV;
1957            if ( is_array( $args ) && isset( $args[ $argK ] ) ) {
1958                if ( is_array( $args[ $argK ] ) ) {
1959                    $newData = $$argK;
1960                    if ( ! is_array( $newData ) ) {
1961                        $newData = array();
1962                    } foreach ( $args[ $argK ] as $subK => $subV ) {
1963                        $newData[ $subK ] = $subV;
1964                    }$$argK = $newData;
1965                } else {
1966                    $$argK = $args[ $argK ]; }
1967            }
1968        }
1969        #} =========== / LOAD ARGS ============
1970
1971        #} Check ID & Delete :)
1972        $id = (int) $id;
1973        if ( ! empty( $id ) && $id > 0 ) {
1974
1975            // delete orphans?
1976            if ( $saveOrphans === false ) {
1977
1978                // delete any tag links
1979                $this->DAL()->deleteTagObjLinks(
1980                    array(
1981
1982                        'objtype' => ZBS_TYPE_TASK,
1983                        'objid'   => $id,
1984                    )
1985                );
1986
1987                // delete any objlinks
1988                $this->addUpdateObjectLinks( $id, 'unset', ZBS_TYPE_TASK );
1989
1990                // delete any reminders
1991                $this->DAL()->eventreminders->deleteEventRemindersForEvent( array( 'eventID' => $id ) );
1992
1993                // delete any external source information
1994                $this->DAL()->delete_external_sources(
1995                    array(
1996
1997                        'obj_type'   => ZBS_TYPE_TASK,
1998                        'obj_id'     => $id,
1999                        'obj_source' => 'all',
2000
2001                    )
2002                );
2003
2004            }
2005
2006            $del = zeroBSCRM_db2_deleteGeneric( $id, 'events' );
2007
2008            #} Add to automator
2009            zeroBSCRM_FireInternalAutomator(
2010                'event.delete',
2011                array(
2012                    'id'          => $id,
2013                    'saveOrphans' => $saveOrphans,
2014                )
2015            );
2016
2017            return $del;
2018
2019        }
2020
2021        return false;
2022    }
2023
2024    /**
2025     * tidy's the object from wp db into clean array
2026     *
2027     * @param array $obj (DB obj)
2028     *
2029     * @return array event (clean obj)
2030     */
2031    private function tidy_event( $obj = false, $withCustomFields = false ) {
2032
2033            $res = false;
2034
2035        if ( isset( $obj->ID ) ) {
2036            $res       = array();
2037            $res['id'] = $obj->ID;
2038            /*
2039            `zbs_site` INT NULL DEFAULT NULL,
2040            `zbs_team` INT NULL DEFAULT NULL,
2041            `zbs_owner` INT NOT NULL,
2042            */
2043            $res['owner'] = $obj->zbs_owner;
2044
2045            $res['title']            = $this->stripSlashes( $obj->zbse_title );
2046            $res['desc']             = $this->stripSlashes( $obj->zbse_desc );
2047            $res['start']            = (int) $obj->zbse_start;
2048            $res['start_date']       = ( isset( $obj->zbse_start ) && $obj->zbse_start > 0 ) ? zeroBSCRM_locale_utsToDatetime( $obj->zbse_start ) : false;
2049            $res['end']              = (int) $obj->zbse_end;
2050            $res['end_date']         = ( isset( $obj->zbse_end ) && $obj->zbse_end > 0 ) ? zeroBSCRM_locale_utsToDatetime( $obj->zbse_end ) : false;
2051            $res['complete']         = (int) $this->stripSlashes( $obj->zbse_complete );
2052            $res['show_on_portal']   = (int) $obj->zbse_show_on_portal;
2053            $res['show_on_cal']      = (int) $obj->zbse_show_on_cal;
2054            $res['created']          = (int) $obj->zbse_created;
2055            $res['created_date']     = ( isset( $obj->zbse_created ) && $obj->zbse_created > 0 ) ? zeroBSCRM_locale_utsToDatetime( $obj->zbse_created ) : false;
2056            $res['lastupdated']      = (int) $obj->zbse_lastupdated;
2057            $res['lastupdated_date'] = ( isset( $obj->zbse_lastupdated ) && $obj->zbse_lastupdated > 0 ) ? zeroBSCRM_locale_utsToDatetime( $obj->zbse_lastupdated ) : false;
2058
2059            // custom fields - tidy any that are present:
2060            if ( $withCustomFields ) {
2061                $res = $this->tidyAddCustomFields( ZBS_TYPE_TASK, $obj, $res, false );
2062            }
2063        }
2064
2065        return $res;
2066    }
2067
2068    /**
2069     * Wrapper, use $this->getEventMeta($contactID,$key) for easy retrieval of singular event
2070     * Simplifies $this->getMeta
2071     *
2072     * @param int objtype
2073     * @param int objid
2074     * @param string key
2075     *
2076     * @return array event meta result
2077     */
2078    public function getEventMeta( $id = -1, $key = '', $default = false ) {
2079
2080        global $zbs;
2081
2082        if ( ! empty( $key ) ) {
2083
2084            return $this->DAL()->getMeta(
2085                array(
2086
2087                    'objtype'     => ZBS_TYPE_TASK,
2088                    'objid'       => $id,
2089                    'key'         => $key,
2090                    'fullDetails' => false,
2091                    'default'     => $default,
2092                    'ignoreowner' => true, // for now !!
2093
2094                )
2095            );
2096
2097        }
2098
2099        return $default;
2100    }
2101
2102    /**
2103     * Returns an ownerid against a event
2104     *
2105     * @param int id event ID
2106     *
2107     * @return int event owner id
2108     */
2109    public function getEventOwner( $id = -1 ) {
2110
2111        global $zbs;
2112
2113        $id = (int) $id;
2114
2115        if ( $id > 0 ) {
2116
2117            return $this->DAL()->getFieldByID(
2118                array(
2119                    'id'          => $id,
2120                    'objtype'     => ZBS_TYPE_TASK,
2121                    'colname'     => 'zbs_owner',
2122                    'ignoreowner' => true,
2123                )
2124            );
2125
2126        }
2127
2128        return false;
2129    }
2130
2131    /**
2132     * remove any non-db fields from the object
2133     * basically takes array like array('owner'=>1,'fname'=>'x','fullname'=>'x')
2134     * and returns array like array('owner'=>1,'fname'=>'x')
2135     * This does so based on the objectModel!
2136     *
2137     * @param array $obj (clean obj)
2138     *
2139     * @return array (db ready arr)
2140     */
2141    private function db_ready_event( $obj = false ) {
2142
2143        // use the generic? (override here if necessary)
2144        return $this->db_ready_obj( $obj );
2145    }
2146
2147    /**
2148     * Takes full object and makes a "list view" boiled down version
2149     * Used to generate listview objs
2150     *
2151     * @param array $obj (clean obj)
2152     *
2153     * @return array (listview ready obj)
2154     */
2155    public function listViewObj( $event = false, $columnsRequired = array() ) {
2156
2157        if ( is_array( $event ) && isset( $event['id'] ) ) {
2158
2159            $resArr = $event;
2160
2161            #} Convert contact arr into list-view-digestable 'customer'// & unset contact for leaner data transfer
2162            if ( array_key_exists( 'contact', $event ) ) {
2163                $resArr['contact'] = zeroBSCRM_getSimplyFormattedContact( $event['contact'], ( in_array( 'assignedobj', $columnsRequired ) ) );
2164            }
2165
2166            #} Convert company arr into list-view-digestable 'customer'// & unset contact for leaner data transfer
2167            if ( array_key_exists( 'company', $event ) ) {
2168                $resArr['company'] = zeroBSCRM_getSimplyFormattedCompany( $event['company'], ( in_array( 'assignedobj', $columnsRequired ) ) );
2169            }
2170
2171            return $resArr;
2172
2173        }
2174
2175        return false;
2176    }
2177
2178    // ===========  /   EVENT  =======================================================
2179    // ===============================================================================
2180} // / class