Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 486
0.00% covered (danger)
0.00%
0 / 12
CRAP
0.00% covered (danger)
0.00%
0 / 1
zbsDAL_logs
0.00% covered (danger)
0.00%
0 / 486
0.00% covered (danger)
0.00%
0 / 12
25760
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
56
 getSingle
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getLog
0.00% covered (danger)
0.00%
0 / 55
0.00% covered (danger)
0.00%
0 / 1
272
 getLogsForObj
0.00% covered (danger)
0.00%
0 / 83
0.00% covered (danger)
0.00%
0 / 1
992
 getLogsForANYObj
0.00% covered (danger)
0.00%
0 / 71
0.00% covered (danger)
0.00%
0 / 1
506
 getLogCount
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 1
90
 addUpdateLog
0.00% covered (danger)
0.00%
0 / 161
0.00% covered (danger)
0.00%
0 / 1
2756
 deleteLog
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
90
 set_log_pin_status
0.00% covered (danger)
0.00%
0 / 32
0.00% covered (danger)
0.00%
0 / 1
72
 tidy_log
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
12
 logTypeIn
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 logTypeOut
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
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 >> Logs
16 *
17 * @author   Woody Hayday <hello@jetpackcrm.com>
18 * @version  2.0
19 * @access   public
20 * @see      https://jetpackcrm.com/kb
21 */
22class zbsDAL_logs extends zbsDAL_ObjectLayer {
23
24    protected $objectType  = ZBS_TYPE_LOG;
25    protected $objectModel = array(
26
27        // ID
28        'ID'          => array(
29            'fieldname' => 'ID',
30            'format'    => 'int',
31        ),
32
33        // site + team generics
34        'zbs_site'    => array(
35            'fieldname' => 'zbs_site',
36            'format'    => 'int',
37        ),
38        'zbs_team'    => array(
39            'fieldname' => 'zbs_team',
40            'format'    => 'int',
41        ),
42        'zbs_owner'   => array(
43            'fieldname' => 'zbs_owner',
44            'format'    => 'int',
45        ),
46
47        // other fields
48        'objtype'     => array(
49            'fieldname' => 'zbsl_objtype',
50            'format'    => 'int',
51        ),
52        'objid'       => array(
53            'fieldname' => 'zbsl_objid',
54            'format'    => 'int',
55        ),
56        'type'        => array(
57            'fieldname' => 'zbsl_type',
58            'format'    => 'str',
59        ),
60        'shortdesc'   => array(
61            'fieldname' => 'zbsl_shortdesc',
62            'format'    => 'str',
63        ),
64        'longdesc'    => array(
65            'fieldname' => 'zbsl_longdesc',
66            'format'    => 'str',
67        ),
68        'pinned'      => array(
69            'fieldname' => 'zbsl_pinned',
70            'format'    => 'int',
71        ),
72        'created'     => array(
73            'fieldname' => 'zbsl_created',
74            'format'    => 'uts',
75        ),
76        'lastupdated' => array(
77            'fieldname' => 'zbsl_lastupdated',
78            'format'    => 'uts',
79        ),
80
81    );
82
83    /**
84     * Returns log types which count as 'contact'
85     * (These effect what updates 'last contacted' field against customer and 'latest contact log')
86     * - For now hard typed
87     */
88    public $contact_log_types = array( 'call', 'email', 'mail', 'meeting', 'feedback', 'invoice__sent', 'quote__sent', 'feedback', 'tweet', 'facebook_post', 'other_contact' );
89
90    function __construct( $args = array() ) {
91
92        #} =========== LOAD ARGS ==============
93        $defaultArgs = array(
94
95            // 'tag' => false,
96
97        );
98        foreach ( $defaultArgs as $argK => $argV ) {
99            $this->$argK = $argV;
100            if ( is_array( $args ) && isset( $args[ $argK ] ) ) {
101                if ( is_array( $args[ $argK ] ) ) {
102                    $newData = $this->$argK;
103                    if ( ! is_array( $newData ) ) {
104                        $newData = array();
105                    } foreach ( $args[ $argK ] as $subK => $subV ) {
106                        $newData[ $subK ] = $subV;
107                    }$this->$argK = $newData;
108                } else {
109                    $this->$argK = $args[ $argK ]; }
110            }
111        }
112        #} =========== / LOAD ARGS =============
113    }
114
115    // ===============================================================================
116    // ===========   LOGS  ===========================================================
117
118    // generic get Company (by ID)
119    // Super simplistic wrapper used by edit page etc. (generically called via dal->contacts->getSingle etc.)
120    public function getSingle( $ID = -1 ) {
121
122        return $this->getLog( array( 'id' => $ID ) );
123    }
124
125    /**
126     * returns full Log line +- details
127     *
128     * @param array $args   Associative array of arguments
129     *                      key, fullDetails, default
130     *
131     * @return array result
132     */
133    public function getLog( $args = array() ) {
134
135        #} =========== LOAD ARGS ==============
136        $defaultArgs = array(
137
138            // search args:
139            'id'          => -1,
140
141            // include:
142            'incMeta'     => false,
143
144            // permissions
145            'ignoreowner' => zeroBSCRM_DAL2_ignoreOwnership( ZBS_TYPE_LOG ), // this'll let you not-check the owner of obj
146
147            // returns scalar ID of line
148            'onlyID'      => false,
149
150        );
151        foreach ( $defaultArgs as $argK => $argV ) {
152            $$argK = $argV;
153            if ( is_array( $args ) && isset( $args[ $argK ] ) ) {
154                if ( is_array( $args[ $argK ] ) ) {
155                    $newData = $$argK;
156                    if ( ! is_array( $newData ) ) {
157                        $newData = array();
158                    } foreach ( $args[ $argK ] as $subK => $subV ) {
159                        $newData[ $subK ] = $subV;
160                    }$$argK = $newData;
161                } else {
162                    $$argK = $args[ $argK ]; }
163            }
164        }
165        #} =========== / LOAD ARGS =============
166
167        #} ========== CHECK FIELDS ============
168
169            // check id
170            $id = (int) $id;
171        if ( empty( $id ) || $id <= 0 ) {
172            return false;
173        }
174
175        #} ========= / CHECK FIELDS ===========
176
177        #} Check key
178        if ( $id ) {
179
180            global $ZBSCRM_t, $wpdb;
181            $wheres          = array( 'direct' => array() );
182            $whereStr        = '';
183            $additionalWhere = '';
184            $params          = array();
185            $res             = array();
186
187            #} Build query
188            $query = 'SELECT * FROM ' . $ZBSCRM_t['logs'];
189
190            #} ============= WHERE ================
191
192                #} Add ID
193                $wheres['ID'] = array( 'ID', '=', '%d', $id );
194
195            #} ============ / WHERE ==============
196
197            #} Build out any WHERE clauses
198            $wheresArr = $this->buildWheres( $wheres, $whereStr, $params );
199            $whereStr  = $wheresArr['where'];
200            $params    = $params + $wheresArr['params'];
201            #} / Build WHERE
202
203            #} Ownership v1.0 - the following adds SITE + TEAM checks, and (optionally), owner
204            $params = array_merge( $params, $this->ownershipQueryVars( $ignoreowner ) ); // merges in any req.
205            $ownQ   = $this->ownershipSQL( $ignoreowner );
206            if ( ! empty( $ownQ ) ) {
207                $additionalWhere = $this->spaceAnd( $additionalWhere ) . $ownQ; // adds str to query
208            }
209            #} / Ownership
210
211            #} Append to sql (this also automatically deals with sortby and paging)
212            $query .= $this->buildWhereStr( $whereStr, $additionalWhere ) . $this->buildSort( 'ID', 'DESC' ) . $this->buildPaging( 0, 1 );
213
214            try {
215
216                #} Prep & run query
217                $queryObj     = $this->prepare( $query, $params );
218                $potentialRes = $wpdb->get_row( $queryObj, OBJECT );
219
220            } catch ( Exception $e ) {
221
222                #} General SQL Err
223                $this->catchSQLError( $e );
224
225            }
226
227            #} Interpret Results (ROW)
228            if ( isset( $potentialRes ) && isset( $potentialRes->ID ) ) {
229
230                #} Has results, tidy + return
231
232                    #} Only ID? return it directly
233                if ( $onlyID === true ) {
234                    return $potentialRes->ID;
235                }
236
237                if ( $incMeta ) {
238                    $potentialRes->meta = $this->DAL()->getMeta(
239                        array(
240
241                            'objtype'     => ZBS_TYPE_LOG,
242                            'objid'       => $potentialRes->ID,
243                            'key'         => 'logmeta',
244                            'fullDetails' => false,
245                            'default'     => -1,
246
247                        )
248                    );
249                }
250
251                    return $this->tidy_log( $potentialRes );
252
253            }
254        } // / if ID
255
256        return $default;
257    }
258
259    /**
260     * returns log lines for an obj
261     *
262     * @param array $args Associative array of arguments
263     *              searchPhrase, sortByField, sortOrder, page, perPage
264     *
265     * @return array of tag lines
266     */
267    public function getLogsForObj( $args = array() ) {
268
269        #} ============ LOAD ARGS =============
270        $defaultArgs = array(
271
272            // search args:
273            'objtype'      => -1,
274            'objid'        => -1,
275            'searchPhrase' => '', // specify to search through all note descs
276            'notetype'     => -1, // specify a permified type to grab collection
277            'notetypes'    => -1, // specify an array of permified types to grab collection
278            'only_pinned'  => false,
279            'meta_pair'    => -1, // where array('key'=>x,'value'=>y) will find logs with this meta
280
281            // return
282            'incMeta'      => false,
283
284            'sortByField'  => 'ID',
285            'sortOrder'    => 'ASC',
286            'page'         => 0,
287            'perPage'      => 100,
288
289            // permissions
290            'ignoreowner'  => zeroBSCRM_DAL2_ignoreOwnership( ZBS_TYPE_LOG ), // this'll let you not-check the owner of obj
291
292        );
293        foreach ( $defaultArgs as $argK => $argV ) {
294            $$argK = $argV;
295            if ( is_array( $args ) && isset( $args[ $argK ] ) ) {
296                if ( is_array( $args[ $argK ] ) ) {
297                    $newData = $$argK;
298                    if ( ! is_array( $newData ) ) {
299                        $newData = array();
300                    } foreach ( $args[ $argK ] as $subK => $subV ) {
301                        $newData[ $subK ] = $subV;
302                    }$$argK = $newData;
303                } else {
304                    $$argK = $args[ $argK ]; }
305            }
306        }
307        #} =========== / LOAD ARGS =============
308
309        #} ========== CHECK FIELDS ============
310
311            // ID
312            $objid = (int) $objid;
313        if ( empty( $objid ) || $objid <= 0 ) {
314            return false;
315        }
316
317            // This was returning false when $objid was 0 (or -1)
318        if ( $objid < 0 ) {
319            return false;
320        }
321
322            // check obtype is legit..
323            $objtype = (int) $objtype;
324        if ( ! isset( $objtype ) || $objtype == -1 || $this->DAL()->objTypeKey( $objtype ) === -1 ) {
325            return false;
326        }
327
328        #} ========= / CHECK FIELDS ===========
329
330        global $ZBSCRM_t, $wpdb;
331        $wheres          = array( 'direct' => array() );
332        $whereStr        = '';
333        $additionalWhere = '';
334        $params          = array();
335        $res             = array();
336
337        #} Build query
338        $query = 'SELECT * FROM ' . $ZBSCRM_t['logs'];
339
340        #} ============= WHERE ================
341
342            #} objid
343                $wheres['zbsl_objid'] = array( 'zbsl_objid', '=', '%d', $objid );
344
345            #} objtype
346        if ( ! empty( $objtype ) && $objtype !== -1 ) {
347            $wheres['zbsl_objtype'] = array( 'zbsl_objtype', '=', '%d', $objtype );
348        }
349
350            #} notetype
351        if ( ! empty( $notetype ) && $notetype !== -1 ) {
352            $wheres['zbsl_type'] = array( 'zbsl_type', '=', '%s', $notetype );
353        }
354
355            #} notetypes
356        if ( is_array( $notetypes ) && count( $notetypes ) > 0 ) {
357
358            // Generate escaped csv, e.g. 'Call','Email'
359            $notetypesStr = $this->build_csv( $notetypes );
360
361            // add it as a direct where clause to avoid double escaping
362            $wheres['direct'][] = array( 'zbsl_type IN (' . $notetypesStr . ')', array() );
363
364        }
365
366            // pinned
367        if ( $only_pinned ) {
368
369            $wheres['direct'][] = array( 'zbsl_pinned = 1', array() );
370
371        }
372
373            #} Search
374        if ( ! empty( $searchPhrase ) ) {
375            $wheres['zbsl_shortdesc'] = array( 'zbsl_shortdesc', 'LIKE', '%s', '%' . $searchPhrase . '%' );
376            $wheres['zbsl_longdesc']  = array( 'zbsl_longdesc', 'LIKE', '%s', '%' . $searchPhrase . '%' );
377        }
378
379            // meta_pair
380                        // @phan-suppress-next-line PhanImpossibleCondition -- This var is initialized by arbitrary data in $args.
381        if ( is_array( $meta_pair ) && isset( $meta_pair['key'] ) && isset( $meta_pair['value'] ) ) {
382
383            // make a clean version
384            $meta_pair_key = $this->DAL()->makeSlug( $meta_pair['key'] );
385
386            // search for it
387            $wheres['log_meta'] = array( 'ID', 'IN', '(SELECT zbsm_objid FROM ' . $ZBSCRM_t['meta'] . ' WHERE zbsm_objtype = ' . ZBS_TYPE_LOG . ' AND zbsm_key = %s AND zbsm_val = %s)', array( $meta_pair_key, $meta_pair['value'] ) );
388
389        }
390
391        #} ============ / WHERE ===============
392
393        #} Build out any WHERE clauses
394        $wheresArr = $this->buildWheres( $wheres, $whereStr, $params );
395        $whereStr  = $wheresArr['where'];
396        $params    = $params + $wheresArr['params'];
397        #} / Build WHERE
398
399        #} Ownership v1.0 - the following adds SITE + TEAM checks, and (optionally), owner
400        $params = array_merge( $params, $this->ownershipQueryVars( $ignoreowner ) ); // merges in any req.
401        $ownQ   = $this->ownershipSQL( $ignoreowner );
402        if ( ! empty( $ownQ ) ) {
403            $additionalWhere = $this->spaceAnd( $additionalWhere ) . $ownQ; // adds str to query
404        }
405        #} / Ownership
406
407        #} Append to sql (this also automatically deals with sortby and paging)
408        $query .= $this->buildWhereStr( $whereStr, $additionalWhere ) . $this->buildSort( $sortByField, $sortOrder ) . $this->buildPaging( $page, $perPage );
409
410        try {
411
412            #} Prep & run query
413            $queryObj     = $this->prepare( $query, $params );
414            $potentialRes = $wpdb->get_results( $queryObj, OBJECT );
415
416        } catch ( Exception $e ) {
417
418            #} General SQL Err
419            $this->catchSQLError( $e );
420
421        }
422
423        #} Interpret results (Result Set - multi-row)
424        if ( isset( $potentialRes ) && is_array( $potentialRes ) && count( $potentialRes ) > 0 ) {
425
426            #} Has results, tidy + return
427            foreach ( $potentialRes as $resDataLine ) {
428
429                if ( $incMeta ) {
430                    $resDataLine->meta = $this->DAL()->getMeta(
431                        array(
432
433                            'objtype'     => ZBS_TYPE_LOG,
434                            'objid'       => $resDataLine->ID,
435                            'key'         => 'logmeta',
436                            'fullDetails' => false,
437                            'default'     => -1,
438
439                        )
440                    );
441                }
442
443                    // tidy
444                    $resArr = $this->tidy_log( $resDataLine );
445
446                    $res[] = $resArr;
447
448            }
449        }
450
451        return $res;
452    }
453
454    /**
455     * returns log lines, ignoring obj/owner - added to infill a few funcs ms added, not sure where used (not core)
456     * (zeroBS_searchLogs + allLogs)
457     *
458     * @param array $args Associative array of arguments
459     *              searchPhrase, sortByField, sortOrder, page, perPage
460     *
461     * @return array of tag lines
462     */
463    public function getLogsForANYObj( $args = array() ) {
464
465        #} ============ LOAD ARGS =============
466        $defaultArgs = array(
467
468            'objtype'      => -1, // optional
469
470            'searchPhrase' => -1, // specify to search through all note descs
471            'notetype'     => -1, // specify a permified type to grab collection
472            'notetypes'    => -1, // specify an array of permified types to grab collection
473
474            // return
475            'incMeta'      => false,
476
477            'sortByField'  => 'ID',
478            'sortOrder'    => 'ASC',
479            'page'         => 0,
480            'perPage'      => 100,
481
482            // permissions
483            'ignoreowner'  => zeroBSCRM_DAL2_ignoreOwnership( ZBS_TYPE_LOG ), // this'll let you not-check the owner of obj
484
485        );
486        foreach ( $defaultArgs as $argK => $argV ) {
487            $$argK = $argV;
488            if ( is_array( $args ) && isset( $args[ $argK ] ) ) {
489                if ( is_array( $args[ $argK ] ) ) {
490                    $newData = $$argK;
491                    if ( ! is_array( $newData ) ) {
492                        $newData = array();
493                    } foreach ( $args[ $argK ] as $subK => $subV ) {
494                        $newData[ $subK ] = $subV;
495                    }$$argK = $newData;
496                } else {
497                    $$argK = $args[ $argK ]; }
498            }
499        }
500        #} =========== / LOAD ARGS =============
501
502        #} ========== CHECK FIELDS ============
503
504            // check obtype is legit
505            $objtype = (int) $objtype;
506
507        #} ========= / CHECK FIELDS ===========
508
509        global $ZBSCRM_t, $wpdb;
510        $wheres          = array( 'direct' => array() );
511        $whereStr        = '';
512        $additionalWhere = '';
513        $params          = array();
514        $res             = array();
515
516        #} Build query
517        $query = 'SELECT * FROM ' . $ZBSCRM_t['logs'];
518
519        #} ============= WHERE ================
520
521            #} objtype
522        if ( ! empty( $objtype ) ) {
523            $wheres['zbsl_objtype'] = array( 'zbsl_objtype', '=', '%d', $objtype );
524        }
525
526            #} notetype
527        if ( ! empty( $notetype ) && $notetype != -1 ) {
528            $wheres['zbsl_type'] = array( 'zbsl_type', '=', '%s', $notetype );
529        }
530
531            #} notetypes
532        if ( is_array( $notetypes ) && count( $notetypes ) > 0 ) {
533            $notetypesStr = '';
534            foreach ( $notetypes as $nt ) {
535                if ( ! empty( $notetypesStr ) ) {
536                    $notetypesStr .= ',';
537                }
538                $notetypesStr .= '"' . $nt . '"';
539            }
540
541            $wheres['zbsl_types'] = array( 'zbsl_type', 'IN', '%s', '(' . $notetypesStr . ')' );
542        }
543
544            #} Search
545        if ( ! empty( $searchPhrase ) ) {
546            $wheres['zbsl_shortdesc'] = array( 'zbsl_shortdesc', 'LIKE', '%s', '%' . $searchPhrase . '%' );
547            $wheres['zbsl_longdesc']  = array( 'zbsl_longdesc', 'LIKE', '%s', '%' . $searchPhrase . '%' );
548        }
549
550        #} ============ / WHERE ===============
551
552        #} Build out any WHERE clauses
553        $wheresArr = $this->buildWheres( $wheres, $whereStr, $params );
554        $whereStr  = $wheresArr['where'];
555        $params    = $params + $wheresArr['params'];
556        #} / Build WHERE
557
558        #} Ownership v1.0 - the following adds SITE + TEAM checks, and (optionally), owner
559        $params = array_merge( $params, $this->ownershipQueryVars( $ignoreowner ) ); // merges in any req.
560        $ownQ   = $this->ownershipSQL( $ignoreowner );
561        if ( ! empty( $ownQ ) ) {
562            $additionalWhere = $this->spaceAnd( $additionalWhere ) . $ownQ; // adds str to query
563        }
564        #} / Ownership
565
566        #} Append to sql (this also automatically deals with sortby and paging)
567        $query .= $this->buildWhereStr( $whereStr, $additionalWhere ) . $this->buildSort( $sortByField, $sortOrder ) . $this->buildPaging( $page, $perPage );
568
569        try {
570
571            #} Prep & run query
572            $queryObj     = $this->prepare( $query, $params );
573            $potentialRes = $wpdb->get_results( $queryObj, OBJECT );
574
575        } catch ( Exception $e ) {
576
577            #} General SQL Err
578            $this->catchSQLError( $e );
579
580        }
581
582        #} Interpret results (Result Set - multi-row)
583        if ( isset( $potentialRes ) && is_array( $potentialRes ) && count( $potentialRes ) > 0 ) {
584
585            #} Has results, tidy + return
586            foreach ( $potentialRes as $resDataLine ) {
587
588                if ( $incMeta ) {
589                    $resDataLine->meta = $this->DAL()->getMeta(
590                        array(
591
592                            'objtype'     => ZBS_TYPE_LOG,
593                            'objid'       => $resDataLine->ID,
594                            'key'         => 'logmeta',
595                            'fullDetails' => false,
596                            'default'     => -1,
597
598                        )
599                    );
600                }
601
602                    // tidy
603                    $resArr = $this->tidy_log( $resDataLine );
604
605                    $res[] = $resArr;
606
607            }
608        }
609
610        return $res;
611    }
612
613    /**
614     * Returns a count of logs (owned)
615     *
616     * @return int count
617     */
618    public function getLogCount( $args = array() ) {
619
620        #} ============ LOAD ARGS =============
621        $defaultArgs = array(
622
623            // Search/Filtering (leave as false to ignore)
624            'withType'    => false, // will be str if used
625
626            // permissions
627            'ignoreowner' => zeroBSCRM_DAL2_ignoreOwnership( ZBS_TYPE_LOG ), // this'll let you not-check the owner of obj
628
629        );
630        foreach ( $defaultArgs as $argK => $argV ) {
631            $$argK = $argV;
632            if ( is_array( $args ) && isset( $args[ $argK ] ) ) {
633                if ( is_array( $args[ $argK ] ) ) {
634                    $newData = $$argK;
635                    if ( ! is_array( $newData ) ) {
636                        $newData = array();
637                    } foreach ( $args[ $argK ] as $subK => $subV ) {
638                        $newData[ $subK ] = $subV;
639                    }$$argK = $newData;
640                } else {
641                    $$argK = $args[ $argK ]; }
642            }
643        }
644        #} =========== / LOAD ARGS =============
645
646        $whereArr = array();
647
648        if ( $withType !== false && ! empty( $withType ) ) {
649            $whereArr['status'] = array( 'zbsl_type', '=', '%s', $withType );
650        }
651
652        return $this->DAL()->getFieldByWHERE(
653            array(
654                'objtype'     => ZBS_TYPE_LOG,
655                'colname'     => 'COUNT(ID)',
656                'where'       => $whereArr,
657                'ignoreowner' => $ignoreowner,
658            )
659        );
660    }
661
662    /**
663     * adds or updates a log object
664     *
665     * @param array $args Associative array of arguments
666     *              id (not req.), owner (not req.) data -> key/val
667     *
668     * @return int line ID
669     */
670    public function addUpdateLog( $args = array() ) {
671
672        global $zbs, $ZBSCRM_t, $wpdb;
673
674        #} ============ LOAD ARGS =============
675        $defaultArgs = array(
676
677            'id'                           => -1,
678            'owner'                        => -1,
679
680            // fields (directly)
681            'data'                         => array(
682
683                'objtype'   => -1,
684                'objid'     => -1,
685                'type'      => '', // log type e.g. zbsOc1 (zbsencoded) or custom e.g. "ALARM"
686                'shortdesc' => '',
687                'longdesc'  => '',
688                'pinned'    => -1,
689
690                'meta'      => -1, // can be any obj which'll be stored in meta table :)
691
692                'created'   => -1, // override date? :(
693
694            ),
695
696            // where this is true, if a log of matching description strings and type are added to a single object
697            // no add or update will be enacted
698            'ignore_if_existing_desc_type' => false,
699
700            // where this is true, if a log with the given array('key','value') exists against an objid/type
701            // no add or update will be enacted
702            'ignore_if_meta_matching'      => false,
703
704        );
705        foreach ( $defaultArgs as $argK => $argV ) {
706            $$argK = $argV;
707            if ( is_array( $args ) && isset( $args[ $argK ] ) ) {
708                if ( is_array( $args[ $argK ] ) ) {
709                    $newData = $$argK;
710                    if ( ! is_array( $newData ) ) {
711                        $newData = array();
712                    } foreach ( $args[ $argK ] as $subK => $subV ) {
713                        $newData[ $subK ] = $subV;
714                    }$$argK = $newData;
715                } else {
716                    $$argK = $args[ $argK ]; }
717            }
718        }
719        #} =========== / LOAD ARGS ============
720
721        #} ========== CHECK FIELDS ============
722
723            $id = (int) $id;
724
725        // if owner = -1, add current
726        if ( $owner === -1 ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
727            $owner = zeroBSCRM_user();
728        }
729
730            // check obtype is legit
731            $data['objtype'] = (int) $data['objtype'];
732        if ( ! isset( $data['objtype'] ) || $data['objtype'] == -1 || $this->DAL()->objTypeKey( $data['objtype'] ) === -1 ) {
733            return false;
734        }
735
736            // check id present + legit
737            $data['objid'] = (int) $data['objid'];
738        if ( empty( $data['objid'] ) || $data['objid'] <= 0 ) {
739            return false;
740        }
741
742            // check type not empty
743        if ( empty( $data['type'] ) ) {
744            return false;
745        }
746
747            // check for existing log which has same type and description values
748            $has_desc_matching_record = false;
749        if ( $ignore_if_existing_desc_type ) {
750
751            // find existing - will become unperformant if a contact ever gets 10's of thousands of notes of a type
752            $existing_logs = $this->getLogsForObj(
753                array(
754
755                    'objtype'  => $data['objtype'],
756                    'objid'    => $data['objid'],
757                    'notetype' => $data['type'],
758                    'page'     => -1,
759                    'perPage'  => -1,
760
761                )
762            );
763
764            if ( is_array( $existing_logs ) ) {
765
766                foreach ( $existing_logs as $log ) {
767
768                    if ( $log['shortdesc'] == $data['shortdesc']
769                        && $log['longdesc'] == $data['longdesc'] ) {
770
771                        // log with this type and matching description strings already exists against this object
772                        $has_desc_matching_record = true;
773
774                    }
775                }
776            }
777        }
778
779            // check for exsting with meta
780            $has_meta_matching_record = false;
781                        // @phan-suppress-next-line PhanImpossibleCondition -- This var is initialized by arbitrary data in $args.
782        if ( is_array( $ignore_if_meta_matching ) && isset( $ignore_if_meta_matching['key'] ) && isset( $ignore_if_meta_matching['value'] ) ) {
783
784            // find existing
785            $existing_logs = $this->getLogsForObj(
786                array(
787
788                    'objtype'   => $data['objtype'],
789                    'objid'     => $data['objid'],
790                    'meta_pair' => array(
791                        'key'   => $ignore_if_meta_matching['key'],
792                        'value' => $ignore_if_meta_matching['value'],
793                    ),
794
795                )
796            );
797
798            if ( is_array( $existing_logs ) && count( $existing_logs ) > 0 ) {
799
800                // log with this meta already exists against this object
801                $has_meta_matching_record = true;
802
803            }
804        }
805
806            // here we allow either or | both | none
807            // this lets us say 'is there a record with these meta + matching short/long desc' together
808
809            // both
810        if ( $ignore_if_existing_desc_type
811                &&
812                is_array( $ignore_if_meta_matching ) && isset( $ignore_if_meta_matching['key'] ) && isset( $ignore_if_meta_matching['value'] ) ) {
813
814            // both or fail
815            if ( $has_meta_matching_record && $has_desc_matching_record ) {
816
817                return false;
818
819            }
820
821            // either or
822        } elseif ( $ignore_if_existing_desc_type
823                ||
824                is_array( $ignore_if_meta_matching ) && isset( $ignore_if_meta_matching['key'] ) && isset( $ignore_if_meta_matching['value'] ) ) {
825
826            // either = fail
827            if ( $has_meta_matching_record || $has_desc_matching_record ) {
828
829                return false;
830
831            }
832        }
833
834        #} ========= / CHECK FIELDS ===========
835
836        $dataArr = array(
837
838            // ownership
839            // no need to update these (as of yet) - can't move teams etc.
840            // 'zbs_site' => zeroBSCRM_installSite(),
841            // 'zbs_team' => zeroBSCRM_installTeam(),
842            'zbs_owner'        => $owner,
843
844            // fields
845            'zbsl_objtype'     => $data['objtype'],
846            'zbsl_objid'       => $data['objid'],
847            'zbsl_type'        => $data['type'],
848            'zbsl_shortdesc'   => $data['shortdesc'],
849            'zbsl_longdesc'    => $data['longdesc'],
850            'zbsl_pinned'      => $data['pinned'],
851            'zbsl_lastupdated' => time(),
852        );
853
854        $dataTypes = array( // field data types
855            '%d',
856
857            '%d',
858            '%d',
859            '%s',
860            '%s',
861            '%s',
862            '%d',
863            '%d',
864        );
865
866        if ( isset( $data['created'] ) && ! empty( $data['created'] ) && $data['created'] !== -1 ) {
867            $dataArr['zbsl_created'] = $data['created'];
868            $dataTypes[]             = '%d';
869        }
870
871        if ( isset( $id ) && ! empty( $id ) && $id > 0 ) {
872
873                #} Check if obj exists (here) - for now just brutal update (will error when doesn't exist)
874
875                #} Attempt update
876            if ( $wpdb->update(
877                $ZBSCRM_t['logs'],
878                $dataArr,
879                array( // where
880                    'ID' => $id,
881                ),
882                $dataTypes,
883                array( // where data types
884                    '%d',
885                )
886            ) !== false ) {
887
888                        // any meta
889                if ( isset( $data['meta'] ) && is_array( $data['meta'] ) ) {
890
891                    // add/update each meta key pair
892                    foreach ( $data['meta'] as $k => $v ) {
893
894                                // simple add
895                                $this->DAL()->updateMeta( ZBS_TYPE_LOG, $id, $this->DAL()->makeSlug( $k ), $v );
896
897                    }
898                }
899
900                        #} Internal Automator
901                            zeroBSCRM_FireInternalAutomator(
902                                'log.update',
903                                array(
904                                    'id'             => $id,
905                                    'logagainst'     => $data['objid'],
906                                    'logagainsttype' => $data['objtype'],
907                                    'logtype'        => $data['type'],
908                                    'logshortdesc'   => $data['shortdesc'],
909                                    'loglongdesc'    => $data['longdesc'],
910                                )
911                            );
912
913                        // Successfully updated - Return id
914                        return $id;
915
916            } else {
917
918                $msg = __( 'DB Update Failed', 'zero-bs-crm' );
919                $zbs->DAL->addError( 302, $this->objectType, $msg, $dataArr );
920
921                // FAILED update
922                return false;
923
924            }
925        } else {
926
927            // set created if not set
928            if ( ! isset( $dataArr['zbsl_created'] ) ) {
929                $dataArr['zbsl_created'] = time();
930                $dataTypes[]             = '%d';
931            }
932
933            // add team etc
934            $dataArr['zbs_site'] = zeroBSCRM_site();
935            $dataTypes[]         = '%d';
936            $dataArr['zbs_team'] = zeroBSCRM_team();
937            $dataTypes[]         = '%d';
938
939            #} No ID - must be an INSERT
940            if ( $wpdb->insert(
941                $ZBSCRM_t['logs'],
942                $dataArr,
943                $dataTypes
944            ) > 0 ) {
945
946                    #} Successfully inserted, lets return new ID
947                    $newID = $wpdb->insert_id;
948
949                    // any meta
950                if ( isset( $data['meta'] ) && is_array( $data['meta'] ) ) {
951
952                    // add/update each meta key pair
953                    foreach ( $data['meta'] as $k => $v ) {
954
955                        // simple add
956                        $this->DAL()->updateMeta( ZBS_TYPE_LOG, $newID, $this->DAL()->makeSlug( $k ), $v );
957
958                    }
959                }
960
961                    #} Internal Automator
962                if ( ! empty( $newID ) ) {
963
964                    zeroBSCRM_FireInternalAutomator(
965                        'log.new',
966                        array(
967                            'id'             => $newID,
968                            'logagainst'     => $data['objid'],
969                            'logagainsttype' => $data['objtype'],
970                            'logtype'        => $data['type'],
971                            'logshortdesc'   => $data['shortdesc'],
972                            'loglongdesc'    => $data['longdesc'],
973                        )
974                    );
975
976                }
977
978                    return $newID;
979
980            } else {
981
982                $msg = __( 'DB Insert Failed', 'zero-bs-crm' );
983                $zbs->DAL->addError( 303, $this->objectType, $msg, $dataArr );
984
985                #} Failed to Insert
986                return false;
987
988            }
989        }
990
991        return false;
992    }
993
994    /**
995     * deletes a Log object
996     * NOTE! this doesn't yet delete any META!
997     *
998     * @param array $args Associative array of arguments
999     *              id
1000     *
1001     * @return int success;
1002     */
1003    public function deleteLog( $args = array() ) {
1004
1005        global $ZBSCRM_t, $wpdb;
1006
1007        #} ============ LOAD ARGS =============
1008        $defaultArgs = array(
1009
1010            'id' => -1,
1011
1012        );
1013        foreach ( $defaultArgs as $argK => $argV ) {
1014            $$argK = $argV;
1015            if ( is_array( $args ) && isset( $args[ $argK ] ) ) {
1016                if ( is_array( $args[ $argK ] ) ) {
1017                    $newData = $$argK;
1018                    if ( ! is_array( $newData ) ) {
1019                        $newData = array();
1020                    } foreach ( $args[ $argK ] as $subK => $subV ) {
1021                        $newData[ $subK ] = $subV;
1022                    }$$argK = $newData;
1023                } else {
1024                    $$argK = $args[ $argK ]; }
1025            }
1026        }
1027        #} =========== / LOAD ARGS ============
1028
1029        #} Check ID & Delete :)
1030        $id = (int) $id;
1031        if ( ! empty( $id ) && $id > 0 ) {
1032            return zeroBSCRM_db2_deleteGeneric( $id, 'logs' );
1033        }
1034
1035        return false;
1036    }
1037
1038    /**
1039     * Pins a log object to its contact
1040     *
1041     * @param array $args Associative array of arguments
1042     *              id
1043     *
1044     * @return int success;
1045     */
1046    public function set_log_pin_status( $args = array() ) {
1047
1048        global $ZBSCRM_t, $wpdb;
1049
1050        #} ============ LOAD ARGS =============
1051        $defaultArgs = array(
1052
1053            'id'     => -1,
1054            'pinned' => 1,
1055
1056        );
1057        foreach ( $defaultArgs as $argK => $argV ) {
1058            $$argK = $argV;
1059            if ( is_array( $args ) && isset( $args[ $argK ] ) ) {
1060                if ( is_array( $args[ $argK ] ) ) {
1061                    $newData = $$argK;
1062                    if ( ! is_array( $newData ) ) {
1063                        $newData = array();
1064                    } foreach ( $args[ $argK ] as $subK => $subV ) {
1065                        $newData[ $subK ] = $subV;
1066                    }$$argK = $newData;
1067                } else {
1068                    $$argK = $args[ $argK ]; }
1069            }
1070        }
1071        #} =========== / LOAD ARGS ============
1072
1073        if ( $pinned !== 1 ) {
1074            $pinned = -1;
1075        }
1076
1077        // attempt update
1078        return $wpdb->update(
1079            $ZBSCRM_t['logs'],
1080            array(
1081                'zbsl_pinned' => $pinned,
1082            ),
1083            array( // where
1084                'ID' => $id,
1085            ),
1086            array( // field data types
1087                '%d',
1088            ),
1089            array( // where data types
1090                '%d',
1091            )
1092        );
1093    }
1094
1095    /**
1096     * tidy's the object from wp db into clean array
1097     *
1098     * @param array $obj (DB obj)
1099     *
1100     * @return array (clean obj)
1101     */
1102    private function tidy_log( $obj = false ) {
1103
1104            $res = false;
1105
1106        if ( isset( $obj->ID ) ) {
1107            $res          = array();
1108            $res['id']    = $obj->ID;
1109            $res['owner'] = $obj->zbs_owner;
1110
1111            // added these two for backward compatibility / alias of (TROY modifications):
1112            // please use owner ideally :)
1113            $res['authorid'] = $obj->zbs_owner;
1114            $res['author']   = get_the_author_meta( 'display_name', $obj->zbs_owner );
1115
1116            $res['objtype'] = $obj->zbsl_objtype;
1117            $res['objid']   = $obj->zbsl_objid;
1118
1119            $res['type']      = $this->stripSlashes( $obj->zbsl_type );
1120            $res['shortdesc'] = $this->stripSlashes( $obj->zbsl_shortdesc );
1121            $res['longdesc']  = $this->stripSlashes( $obj->zbsl_longdesc );
1122            $res['pinned']    = ( (int) $obj->zbsl_pinned === 1 );
1123
1124            // to maintain old obj more easily, here we refine created into datestamp
1125            $res['created']    = zeroBSCRM_locale_utsToDatetime( $obj->zbsl_created );
1126            $res['createduts'] = $obj->zbsl_created; // this is the UTS (int14)
1127
1128            $res['lastupdated'] = $obj->zbsl_lastupdated;
1129
1130            if ( isset( $obj->meta ) ) {
1131                $res['meta'] = $obj->meta;
1132            }
1133        }
1134
1135        return $res;
1136    }
1137
1138    /**
1139     * Translates a clear text log type to a lowercase (kinda) permalink
1140     * ... this is kinda DAL1 legacy
1141     *
1142     * @param string
1143     *
1144     * @return string
1145     */
1146    public function logTypeIn( $str = '' ) {
1147
1148            $x = str_replace( ' ', '_', $str );
1149            $x = str_replace( ':', '_', $x );
1150            return strtolower( $x );
1151    }
1152
1153    /**
1154     * Translates a db text log type to a clear text output
1155     * ... this is kinda DAL1 legacy
1156     * *UNTESTED
1157     *
1158     * @param string
1159     *
1160     * @return string
1161     */
1162    public function logTypeOut( $str = '' ) {
1163
1164            $x = str_replace( '_', ' ', $str );
1165            $x = str_replace( '  ', ': ', $x );
1166            return ucwords( $x );
1167    }
1168
1169    // =========== / LOGS      =======================================================
1170    // ===============================================================================
1171} // / class