Passed
Push — master ( a1c19a...54b258 )
by Laurent
02:07
created

Func_App::mailTo()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 4
eloc 9
c 2
b 0
f 0
nc 8
nop 3
dl 0
loc 15
rs 9.9666
1
<?php
2
//-------------------------------------------------------------------------
3
// OVIDENTIA http://www.ovidentia.org
4
// Ovidentia is free software; you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation; either version 2, or (at your option)
7
// any later version.
8
//
9
// This program is distributed in the hope that it will be useful, but
10
// WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
// See the GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with this program; if not, write to the Free Software
16
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17
// USA.
18
//-------------------------------------------------------------------------
19
/**
20
 * @license http://opensource.org/licenses/gpl-license.php GNU General Public License (GPL)
21
 * @copyright Copyright (c) 2018 by CANTICO ({@link http://www.cantico.fr})
22
 */
23
24
require_once dirname(__FILE__) . '/define.php';
25
require_once dirname(__FILE__) . '/functions.php';
26
27
28
spl_autoload_register(array(app_App(), 'loadObject'));
29
30
/**
31
 * Provides extensible functionalities to manage an application.
32
 */
33
class Func_App extends bab_Functionality
34
{
35
    public $addonPrefix;
36
    public $classPrefix;
37
    public $addonName;
38
    public $controllerTg;
39
    public $phpPath;
40
    public $recordSetPath;
41
    public $ctrlPath;
42
    public $uiPath;
43
44
45
    /**
46
     * @var string
47
     */
48
    private $language = null;
49
50
51
    public function __construct()
52
    {
53
        $this->addonName = 'libapp';
54
        $this->addonPrefix = 'app';
55
56
        $this->classPrefix = $this->addonPrefix . '_';
57
        $this->controllerTg = 'addon/' . $this->addonName . '/main';
58
59
        $addon = bab_getAddonInfosInstance($this->addonName);
60
        $this->phpPath = $addon->getPhpPath();
61
        $this->recordSetPath = $this->phpPath;
62
        $this->ctrlPath = $this->phpPath;
63
        $this->uiPath = $this->phpPath . 'ui/';
64
65
        $babDB = bab_getDB();
66
67
        $LibOrm = bab_Functionality::get('LibOrm');
68
        /*@var $LibOrm Func_LibOrm */
69
70
        $LibOrm->initMysql();
71
        ORM_RecordSet::setBackend(new ORM_MySqlBackend($babDB));
72
    }
73
74
75
    /**
76
     * @param string $class
77
     * @return boolean
78
     */
79
    public function loadObject($class)
80
    {
81
        $classPrefix = $this->classPrefix;
82
83
        if (substr($class, 0, strlen($classPrefix)) === $classPrefix) {
84
            if (substr($class, -3) === 'Set') {
85
                $pathname = $this->getRecordSetPathname($class);
86
                if (file_exists($pathname)) {
87
                    require $pathname;
88
                    return true;
89
                }
90
            } else {
91
                $pathname = $this->getRecordPathname($class);
92
                if (file_exists($pathname)) {
93
                    require $pathname;
94
                    return true;
95
                }
96
            }
97
        }
98
        return false;
99
    }
100
101
    /**
102
     * Returns the expected pathname for the file containing the definition of the record set class.
103
     *
104
     * @param string $class
105
     * @return string
106
     */
107
    public function getRecordSetPathname($class)
108
    {
109
        // $App->MyRecordSet() -> myrecord.class.php
110
        $file = strtolower(substr($class, strlen($this->classPrefix), -3)) . '.class.php';
111
        return $this->recordSetPath . $file;
112
    }
113
114
    /**
115
     *  Returns the expected pathname for the file containing the definition of the record class.
116
     *
117
     * @param string $class
118
     * @return string
119
     */
120
    public function getRecordPathname($class)
121
    {
122
        // $App->MyRecord() -> myrecord.class.php
123
        $file = strtolower(substr($class, strlen($this->classPrefix))) . '.class.php';
124
        return $this->recordSetPath . $file;
125
    }
126
127
    /**
128
     * @return string
129
     */
130
    public function getUiPath()
131
    {
132
        return APP_UI_PATH;
133
    }
134
135
    /**
136
     * @return string
137
     */
138
    public function getSetPath()
139
    {
140
        return APP_SET_PATH;
141
    }
142
143
    /**
144
     * @return string
145
     */
146
    public function getCtrlPath()
147
    {
148
        return APP_CTRL_PATH;
149
    }
150
151
    /**
152
     * @return string
153
     */
154
    public function getPhpPath()
155
    {
156
        return APP_PHP_PATH;
157
    }
158
159
160
    /**
161
     * @return string
162
     *
163
     */
164
    public function getDescription()
165
    {
166
        return 'Application framework.';
167
    }
168
169
170
    /**
171
     * Get the addon name
172
     * @return string
173
     */
174
    public function getAddonName()
175
    {
176
        return $this->addonName;
177
    }
178
179
180
    /**
181
     * @return bab_addonInfos
182
     */
183
    public function getAddon()
184
    {
185
        return bab_getAddonInfosInstance($this->getAddonName());
186
    }
187
188
189
    /**
190
     * Register myself as a functionality.
191
     *
192
     */
193
    public static function register()
194
    {
195
        require_once $GLOBALS['babInstallPath'].'utilit/functionalityincl.php';
196
        $functionalities = new bab_functionalities();
0 ignored issues
show
Unused Code introduced by
The assignment to $functionalities is dead and can be removed.
Loading history...
197
198
        $addon = bab_getAddonInfosInstance('libapp');
199
200
        $addon->registerFunctionality('App', 'app.php');
201
    }
202
203
204
    /**
205
     * Synchronize sql tables for all classes found in Application object
206
     * using methods  'includeXxxxxClassName'
207
     * sychronize if the two correspond methods are met and the set classname match the prefix from parameter
208
     * do not synchronize if the set method has a VueSet suffix, in this case the table si juste a readonly vue
209
     *
210
     * @param	string	$prefix		tables and classes prefix
211
     * @return bab_synchronizeSql
212
     */
213
    public function synchronizeSql($prefix)
214
    {
215
        if (!$prefix) {
216
            return null;
217
        }
218
219
        require_once $GLOBALS['babInstallPath'].'utilit/devtools.php';
220
        $mysqlbackend = new ORM_MySqlBackend($GLOBALS['babDB']);
221
        $sql = 'SET FOREIGN_KEY_CHECKS=0;
222
            ';
223
224
        foreach (get_class_methods($this) as $method) {
225
226
            if (substr($method, 0, 7) === 'include' && substr($method, -3) === 'Set') {
227
                $incl = $method;
228
                $classNameMethod = substr($method, strlen('include')) . 'ClassName';
229
230
231
                $classname = $this->$classNameMethod();
232
233
                if ($prefix === substr($classname, 0, strlen($prefix))
234
                  && 'Set' === substr($classname, -3)
235
                  && 'ViewSet' !== substr($classname, -7)) {
236
                    if (method_exists($this, $incl)) {
237
                        $this->$incl();
238
239
                        $call = substr($classname, strlen($prefix));
240
241
                        if (class_exists($classname)) {
242
243
                            /* @var $set ORM_RecordSet */
244
                            $set = $this->$call();
245
                            if (method_exists($set, 'useLang')) {
246
                                // This is necessary if the recordSet constructor uses a setLang().
247
                                // We need to revert to multilang fields before synchronizing.
248
                                $set->useLang(false);
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type string expected by parameter $language of ORM_RecordSet::useLang(). ( Ignorable by Annotation )

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

248
                                $set->useLang(/** @scrutinizer ignore-type */ false);
Loading history...
249
                            }
250
                            $sql .= $mysqlbackend->setToSql($set) . "\n";
251
                        }
252
                    }
253
                }
254
            }
255
        }
256
257
        require_once $GLOBALS['babInstallPath'].'utilit/devtools.php';
258
        $synchronize = new bab_synchronizeSql();
259
260
        $synchronize->fromSqlString($sql);
261
262
        return $synchronize;
263
    }
264
265
266
267
    public function getSynchronizeSql($prefix)
268
    {
269
        if (!$prefix) {
270
            return null;
271
        }
272
273
        require_once $GLOBALS['babInstallPath'].'utilit/devtools.php';
274
        $mysqlbackend = new ORM_MySqlBackend($GLOBALS['babDB']);
275
        $sql = '';
276
277
        foreach (get_class_methods($this) as $method) {
278
279
            if (substr($method, 0, strlen('include')) === 'include' && substr($method, -strlen('Set')) === 'Set') {
280
                $incl = $method;
281
                $classNameMethod = substr($method, strlen('include')) . 'ClassName';
282
283
                $classname = $this->$classNameMethod();
284
285
                if ($prefix === substr($classname, 0, strlen($prefix))
286
                    && 'Set' === substr($classname, -3)
287
                    && 'ViewSet' !== substr($classname, -6)
288
                    ) {
289
                        if (method_exists($this, $incl)) {
290
                            $this->$incl();
291
                            $call = substr($classname, strlen($prefix));
292
293
                            if (class_exists($classname) && method_exists($this, $call)) {
294
                                $set = $this->$call();
295
                                $sql .= $mysqlbackend->setToSql($set) . "\n";
296
                            }
297
                        }
298
                    }
299
            }
300
        }
301
302
        return $sql;
303
    }
304
305
306
307
    public function includeBase()
308
    {
309
        require_once APP_PHP_PATH . 'base.class.php';
310
    }
311
312
    /**
313
     * Includes app_RecordSet class definition.
314
     */
315
    public function includeRecordSet()
316
    {
317
        require_once APP_SET_PATH . 'record.class.php';
318
    }
319
320
321
    /**
322
     * Includes app_TraceableRecordSet class definition.
323
     */
324
    public function includeTraceableRecordSet()
325
    {
326
        require_once APP_SET_PATH . 'traceablerecord.class.php';
327
    }
328
329
330
331
    //Link
332
333
    /**
334
     * Includes LinkSet class definition.
335
     */
336
    public function includeLinkSet()
337
    {
338
        require_once APP_SET_PATH . 'link.class.php';
339
    }
340
341
    /**
342
     * @return string
343
     */
344
    public function LinkClassName()
345
    {
346
        return 'app_Link';
347
    }
348
349
    /**
350
     * @return string
351
     */
352
    public function LinkSetClassName()
353
    {
354
        return $this->LinkClassName() . 'Set';
355
    }
356
357
    /**
358
     * @return app_LinkSet
359
     */
360
    public function LinkSet()
361
    {
362
        $this->includeLinkSet();
363
        $className = $this->LinkSetClassName();
364
        $set = new $className($this);
365
        return $set;
366
    }
367
368
369
370
371
372
373
374
    /**
375
     * Returns the app_Record corresponding to the specified
376
     * reference $ref.
377
     *
378
     * @param string 	$ref	A reference string (e.g. Contact:12)
379
     * @return app_Record	or null if no corresponding record is found.
380
     */
381
    public function getRecordByRef($ref)
382
    {
383
        $refParts = explode(':', $ref);
384
        if (count($refParts) !== 2) {
385
            return null;
386
        }
387
        list($classname, $id) = $refParts;
388
        $classSet = $classname . 'Set';
389
        $set = $this->$classSet();
390
        if (isset($set)) {
391
            return $set->get($id);
392
        }
393
        return null;
394
    }
395
396
    /**
397
     * Returns the reference corresponding to the specified
398
     * app_Record $record (e.g. Contact:12 or Deal:125)
399
     *
400
     * @param app_Record	$record
401
     * @return string
402
     */
403
    public function getRecordRef(app_Record $record)
404
    {
405
        $fullClassName = get_class($record);
406
        list(, $className) = explode('_', $fullClassName);
407
        return $className . ':' . $record->id;
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on app_Record. Since you implemented __get, consider adding a @property annotation.
Loading history...
408
    }
409
410
411
    /**
412
     * Specifies the language to use for translation.
413
     *
414
     * If $language is null, the language is reset to
415
     * the current logged user language.
416
     *
417
     * @param string|null $language
418
     */
419
    public function setTranslateLanguage($language)
420
    {
421
        $this->language = $language;
422
    }
423
424
425
426
    /**
427
     * Translates the string.
428
     *
429
     * @param string $str
430
     * @return string
431
     */
432
    public function translate($str, $str_plurals = null, $number = null)
433
    {
434
        require_once APP_PHP_PATH . 'functions.php';
435
        $translation = $str;
436
        if ($translate = bab_functionality::get('Translate/Gettext')) {
437
            /* @var $translate Func_Translate_Gettext */
438
            $translate->setAddonName('libapp');
439
            $translation = $translate->translate($str, $str_plurals, $number);
440
        }
441
442
        return $translation;
443
    }
444
445
    /**
446
     * @param string    $str
447
     * @param string    $str_plurals
448
     * @param int       $number
449
     * @return string
450
     */
451
    public function translatable($str, $str_plurals = null, $number = null)
452
    {
453
        return $str;
454
    }
455
456
    /**
457
     * Translates all the string in an array and returns a new array.
458
     *
459
     * @param array $arr
460
     * @return array
461
     */
462
    public function translateArray($arr)
463
    {
464
        $newarr = $arr;
465
466
        foreach ($newarr as &$str) {
467
            $str = $this->translate($str);
468
        }
469
        return $newarr;
470
    }
471
472
473
474
    /**
475
     * Returns a link for writting an email to the specified email address.
476
     *
477
     * @param string $addr
478
     * @param string $subject
479
     * @param string $body
480
     *
481
     * @return string
482
     */
483
    public function mailTo($addr, $subject = null, $body = null)
484
    {
485
        $mailTo = 'mailto:' . $addr;
486
        $parameters = array();
487
        if (isset($subject)) {
488
            $parameters[] = 'subject=' . $subject;
489
        }
490
        if (isset($body)) {
491
            $parameters[] = 'body=' . $body;
492
        }
493
        if (!empty($parameters)) {
494
            $mailTo .= '?' . implode('&', $parameters);
495
        }
496
497
        return $mailTo;
498
    }
499
500
501
502
    /**
503
     * Format a number for display
504
     *
505
     * @param   float|string|null   $number     Numeric value with decimal
506
     * @return string
507
     */
508
    public function numberFormat($number, $decimals = 2)
509
    {
510
        if (is_null($number)) {
511
            return '#,##';
512
        }
513
514
        $number = number_format(floatval($number), $decimals, ',', ' ');
515
        return str_replace(' ', bab_nbsp(), $number);
516
    }
517
518
519
    /**
520
     * Format a number with an optional unit.
521
     *
522
     * If the value is >= 1000 the value is shortened and the corresponding prexif (k or M) is used.
523
     *
524
     * @param float|string|null $number
525
     * @param string $unitSymbol    (For example $, m2, Wh)
526
     * @param int $decimals
527
     * @return string|mixed
528
     */
529
    public function shortFormatWithUnit($number, $unitSymbol = '', $decimals = 2)
530
    {
531
        if (is_null($number)) {
532
            return '#,##';
533
        }
534
535
        $prefix = '';
536
        if ($number >= 1000000) {
537
            $number /= 1000000;
538
            $prefix = 'M';
539
        } elseif ($number >= 1000) {
540
            $number /= 1000;
541
            $prefix = 'k';
542
        }
543
544
        $number = number_format($number, $decimals, ',', ' ');
0 ignored issues
show
Bug introduced by
It seems like $number can also be of type string; however, parameter $number of number_format() does only seem to accept double, maybe add an additional type check? ( Ignorable by Annotation )

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

544
        $number = number_format(/** @scrutinizer ignore-type */ $number, $decimals, ',', ' ');
Loading history...
545
        return str_replace(' ', bab_nbsp(), $number . ' ' . $prefix . $unitSymbol);
546
    }
547
548
549
    /**
550
     * Reformat a phone number in the specified format.
551
     *
552
     * @param string    $phone      The phone number to be formatted
553
     * @param int       $format     The format the phone number should be formatted into
554
     *
555
     * @return string               The formatted phone number
556
     */
557
    public function phoneNumberFormat($phone, $format = null)
558
    {
559
        $PhoneNumber = bab_Functionality::get('PhoneNumber');
560
        if ($PhoneNumber === false) {
0 ignored issues
show
introduced by
The condition $PhoneNumber === false is always false.
Loading history...
561
            return $phone;
562
        }
563
564
        if (!isset($format)) {
565
            $format = bab_registry::get('/' . $this->addonName . '/numberFormat', $PhoneNumber->getDefaultFormat());
0 ignored issues
show
Bug introduced by
The method getDefaultFormat() does not exist on bab_functionality. It seems like you code against a sub-type of bab_functionality such as Func_App. ( Ignorable by Annotation )

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

565
            $format = bab_registry::get('/' . $this->addonName . '/numberFormat', $PhoneNumber->/** @scrutinizer ignore-call */ getDefaultFormat());
Loading history...
566
        }
567
        $phoneNumberUtil = $PhoneNumber->PhoneNumberUtil();
0 ignored issues
show
Bug introduced by
The method PhoneNumberUtil() does not exist on bab_functionality. It seems like you code against a sub-type of bab_functionality such as Func_App. ( Ignorable by Annotation )

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

567
        /** @scrutinizer ignore-call */ 
568
        $phoneNumberUtil = $PhoneNumber->PhoneNumberUtil();
Loading history...
568
569
        try {
570
            $phoneNumber = $phoneNumberUtil->parse($phone, 'FR');
571
            $phone = $phoneNumberUtil->format($phoneNumber, $format);
572
        } catch (\libphonenumber\NumberParseException $e) {
0 ignored issues
show
Bug introduced by
The type libphonenumber\NumberParseException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
573
        }
574
575
        return $phone;
576
    }
577
578
579
580
581
    /**
582
     * Includes Controller class definition.
583
     */
584
    public function includeController()
585
    {
586
        require_once APP_PHP_PATH . '/controller.class.php';
587
    }
588
589
590
    /**
591
     * Includes RecordController class definition.
592
     */
593
    public function includeRecordController()
594
    {
595
        require_once APP_CTRL_PATH . '/record.ctrl.php';
596
    }
597
598
599
    /**
600
     * Instanciates the controller.
601
     *
602
     * @return app_Controller
603
     */
604
    public function Controller()
605
    {
606
        $this->includeController();
607
        return bab_getInstance($this->classPrefix.'Controller')->setApp($this);
608
    }
609
610
611
    /**
612
     * Instanciates a controller class.
613
     *
614
     * @return bab_Controller
615
     */
616
    public function ControllerProxy($className, $proxy = true)
617
    {
618
        $this->includeController();
619
620
        if ($proxy) {
621
            return app_Controller::getProxyInstance($this, $className);
622
        }
623
624
        return new $className($this);
625
    }
626
627
628
629
    /**
630
     * Include class app_Ui
631
     *
632
     */
633
    public function includeUi()
634
    {
635
        require_once APP_UI_PATH . 'ui.class.php';
636
    }
637
638
639
    /**
640
     * The app_Ui object propose an access to all ui files and ui objects (widgets)
641
     *
642
     * @return app_Ui
643
     */
644
    public function Ui()
645
    {
646
        $this->includeUi();
647
        return bab_getInstance($this->classPrefix . 'Ui');//->setApp($this);
648
    }
649
650
651
652
    protected function includeAccess()
653
    {
654
        require_once WORKSPACE_PHP_PATH . '/access.class.php';
0 ignored issues
show
Bug introduced by
The constant WORKSPACE_PHP_PATH was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
655
    }
656
657
658
659
660
661
    /**
662
     * Get upload path
663
     * if the method return null, no upload functionality
664
     *
665
     * @return bab_Path
666
     */
667
    public function getUploadPath()
668
    {
669
        require_once $GLOBALS['babInstallPath'].'utilit/path.class.php';
670
        return new bab_Path(bab_getAddonInfosInstance($this->getAddonName())->getUploadPath());
671
    }
672
673
674
    /**
675
     *
676
     * @param string $name
677
     * @param mixed $arguments
678
     * @return mixed
679
     */
680
    public function __call($name, $arguments)
681
    {
682
        switch (true) {
683
684
            case substr($name, -strlen('SetClassName')) === 'SetClassName':
685
                $setName = substr($name, 0, strlen($name) - strlen('ClassName'));
686
                return $this->classPrefix . $setName;
687
688
            case substr($name, -strlen('ClassName')) === 'ClassName':
689
                $recordName = substr($name, 0, strlen($name) - strlen('ClassName'));
690
                return $this->classPrefix . $recordName;
691
692
            case substr($name, 0, strlen('include')) === 'include' && substr($name, -strlen('Set')) === 'Set':
693
                $fileNameBase = strtolower(substr(substr($name, 0, strlen($name) - strlen('Set')), strlen('include')));
694
                require_once PHP_SET_PATH . $fileNameBase . '.class.php';
0 ignored issues
show
Bug introduced by
The constant PHP_SET_PATH was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
695
                return;
696
697
            case substr($name, -strlen('Set')) === 'Set':
698
                $includeMethod = 'include' . $name;
699
                $this->$includeMethod();
700
                $setClassNameMethod = $name . 'ClassName';
701
                $className = $this->$setClassNameMethod();
702
                $set = new $className($this);
703
                return $set;
704
705
                //case method_exists($this, $name . 'Set'):
706
            default:
707
                $setName = $name . 'Set';
708
                $recordClassNameMethod = $name . 'ClassName';
709
                $recordClassName = $this->$recordClassNameMethod();
710
                if (isset($arguments[0])) {
711
                    if ($arguments[0] instanceof $recordClassName) {
712
                        return $arguments[0];
713
                    }
714
                    $set = $this->$setName();
715
                    return $set->get($arguments[0]);
716
                }
717
                return null;
718
        }
719
    }
720
721
722
    /**
723
     * Test if this App implementation handles the specified object class.
724
     *
725
     * The default is to consider that an object Xxxx implemented if the includeXxxxSet() method is
726
     * declared public on this App.
727
     *
728
     * @param	string	$objectClassName		App object name (eg. 'Contact' or 'CatalogItem')
729
     * @return bool
730
     */
731
    public function __isset($objectClassName)
732
    {
733
        if (null === $this->implementedObjects) {
734
735
            $this->implementedObjects = array();
0 ignored issues
show
Bug Best Practice introduced by
The property implementedObjects does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
736
737
            $className = get_class($this);
738
            $rClass = new ReflectionClass($className);
739
740
            foreach ($rClass->getMethods(ReflectionMethod::IS_PUBLIC) as $m) {
741
742
                // We consider object Xxxx implemented if the includeXxxxSet() method is
743
                // declared public on this.
744
745
                if ($m->getDeclaringClass()->name !== $className) {
746
                    // The method is declared on an ancestor class.
747
                    continue;
748
                }
749
750
                if (substr($m->name, 0, 7) === 'include' && substr($m->name, -3) === 'Set') {
751
                    $this->implementedObjects[substr($m->name, 7, -3)] = 1;
752
                }
753
            }
754
        }
755
756
        return isset($this->implementedObjects[$objectClassName]);
757
    }
758
}
759
760