Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 429
0.00% covered (danger)
0.00%
0 / 12
CRAP
0.00% covered (danger)
0.00%
0 / 1
zbsDAL_quotetemplates
0.00% covered (danger)
0.00%
0 / 428
0.00% covered (danger)
0.00%
0 / 12
22350
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
 getQuotetemplate
0.00% covered (danger)
0.00%
0 / 63
0.00% covered (danger)
0.00%
0 / 1
650
 getQuotetemplates
0.00% covered (danger)
0.00%
0 / 83
0.00% covered (danger)
0.00%
0 / 1
992
 getQuotetemplateCount
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
56
 addUpdateQuotetemplate
0.00% covered (danger)
0.00%
0 / 171
0.00% covered (danger)
0.00%
0 / 1
2652
 deleteQuotetemplate
0.00% covered (danger)
0.00%
0 / 21
0.00% covered (danger)
0.00%
0 / 1
110
 tidy_quotetemplate
0.00% covered (danger)
0.00%
0 / 21
0.00% covered (danger)
0.00%
0 / 1
90
 getQuotetemplateMeta
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
6
 getQuotetemplateOwner
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
6
 db_ready_quotetemplate
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 / 4
0.00% covered (danger)
0.00%
0 / 1
12
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
12/*
13======================================================
14    Breaking Checks ( stops direct access )
15    ====================================================== */
16    defined( 'ZEROBSCRM_PATH' ) || exit( 0 );
17/*
18======================================================
19    / Breaking Checks
20    ====================================================== */
21
22/**
23 * ZBS DAL >> Quote Templates
24 *
25 * @author   Woody Hayday <hello@jetpackcrm.com>
26 * @version  2.0
27 * @access   public
28 * @see      https://jetpackcrm.com/kb
29 */
30class zbsDAL_quotetemplates extends zbsDAL_ObjectLayer {
31
32    protected $objectType     = ZBS_TYPE_QUOTETEMPLATE;
33    protected $objectDBPrefix = 'zbsqt_';
34    protected $objectModel    = array(
35
36        // ID
37        'ID'          => array(
38            'fieldname' => 'ID',
39            'format'    => 'int',
40        ),
41
42        // site + team generics
43        'zbs_site'    => array(
44            'fieldname' => 'zbs_site',
45            'format'    => 'int',
46        ),
47        'zbs_team'    => array(
48            'fieldname' => 'zbs_team',
49            'format'    => 'int',
50        ),
51        'zbs_owner'   => array(
52            'fieldname' => 'zbs_owner',
53            'format'    => 'int',
54        ),
55
56        // other fields
57        'title'       => array(
58            'fieldname' => 'zbsqt_title',
59            'format'    => 'str',
60            'max_len'   => 255,
61        ),
62        'value'       => array(
63            'fieldname' => 'zbsqt_value',
64            'format'    => 'decimal',
65        ),
66        'date_str'    => array(
67            'fieldname' => 'zbsqt_date_str',
68            'format'    => 'str',
69        ),
70        'date'        => array(
71            'fieldname' => 'zbsqt_date',
72            'format'    => 'uts',
73        ),
74        'content'     => array(
75            'fieldname' => 'zbsqt_content',
76            'format'    => 'str',
77        ),
78        'notes'       => array(
79            'fieldname' => 'zbsqt_notes',
80            'format'    => 'str',
81        ),
82        'currency'    => array(
83            'fieldname' => 'zbsqt_currency',
84            'format'    => 'curr',
85            'max_len'   => 4,
86        ),
87        'created'     => array(
88            'fieldname' => 'zbsqt_created',
89            'format'    => 'uts',
90        ),
91        'lastupdated' => array(
92            'fieldname' => 'zbsqt_lastupdated',
93            'format'    => 'uts',
94        ),
95
96    );
97
98    function __construct( $args = array() ) {
99
100        #} =========== LOAD ARGS ==============
101        $defaultArgs = array(
102
103            // 'tag' => false,
104
105        );
106        foreach ( $defaultArgs as $argK => $argV ) {
107            $this->$argK = $argV;
108            if ( is_array( $args ) && isset( $args[ $argK ] ) ) {
109                if ( is_array( $args[ $argK ] ) ) {
110                    $newData = $this->$argK;
111                    if ( ! is_array( $newData ) ) {
112                        $newData = array();
113                    } foreach ( $args[ $argK ] as $subK => $subV ) {
114                        $newData[ $subK ] = $subV;
115                    }$this->$argK = $newData;
116                } else {
117                    $this->$argK = $args[ $argK ]; }
118            }
119        }
120        #} =========== / LOAD ARGS =============
121    }
122    // ===============================================================================
123    // ===========   QUOTETEMPLATE  =======================================================
124
125    // generic get Company (by ID)
126    // Super simplistic wrapper used by edit page etc. (generically called via dal->contacts->getSingle etc.)
127    public function getSingle( $ID = -1 ) {
128
129        return $this->getQuotetemplate( $ID );
130    }
131
132    /**
133     * returns full quotetemplate line +- details
134     *
135     * @param int id        quotetemplate id
136     * @param array                          $args   Associative array of arguments
137     *
138     * @return array quotetemplate object
139     */
140    public function getQuotetemplate( $id = -1, $args = array() ) {
141
142        global $zbs;
143
144        #} =========== LOAD ARGS ==============
145        $defaultArgs = array(
146
147            // with what?
148            'withOwner'   => false,
149
150            // permissions
151            'ignoreowner' => zeroBSCRM_DAL2_ignoreOwnership( ZBS_TYPE_QUOTETEMPLATE ), // this'll let you not-check the owner of obj
152
153            // returns scalar ID of line
154            'onlyID'      => false,
155
156            'fields'      => false, // false = *, array = fieldnames
157
158        );
159        foreach ( $defaultArgs as $argK => $argV ) {
160            $$argK = $argV;
161            if ( is_array( $args ) && isset( $args[ $argK ] ) ) {
162                if ( is_array( $args[ $argK ] ) ) {
163                    $newData = $$argK;
164                    if ( ! is_array( $newData ) ) {
165                        $newData = array();
166                    } foreach ( $args[ $argK ] as $subK => $subV ) {
167                        $newData[ $subK ] = $subV;
168                    }$$argK = $newData;
169                } else {
170                    $$argK = $args[ $argK ]; }
171            }
172        }
173        #} =========== / LOAD ARGS =============
174
175        #} Check ID
176        $id = (int) $id;
177        if (
178            ( ! empty( $id ) && $id > 0 )
179            ||
180            ( ! empty( $email ) )
181            ||
182            ( ! empty( $externalSource ) && ! empty( $externalSourceUID ) )
183            ) {
184
185            global $ZBSCRM_t, $wpdb;
186            $wheres          = array( 'direct' => array() );
187            $whereStr        = '';
188            $additionalWhere = '';
189            $params          = array();
190            $res             = array();
191            $extraSelect     = '';
192
193            #} ============= PRE-QUERY ============
194
195                $selector = 'quotetemplate.*';
196            if ( is_array( $fields ) ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
197                    $selector = '';
198
199                    // always needs id, so add if not present
200                if ( ! in_array( 'ID', $fields ) ) {
201                    $selector = 'quotetemplate.ID';
202                }
203
204                foreach ( $fields as $f ) {
205                    if ( ! empty( $selector ) ) {
206                        $selector .= ',';
207                    }
208                    $selector .= 'quotetemplate.' . $f;
209                }
210            } elseif ( $onlyID ) {
211                $selector = 'quotetemplate.ID';
212            }
213
214            #} ============ / PRE-QUERY ===========
215
216            #} Build query
217            $query = 'SELECT ' . $selector . $extraSelect . ' FROM ' . $ZBSCRM_t['quotetemplates'] . ' as quotetemplate';
218            #} ============= WHERE ================
219
220            if ( ! empty( $id ) && $id > 0 ) {
221
222                #} Add ID
223                $wheres['ID'] = array( 'ID', '=', '%d', $id );
224
225            }
226
227            #} ============ / WHERE ==============
228
229            #} Build out any WHERE clauses
230            $wheresArr = $this->buildWheres( $wheres, $whereStr, $params );
231            $whereStr  = $wheresArr['where'];
232            $params    = $params + $wheresArr['params'];
233            #} / Build WHERE
234
235            #} Ownership v1.0 - the following adds SITE + TEAM checks, and (optionally), owner
236            $params = array_merge( $params, $this->ownershipQueryVars( $ignoreowner ) ); // merges in any req.
237            $ownQ   = $this->ownershipSQL( $ignoreowner, 'quotetemplate' );
238            if ( ! empty( $ownQ ) ) {
239                $additionalWhere = $this->spaceAnd( $additionalWhere ) . $ownQ; // adds str to query
240            }
241            #} / Ownership
242
243            #} Append to sql (this also automatically deals with sortby and paging)
244            $query .= $this->buildWhereStr( $whereStr, $additionalWhere ) . $this->buildSort( 'ID', 'DESC' ) . $this->buildPaging( 0, 1 );
245
246            try {
247
248                #} Prep & run query
249                $queryObj     = $this->prepare( $query, $params );
250                $potentialRes = $wpdb->get_row( $queryObj, OBJECT );
251
252            } catch ( Exception $e ) {
253
254                #} General SQL Err
255                $this->catchSQLError( $e );
256
257            }
258
259            #} Interpret Results (ROW)
260            if ( isset( $potentialRes ) && isset( $potentialRes->ID ) ) {
261
262                #} Has results, tidy + return
263
264                    #} Only ID? return it directly
265                if ( $onlyID ) {
266                    return $potentialRes->ID;
267                }
268
269                    // tidy
270                if ( is_array( $fields ) ) {
271                    // guesses fields based on table col names
272                    $res = $this->lazyTidyGeneric( $potentialRes );
273                } else {
274                    // proper tidy
275                    $res = $this->tidy_quotetemplate( $potentialRes, false );
276                }
277
278                    /*
279                    if ($withTags){
280
281                        // add all tags lines
282                        $res['tags'] = $this->DAL()->getTagsForObjID(array('objtypeid'=>ZBS_TYPE_QUOTETEMPLATE,'objid'=>$potentialRes->ID));
283
284                    }*/
285
286                    return $res;
287
288            }
289        } // / if ID
290
291        return false;
292    }
293
294    /**
295     * returns quotetemplate detail lines
296     *
297     * @param array $args Associative array of arguments
298     *
299     * @return array of quotetemplate lines
300     */
301    public function getQuotetemplates( $args = array() ) {
302
303        global $zbs;
304
305        #} ============ LOAD ARGS =============
306        $defaultArgs = array(
307
308            // Search/Filtering (leave as false to ignore)
309            'searchPhrase'  => '', // searches which fields?
310            'inArr'         => false,
311            // 'isTagged'          => false, // 1x INT OR array(1,2,3)
312            // 'isNotTagged'       => false, // 1x INT OR array(1,2,3)
313            'ownedBy'       => false,
314            'olderThan'     => false, // uts
315            'newerThan'     => false, // uts
316            // 'hasStatus'         => false, // Lead (this takes over from the quick filter post 19/6/18)
317            // 'otherStatus'       => false, // status other than 'Lead'
318
319            // returns
320            'count'         => false,
321            'withOwner'     => false,
322            'checkDefaults' => false, // if true returns 'default' value too (is one of our defaults)
323
324            'sortByField'   => 'ID',
325            'sortOrder'     => 'ASC',
326            'page'          => 0, // this is what page it is (gets * by for limit)
327            'perPage'       => 100,
328            'whereCase'     => 'AND', // DEFAULT = AND
329
330            // permissions
331            'ignoreowner'   => zeroBSCRM_DAL2_ignoreOwnership( ZBS_TYPE_QUOTETEMPLATE ), // this'll let you not-check the owner of obj - GLOBAL FOR NOW
332
333        );
334        foreach ( $defaultArgs as $argK => $argV ) {
335            $$argK = $argV;
336            if ( is_array( $args ) && isset( $args[ $argK ] ) ) {
337                if ( is_array( $args[ $argK ] ) ) {
338                    $newData = $$argK;
339                    if ( ! is_array( $newData ) ) {
340                        $newData = array();
341                    } foreach ( $args[ $argK ] as $subK => $subV ) {
342                        $newData[ $subK ] = $subV;
343                    }$$argK = $newData;
344                } else {
345                    $$argK = $args[ $argK ]; }
346            }
347        }
348        #} =========== / LOAD ARGS =============
349
350        global $ZBSCRM_t, $wpdb, $zbs;
351        $wheres          = array( 'direct' => array() );
352        $whereStr        = '';
353        $additionalWhere = '';
354        $params          = array();
355        $res             = array();
356        $joinQ           = '';
357        $extraSelect     = '';
358
359        #} ============= PRE-QUERY ============
360
361            #} Capitalise this
362            $sortOrder = strtoupper( $sortOrder );
363
364            #} If just count, turn off any extra gumpf
365        if ( $count ) {
366            $withOwner = false;
367        }
368
369        #} ============ / PRE-QUERY ===========
370
371        #} Build query
372        $query = 'SELECT quotetemplate.*' . $extraSelect . ' FROM ' . $ZBSCRM_t['quotetemplates'] . ' as quotetemplate' . $joinQ;
373
374        #} Count override
375        if ( $count ) {
376            $query = 'SELECT COUNT(quotetemplate.ID) FROM ' . $ZBSCRM_t['quotetemplates'] . ' as quotetemplate' . $joinQ;
377        }
378
379        #} ============= WHERE ================
380
381            #} Add Search phrase
382        if ( ! empty( $searchPhrase ) ) {
383
384            // search? - ALL THESE COLS should probs have index of FULLTEXT in db?
385            $searchWheres                   = array();
386            $searchWheres['search_title']   = array( 'zbsqt_title', 'LIKE', '%s', '%' . $searchPhrase . '%' );
387            $searchWheres['search_content'] = array( 'zbsqt_content', 'LIKE', '%s', '%' . $searchPhrase . '%' );
388
389            // This generates a query like 'zbsqt_fname LIKE %s OR zbsqt_lname LIKE %s',
390            // which we then need to include as direct subquery (below) in main query :)
391            $searchQueryArr = $this->buildWheres( $searchWheres, '', array(), 'OR', false );
392
393            if ( is_array( $searchQueryArr ) && isset( $searchQueryArr['where'] ) && ! empty( $searchQueryArr['where'] ) ) {
394
395                // add it
396                $wheres['direct'][] = array( '(' . $searchQueryArr['where'] . ')', $searchQueryArr['params'] );
397
398            }
399        }
400
401            #} In array (if inCompany passed, this'll currently overwrite that?! (todo2.5))
402        if ( is_array( $inArr ) && count( $inArr ) > 0 ) {
403
404            // clean for ints
405            $inArrChecked = array();
406            foreach ( $inArr as $x ) {
407                $inArrChecked[] = (int) $x; }
408
409            // add where
410            $wheres['inarray'] = array( 'ID', 'IN', '(' . implode( ',', $inArrChecked ) . ')' );
411
412        }
413
414            #} Owned by
415        if ( ! empty( $ownedBy ) && $ownedBy > 0 ) {
416
417            // would never hard-type this in (would make generic as in buildWPMetaQueryWhere)
418            // but this is only here until MIGRATED to db2 globally
419            // $wheres['incompany'] = array('ID','IN','(SELECT DISTINCT post_id FROM '.$wpdb->prefix."postmeta WHERE meta_key = 'zbs_company' AND meta_value = %d)",$inCompany);
420            // Use obj links now
421            $wheres['ownedBy'] = array( 'zbs_owner', '=', '%s', $ownedBy );
422
423        }
424
425            // phpcs:disable WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase,VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
426            // quick addition for mike
427            #} olderThan
428        if ( ! empty( $olderThan ) && $olderThan > 0 ) {
429            $wheres['olderThan'] = array( 'zbsqt_created', '<=', '%d', $olderThan );
430        }
431            #} newerThan
432        if ( ! empty( $newerThan ) && $newerThan > 0 ) {
433            $wheres['newerThan'] = array( 'zbsqt_created', '>=', '%d', $newerThan );
434        }
435            // phpcs:enable WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase,VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
436
437            #} Is Tagged (expects 1 tag ID OR array)
438            /*
439                // catch 1 item arr
440                if (is_array($isTagged) && count($isTagged) == 1) $isTagged = $isTagged[0];
441
442            if (!is_array($isTagged) && !empty($isTagged) && $isTagged > 0){
443
444                // add where tagged
445                // 1 int:
446                $wheres['direct'][] = array('((SELECT COUNT(ID) FROM '.$ZBSCRM_t['taglinks'].' WHERE zbstl_objtype = %d AND zbstl_objid = quotetemplate.ID AND zbstl_tagid = %d) > 0)',array(ZBS_TYPE_QUOTETEMPLATE,$isTagged));
447
448            } else if (is_array($isTagged) && count($isTagged) > 0){
449
450                // foreach in array :)
451                $tagStr = '';
452                foreach ($isTagged as $iTag){
453                    $i = (int)$iTag;
454                    if ($i > 0){
455
456                        if ($tagStr !== '') $tagStr .',';
457                        $tagStr .= $i;
458                    }
459                }
460                if (!empty($tagStr)){
461
462                    $wheres['direct'][] = array('((SELECT COUNT(ID) FROM '.$ZBSCRM_t['taglinks'].' WHERE zbstl_objtype = %d AND zbstl_objid = quotetemplate.ID AND zbstl_tagid IN (%s)) > 0)',array(ZBS_TYPE_QUOTETEMPLATE,$tagStr));
463
464                }
465
466            }
467            #} Is NOT Tagged (expects 1 tag ID OR array)
468
469                // catch 1 item arr
470                if (is_array($isNotTagged) && count($isNotTagged) == 1) $isNotTagged = $isNotTagged[0];
471
472            if (!is_array($isNotTagged) && !empty($isNotTagged) && $isNotTagged > 0){
473
474                // add where tagged
475                // 1 int:
476                $wheres['direct'][] = array('((SELECT COUNT(ID) FROM '.$ZBSCRM_t['taglinks'].' WHERE zbstl_objtype = %d AND zbstl_objid = quotetemplate.ID AND zbstl_tagid = %d) = 0)',array(ZBS_TYPE_QUOTETEMPLATE,$isNotTagged));
477
478            } else if (is_array($isNotTagged) && count($isNotTagged) > 0){
479
480                // foreach in array :)
481                $tagStr = '';
482                foreach ($isNotTagged as $iTag){
483                    $i = (int)$iTag;
484                    if ($i > 0){
485
486                        if ($tagStr !== '') $tagStr .',';
487                        $tagStr .= $i;
488                    }
489                }
490                if (!empty($tagStr)){
491
492                    $wheres['direct'][] = array('((SELECT COUNT(ID) FROM '.$ZBSCRM_t['taglinks'].' WHERE zbstl_objtype = %d AND zbstl_objid = quotetemplate.ID AND zbstl_tagid IN (%s)) = 0)',array(ZBS_TYPE_QUOTETEMPLATE,$tagStr));
493
494                }
495
496            } */
497
498        #} ============ / WHERE ===============
499
500        #} CHECK this + reset to default if faulty
501        if ( ! in_array( $whereCase, array( 'AND', 'OR' ) ) ) {
502            $whereCase = 'AND';
503        }
504
505        #} Build out any WHERE clauses
506        $wheresArr = $this->buildWheres( $wheres, $whereStr, $params, $whereCase );
507        $whereStr  = $wheresArr['where'];
508        $params    = $params + $wheresArr['params'];
509        #} / Build WHERE
510
511        #} Ownership v1.0 - the following adds SITE + TEAM checks, and (optionally), owner
512        $params = array_merge( $params, $this->ownershipQueryVars( $ignoreowner ) ); // merges in any req.
513        $ownQ   = $this->ownershipSQL( $ignoreowner, 'quotetemplate' );
514        if ( ! empty( $ownQ ) ) {
515            $additionalWhere = $this->spaceAnd( $additionalWhere ) . $ownQ; // adds str to query
516        }
517        #} / Ownership
518
519        #} Append to sql (this also automatically deals with sortby and paging)
520        $query .= $this->buildWhereStr( $whereStr, $additionalWhere ) . $this->buildSort( $sortByField, $sortOrder ) . $this->buildPaging( $page, $perPage );
521
522        try {
523
524            #} Prep & run query
525            $queryObj = $this->prepare( $query, $params );
526
527            #} Catch count + return if requested
528            if ( $count ) {
529                return $wpdb->get_var( $queryObj );
530            }
531
532            #} else continue..
533            $potentialRes = $wpdb->get_results( $queryObj, OBJECT );
534
535        } catch ( Exception $e ) {
536
537            #} General SQL Err
538            $this->catchSQLError( $e );
539
540        }
541
542        #} Interpret results (Result Set - multi-row)
543        if ( isset( $potentialRes ) && is_array( $potentialRes ) && count( $potentialRes ) > 0 ) {
544
545            #} Has results, tidy + return
546            foreach ( $potentialRes as $resDataLine ) {
547
548                    // tidy
549                    $resArr = $this->tidy_quotetemplate( $resDataLine ); // withCustomFields
550
551                    // here we also grab this meta to see if is default
552                if ( $checkDefaults ) {
553                    $resArr['default'] = $this->DAL()->meta( ZBS_TYPE_QUOTETEMPLATE, $resDataLine->ID, 'zbsdefault', false );
554                }
555
556                    /*
557                    if ($withTags){
558
559                        // add all tags lines
560                        $resArr['tags'] = $this->DAL()->getTagsForObjID(array('objtypeid'=>ZBS_TYPE_QUOTETEMPLATE,'objid'=>$resDataLine->ID));
561
562                    }*/
563
564                    $res[] = $resArr;
565
566            }
567        }
568
569        return $res;
570    }
571
572    /**
573     * Returns a count of contacts (owned)
574     * Replaces zeroBS_customerCount
575     *
576     * @param object $args - DAL args.
577     *
578     * @return int count
579     */
580    public function getQuotetemplateCount( $args = array() ) {
581
582        #} ============ LOAD ARGS =============
583        $defaultArgs = array(
584
585            // Search/Filtering (leave as false to ignore)
586
587            // permissions
588            'ignoreowner' => zeroBSCRM_DAL2_ignoreOwnership( ZBS_TYPE_QUOTETEMPLATE ), // this'll let you not-check the owner of obj
589
590        );
591        foreach ( $defaultArgs as $argK => $argV ) {
592            $$argK = $argV;
593            if ( is_array( $args ) && isset( $args[ $argK ] ) ) {
594                if ( is_array( $args[ $argK ] ) ) {
595                    $newData = $$argK;
596                    if ( ! is_array( $newData ) ) {
597                        $newData = array();
598                    } foreach ( $args[ $argK ] as $subK => $subV ) {
599                        $newData[ $subK ] = $subV;
600                    }$$argK = $newData;
601                } else {
602                    $$argK = $args[ $argK ]; }
603            }
604        }
605        #} =========== / LOAD ARGS =============
606
607        $whereArr = array();
608
609        // if ($withStatus !== false && !empty($withStatus)) $whereArr['status'] = array('zbsqt_status','=','%s',$withStatus);
610
611        return $this->DAL()->getFieldByWHERE(
612            array(
613                'objtype'     => ZBS_TYPE_QUOTETEMPLATE,
614                'colname'     => 'COUNT(ID)',
615                'where'       => $whereArr,
616                'ignoreowner' => $ignoreowner,
617            )
618        );
619
620        return 0;
621    }
622
623    /**
624     * adds or updates a quotetemplate object
625     *
626     * @param array $args Associative array of arguments
627     *              id (if update), owner, data (array of field data)
628     *
629     * @return int line ID
630     */
631    public function addUpdateQuotetemplate( $args = array() ) {
632
633        global $ZBSCRM_t, $wpdb, $zbs;
634
635        #} Retrieve any cf
636        // $customFields = $this->DAL()->getActiveCustomFields(array('objtypeid'=>ZBS_TYPE_QUOTETEMPLATE));
637
638        #} ============ LOAD ARGS =============
639        $defaultArgs = array(
640
641            'id'                   => -1,
642            'owner'                => -1,
643
644            // fields (directly)
645            'data'                 => array(
646
647                'title'       => '',
648                'value'       => '',
649                'date_str'    => '',
650                'date'        => '',
651                'content'     => '',
652                'notes'       => '',
653                'currency'    => '',
654
655                // Note Custom fields may be passed here, but will not have defaults so check isset()
656
657                // allow this to be set for MS sync etc.
658                'created'     => -1,
659                'lastupdated' => '',
660
661            ),
662
663            'limitedFields'        => -1, // if this is set it OVERRIDES data (allowing you to set specific fields + leave rest in tact)
664            // ^^ will look like: array(array('key'=>x,'val'=>y,'type'=>'%s'))
665
666            // this function as DAL1 func did.
667            'extraMeta'            => -1,
668            'automatorPassthrough' => -1,
669            'fallBackLog'          => -1,
670
671            'silentInsert'         => false, // this was for init Migration - it KILLS all IA for newQuotetemplate (because is migrating, not creating new :) this was -1 before
672
673            'do_not_update_blanks' => false, // this allows you to not update fields if blank (same as fieldoverride for extsource -> in)
674
675        );
676        foreach ( $defaultArgs as $argK => $argV ) {
677            $$argK = $argV;
678            if ( is_array( $args ) && isset( $args[ $argK ] ) ) {
679                if ( is_array( $args[ $argK ] ) ) {
680                    $newData = $$argK;
681                    if ( ! is_array( $newData ) ) {
682                        $newData = array();
683                    } foreach ( $args[ $argK ] as $subK => $subV ) {
684                        $newData[ $subK ] = $subV;
685                    }$$argK = $newData;
686                } else {
687                    $$argK = $args[ $argK ]; }
688            }
689        }
690
691        #} =========== / LOAD ARGS ============
692
693        #} ========== CHECK FIELDS ============
694
695            $id = (int) $id;
696
697            // here we check that the potential owner CAN even own
698        if ( $owner > 0 && ! user_can( $owner, 'admin_zerobs_usr' ) ) {
699            $owner = -1;
700        }
701
702            // if owner = -1, add current
703        if ( ! isset( $owner ) || $owner === -1 ) {
704            $owner = zeroBSCRM_user(); }
705
706        if ( is_array( $limitedFields ) ) {
707
708            // LIMITED UPDATE (only a few fields.)
709            if ( ! is_array( $limitedFields ) || count( $limitedFields ) <= 0 ) {
710                return false;
711            }
712            // REQ. ID too (can only update)
713            if ( empty( $id ) || $id <= 0 ) {
714                return false;
715            }
716        } else {
717
718            // NORMAL, FULL UPDATE
719
720        }
721
722        #} ========= / CHECK FIELDS ===========
723
724        #} ========= OVERRIDE SETTING (Deny blank overrides) ===========
725
726            // either ext source + setting, or set by the func call
727        if ( $do_not_update_blanks ) {
728
729                // this setting says 'don't override filled-out data with blanks'
730                // so here we check through any passed blanks + convert to limitedFields
731                // only matters if $id is set (there is somt to update not add
732            if ( isset( $id ) && ! empty( $id ) && $id > 0 ) {
733
734                // get data to copy over (for now, this is required to remove 'fullname' etc.)
735                $dbData = $this->db_ready_quotetemplate( $data );
736                // unset($dbData['id']); // this is unset because we use $id, and is update, so not req. legacy issue
737                // unset($dbData['created']); // this is unset because this uses an obj which has been 'updated' against original details, where created is output in the WRONG format :)
738
739                $origData    = $data; // $data = array();
740                $limitedData = array(); // array(array('key'=>'zbsqt_x','val'=>y,'type'=>'%s'))
741
742                // cycle through + translate into limitedFields (removing any blanks, or arrays (e.g. externalSources))
743                // we also have to remake a 'faux' data (removing blanks for tags etc.) for the post-update updates
744                foreach ( $dbData as $k => $v ) {
745
746                    $intV = (int) $v;
747
748                    // only add if valuenot empty
749                    if ( ! is_array( $v ) && ! empty( $v ) && $v != '' && $v !== 0 && $v !== -1 && $intV !== -1 ) {
750
751                        // add to update arr
752                        $limitedData[] = array(
753                            'key'  => 'zbsqt_' . $k, // we have to add zbsqt_ here because translating from data -> limited fields
754                            'val'  => $v,
755                            'type' => $this->getTypeStr( 'zbsqt_' . $k ),
756                        );
757
758                        // add to remade $data for post-update updates
759                        $data[ $k ] = $v;
760
761                    }
762                }
763
764                // copy over
765                $limitedFields = $limitedData;
766
767            } // / if ID
768
769        } // / if do_not_update_blanks
770
771        #} ========= / OVERRIDE SETTING (Deny blank overrides) ===========
772
773        #} ========= BUILD DATA ===========
774
775            $update = false;
776        $dataArr    = array();
777        $typeArr    = array();
778
779        if ( is_array( $limitedFields ) ) {
780
781            // LIMITED FIELDS
782            $update = true;
783
784            // cycle through
785            foreach ( $limitedFields as $field ) {
786
787                // some weird case where getting empties, so added check
788                if ( ! empty( $field['key'] ) ) {
789                    $dataArr[ $field['key'] ] = $field['val'];
790                    $typeArr[]                = $field['type'];
791                }
792            }
793
794            // add update time
795            if ( ! isset( $dataArr['zbsqt_lastupdated'] ) ) {
796                $dataArr['zbsqt_lastupdated'] = time();
797                $typeArr[]                    = '%d'; }
798        } else {
799
800            // FULL UPDATE/INSERT
801
802                // UPDATE
803                $dataArr = array(
804
805                    // ownership
806                    // no need to update these (as of yet) - can't move teams etc.
807                    // 'zbs_site' => zeroBSCRM_installSite(),
808                    // 'zbs_team' => zeroBSCRM_installTeam(),
809                    // 'zbs_owner' => $owner,
810
811                    'zbsqt_title'       => $data['title'],
812                    'zbsqt_value'       => $data['value'],
813                    'zbsqt_date_str'    => $data['date_str'],
814                    'zbsqt_date'        => $data['date'],
815                    'zbsqt_content'     => $data['content'],
816                    'zbsqt_notes'       => $data['notes'],
817                    'zbsqt_currency'    => $data['currency'],
818                    'zbsqt_lastupdated' => time(),
819
820                );
821
822                $typeArr = array( // field data types
823                            // '%d',  // site
824                            // '%d',  // team
825                            // '%d',  // owner
826
827                    '%s',
828                    '%s',
829                    '%s',
830                    '%d',
831                    '%s',
832                    '%s',
833                    '%s',
834                    '%d',
835
836                );
837
838                if ( ! empty( $id ) && $id > 0 ) {
839
840                    // is update
841                    $update = true;
842
843                } else {
844
845                    // INSERT (get's few extra :D)
846                    $update               = false;
847                    $dataArr['zbs_site']  = zeroBSCRM_site();
848                    $typeArr[]            = '%d';
849                    $dataArr['zbs_team']  = zeroBSCRM_team();
850                    $typeArr[]            = '%d';
851                    $dataArr['zbs_owner'] = $owner;
852                    $typeArr[]            = '%d';
853                    if ( isset( $data['created'] ) && ! empty( $data['created'] ) && $data['created'] !== -1 ) {
854                        $dataArr['zbsqt_created'] = $data['created'];
855                        $typeArr[]                = '%d';
856                    } else {
857                        $dataArr['zbsqt_created'] = time();
858                        $typeArr[]                = '%d';
859                    }
860                }
861        }
862
863        #} ========= / BUILD DATA ===========
864
865        #} ============================================================
866        #} ========= CHECK force_uniques & not_empty & max_len ========
867
868            // if we're passing limitedFields we skip these, for now
869            // #v3.1 - would make sense to unique/nonempty check just the limited fields. #gh-145
870        if ( ! is_array( $limitedFields ) ) {
871
872            // verify uniques
873            if ( ! $this->verifyUniqueValues( $data, $id ) ) {
874                return false; // / fails unique field verify
875            }
876
877            // verify not_empty
878            if ( ! $this->verifyNonEmptyValues( $data ) ) {
879                return false; // / fails empty field verify
880            }
881        }
882
883            // whatever we do we check for max_len breaches and abbreviate to avoid wpdb rejections
884            $dataArr = $this->wpdbChecks( $dataArr );
885
886        #} ========= / CHECK force_uniques & not_empty ================
887        #} ============================================================
888
889        #} Check if ID present
890        if ( $update ) {
891
892                #} Attempt update
893            if ( $wpdb->update(
894                $ZBSCRM_t['quotetemplates'],
895                $dataArr,
896                array( // where
897                    'ID' => $id,
898                ),
899                $typeArr,
900                array( // where data types
901                    '%d',
902                )
903            ) !== false ) {
904
905                        // if passing limitedFields instead of data, we ignore the following
906                            // this doesn't work, because data is in args default as arr
907                            // if (isset($data) && is_array($data)){
908                            // so...
909                if ( ! isset( $limitedFields ) || ! is_array( $limitedFields ) || $limitedFields == -1 ) {
910                    /*
911                    // tag work?
912                    if (isset($data['tags']) && is_array($data['tags'])) $this->addUpdateQuotetemplateTags(array('id'=>$id,'tagIDs'=>$data['tags']));
913
914                    // Custom fields?
915
916                    #} Cycle through + add/update if set
917                    if (is_array($customFields)) foreach ($customFields as $cK => $cF){
918
919                        // any?
920                        if (isset($data[$cK])){
921
922                            // add update
923                            $cfID = $this->DAL()->addUpdateCustomField(array(
924                                'data'  => array(
925                                        'objtype'   => ZBS_TYPE_QUOTETEMPLATE,
926                                        'objid'     => $id,
927                                        'objkey'    => $cK,
928                                        'objval'    => $data[$cK]
929                                )));
930
931                        }
932
933                    }
934
935                    // / Custom Fields
936
937                    */
938
939                } // / if $data
940
941                        #} Any extra meta keyval pairs?
942                        // BRUTALLY updates (no checking)
943                        $confirmedExtraMeta = false;
944                if ( is_array( $extraMeta ) ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable,WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
945
946                            $confirmedExtraMeta = array();
947
948                    foreach ( $extraMeta as $k => $v ) {
949
950                        #} This won't fix stupid keys, just catch basic fails...
951                        $cleanKey = strtolower( str_replace( ' ', '_', $k ) );
952
953                        #} Brutal update
954                        // update_post_meta($postID, 'zbs_customer_extra_'.$cleanKey, $v);
955                        $this->DAL()->updateMeta( ZBS_TYPE_QUOTETEMPLATE, $id, 'extra_' . $cleanKey, $v );
956
957                        #} Add it to this, which passes to IA
958                        $confirmedExtraMeta[ $cleanKey ] = $v;
959
960                    }
961                }
962
963                        #} INTERNAL AUTOMATOR
964                        #} &
965                        #} FALLBACKS
966                        // UPDATING CONTACT
967                if ( ! $silentInsert ) {
968
969                    // IA General quotetemplate update (2.87+)
970                    zeroBSCRM_FireInternalAutomator(
971                        'quotetemplate.update',
972                        array(
973                            'id'        => $id,
974                            'againstid' => $id,
975                            'data'      => $dataArr,
976                        )
977                    );
978
979                }
980
981                        // Successfully updated - Return id
982                        return $id;
983
984            } else {
985
986                $msg = __( 'DB Update Failed', 'zero-bs-crm' );
987                $zbs->DAL->addError( 302, $this->objectType, $msg, $dataArr );
988
989                // FAILED update
990                return false;
991
992            }
993        } else {
994
995            #} No ID - must be an INSERT
996            if ( $wpdb->insert(
997                $ZBSCRM_t['quotetemplates'],
998                $dataArr,
999                $typeArr
1000            ) > 0 ) {
1001
1002                    #} Successfully inserted, lets return new ID
1003                    $newID = $wpdb->insert_id;
1004
1005                /*
1006                    // tag work?
1007                    if (isset($data['tags']) && is_array($data['tags'])) $this->addUpdateQuotetemplateTags(array('id'=>$newID,'tagIDs'=>$data['tags']));
1008
1009                    // Custom fields?
1010
1011                        #} Cycle through + add/update if set
1012                        if (is_array($customFields)) foreach ($customFields as $cK => $cF){
1013
1014                            // any?
1015                            if (isset($data[$cK])){
1016
1017                                // add update
1018                                $cfID = $this->DAL()->addUpdateCustomField(array(
1019                                    'data'  => array(
1020                                            'objtype'   => ZBS_TYPE_QUOTETEMPLATE,
1021                                            'objid'     => $newID,
1022                                            'objkey'    => $cK,
1023                                            'objval'    => $data[$cK]
1024                                    )));
1025
1026                            }
1027
1028                        }
1029
1030                    // / Custom Fields
1031
1032                    */
1033
1034                    #} Any extra meta keyval pairs?
1035                    // BRUTALLY updates (no checking)
1036                    $confirmedExtraMeta = false;
1037                if ( is_array( $extraMeta ) ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable,WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
1038
1039                        $confirmedExtraMeta = array();
1040
1041                    foreach ( $extraMeta as $k => $v ) {
1042
1043                        #} This won't fix stupid keys, just catch basic fails...
1044                        $cleanKey = strtolower( str_replace( ' ', '_', $k ) );
1045
1046                        #} Brutal update
1047                        // update_post_meta($postID, 'zbs_customer_extra_'.$cleanKey, $v);
1048                        $this->DAL()->updateMeta( ZBS_TYPE_QUOTETEMPLATE, $id, 'extra_' . $cleanKey, $v );
1049
1050                        #} Add it to this, which passes to IA
1051                        $confirmedExtraMeta[ $cleanKey ] = $v;
1052
1053                    }
1054                }
1055
1056                    #} INTERNAL AUTOMATOR
1057                    #} &
1058                    #} FALLBACKS
1059                    // NEW CONTACT
1060                if ( ! $silentInsert ) {
1061
1062                    #} Add to automator
1063                    zeroBSCRM_FireInternalAutomator(
1064                        'quotetemplate.new',
1065                        array(
1066                            'id'                   => $newID,
1067                            'data'                 => $dataArr,
1068                            // 'extsource'=>array(),
1069                            'automatorpassthrough' => $automatorPassthrough, #} This passes through any custom log titles or whatever into the Internal automator recipe.
1070                            'extraMeta'            => $confirmedExtraMeta, #} This is the "extraMeta" passed (as saved)
1071                        )
1072                    );
1073
1074                }
1075
1076                    return $newID;
1077
1078            } else {
1079
1080                $msg = __( 'DB Insert Failed', 'zero-bs-crm' );
1081                $zbs->DAL->addError( 303, $this->objectType, $msg, $dataArr );
1082
1083                #} Failed to Insert
1084                return false;
1085
1086            }
1087        }
1088
1089        return false;
1090    }
1091
1092    /**
1093     * adds or updates a quotetemplate's tags
1094     * ... this is really just a wrapper for addUpdateObjectTags
1095     *
1096     * @param array $args Associative array of arguments
1097     *              id (if update), owner, data (array of field data)
1098     *
1099     * @return int line ID
1100     */
1101    /*
1102    public function addUpdateQuotetemplateTags($args=array()){
1103
1104        global $ZBSCRM_t,$wpdb;
1105
1106        #} ============ LOAD ARGS =============
1107        $defaultArgs = array(
1108
1109            'id'            => -1,
1110
1111            // EITHER of the following:
1112            'tagIDs'        => -1,
1113            'tags'          => -1,
1114
1115            'mode'          => 'append'
1116
1117        ); foreach ($defaultArgs as $argK => $argV){ $$argK = $argV; if (is_array($args) && isset($args[$argK])) {  if (is_array($args[$argK])){ $newData = $$argK; if (!is_array($newData)) $newData = array(); foreach ($args[$argK] as $subK => $subV){ $newData[$subK] = $subV; }$$argK = $newData;} else { $$argK = $args[$argK]; } } }
1118        #} =========== / LOAD ARGS ============
1119
1120        #} ========== CHECK FIELDS ============
1121
1122            // check id
1123            $id = (int)$id; if (empty($id) || $id <= 0) return false;
1124
1125        #} ========= / CHECK FIELDS ===========
1126
1127        return $this->DAL()->addUpdateObjectTags(array(
1128                'objtype'   =>ZBS_TYPE_QUOTETEMPLATE,
1129                'objid'     =>$id,
1130                'tags'      =>$tags,
1131                'tagIDs'    =>$tagIDs,
1132                'mode'      =>$mode));
1133
1134    } */
1135
1136    /**
1137     * deletes a quotetemplate object
1138     *
1139     * @param array $args Associative array of arguments
1140     *              id
1141     *
1142     * @return int success;
1143     */
1144    public function deleteQuotetemplate( $args = array() ) {
1145
1146        global $ZBSCRM_t, $wpdb, $zbs;
1147
1148        #} ============ LOAD ARGS =============
1149        $defaultArgs = array(
1150
1151            'id'          => -1,
1152            'saveOrphans' => true,
1153
1154        );
1155        foreach ( $defaultArgs as $argK => $argV ) {
1156            $$argK = $argV;
1157            if ( is_array( $args ) && isset( $args[ $argK ] ) ) {
1158                if ( is_array( $args[ $argK ] ) ) {
1159                    $newData = $$argK;
1160                    if ( ! is_array( $newData ) ) {
1161                        $newData = array();
1162                    } foreach ( $args[ $argK ] as $subK => $subV ) {
1163                        $newData[ $subK ] = $subV;
1164                    }$$argK = $newData;
1165                } else {
1166                    $$argK = $args[ $argK ]; }
1167            }
1168        }
1169        #} =========== / LOAD ARGS ============
1170
1171        #} Check ID & Delete :)
1172        $id = (int) $id;
1173        if ( ! empty( $id ) && $id > 0 ) {
1174
1175            // delete orphans?
1176            if ( $saveOrphans === false ) {
1177
1178            }
1179
1180            return zeroBSCRM_db2_deleteGeneric( $id, 'quotetemplates' );
1181
1182        }
1183
1184        return false;
1185    }
1186
1187    /**
1188     * tidy's the object from wp db into clean array
1189     *
1190     * @param array $obj (DB obj)
1191     *
1192     * @return array quotetemplate (clean obj)
1193     */
1194    private function tidy_quotetemplate( $obj = false, $withCustomFields = false ) {
1195            global $zbs;
1196            $res = false;
1197
1198        if ( isset( $obj->ID ) ) {
1199            $res       = array();
1200            $res['id'] = $obj->ID;
1201            /*
1202            `zbs_site` INT NULL DEFAULT NULL,
1203            `zbs_team` INT NULL DEFAULT NULL,
1204            `zbs_owner` INT NOT NULL,
1205            */
1206            $res['owner'] = $obj->zbs_owner;
1207
1208            $res['title']            = wp_kses( html_entity_decode( $obj->zbsqt_title, ENT_QUOTES, 'UTF-8' ), $zbs->acceptable_restricted_html );
1209            $res['value']            = $this->stripSlashes( $obj->zbsqt_value );
1210            $res['date_str']         = $this->stripSlashes( $obj->zbsqt_date_str );
1211            $res['date']             = (int) $obj->zbsqt_date;
1212            $res['date_date']        = ( isset( $obj->zbsqt_date ) && $obj->zbsqt_date > 0 ) ? zeroBSCRM_locale_utsToDatetime( $obj->zbsqt_date ) : false;
1213            $res['content']          = $this->stripSlashes( $obj->zbsqt_content );
1214            $res['notes']            = wp_kses( html_entity_decode( $obj->zbsqt_notes, ENT_QUOTES, 'UTF-8' ), $zbs->acceptable_restricted_html );
1215            $res['currency']         = $this->stripSlashes( $obj->zbsqt_currency );
1216            $res['created']          = (int) $obj->zbsqt_created;
1217            $res['created_date']     = ( isset( $obj->zbsqt_created ) && $obj->zbsqt_created > 0 ) ? zeroBSCRM_locale_utsToDatetime( $obj->zbsqt_created ) : false;
1218            $res['lastupdated']      = (int) $obj->zbsqt_lastupdated;
1219            $res['lastupdated_date'] = ( isset( $obj->zbsqt_lastupdated ) && $obj->zbsqt_lastupdated > 0 ) ? zeroBSCRM_locale_utsToDatetime( $obj->zbsqt_lastupdated ) : false;
1220
1221            // custom fields - tidy any that are present:
1222            if ( $withCustomFields ) {
1223                $res = $this->tidyAddCustomFields( ZBS_TYPE_QUOTETEMPLATE, $obj, $res, false );
1224            }
1225        }
1226
1227        return $res;
1228    }
1229
1230    /**
1231     * Wrapper, use $this->getQuotetemplateMeta($contactID,$key) for easy retrieval of singular quotetemplate
1232     * Simplifies $this->getMeta
1233     *
1234     * @param int objtype
1235     * @param int objid
1236     * @param string key
1237     *
1238     * @return array quotetemplate meta result
1239     */
1240    public function getQuotetemplateMeta( $id = -1, $key = '', $default = false ) {
1241
1242        global $zbs;
1243
1244        if ( ! empty( $key ) ) {
1245
1246            return $this->DAL()->getMeta(
1247                array(
1248
1249                    'objtype'     => ZBS_TYPE_QUOTETEMPLATE,
1250                    'objid'       => $id,
1251                    'key'         => $key,
1252                    'fullDetails' => false,
1253                    'default'     => $default,
1254                    'ignoreowner' => true, // for now !!
1255
1256                )
1257            );
1258
1259        }
1260
1261        return $default;
1262    }
1263
1264    /**
1265     * Returns an ownerid against a quotetemplate
1266     *
1267     * @param int id quotetemplate ID
1268     *
1269     * @return int quotetemplate owner id
1270     */
1271    public function getQuotetemplateOwner( $id = -1 ) {
1272
1273        global $zbs;
1274
1275        $id = (int) $id;
1276
1277        if ( $id > 0 ) {
1278
1279            return $this->DAL()->getFieldByID(
1280                array(
1281                    'id'          => $id,
1282                    'objtype'     => ZBS_TYPE_QUOTETEMPLATE,
1283                    'colname'     => 'zbs_owner',
1284                    'ignoreowner' => true,
1285                )
1286            );
1287
1288        }
1289
1290        return false;
1291    }
1292
1293    /**
1294     * remove any non-db fields from the object
1295     * basically takes array like array('owner'=>1,'fname'=>'x','fullname'=>'x')
1296     * and returns array like array('owner'=>1,'fname'=>'x')
1297     * This does so based on the objectModel!
1298     *
1299     * @param array $obj (clean obj)
1300     *
1301     * @return array (db ready arr)
1302     */
1303    private function db_ready_quotetemplate( $obj = false ) {
1304
1305        // use the generic? (override here if necessary)
1306        return $this->db_ready_obj( $obj );
1307    }
1308
1309    /**
1310     * Takes full object and makes a "list view" boiled down version
1311     * Used to generate listview objs
1312     *
1313     * @param array $obj (clean obj)
1314     *
1315     * @return array (listview ready obj)
1316     */
1317    public function listViewObj( $quotetemplate = false, $columnsRequired = array() ) {
1318
1319        if ( is_array( $quotetemplate ) && isset( $quotetemplate['id'] ) ) {
1320
1321            $resArr = $quotetemplate;
1322
1323            return $resArr;
1324
1325        }
1326
1327        return false;
1328    }
1329
1330    // ===========  /   QUOTETEMPLATE  =======================================================
1331    // ===============================================================================
1332}