FinanCalc::populateFactoryClassesArray()   B
last analyzed

Complexity

Conditions 6
Paths 7

Size

Total Lines 36
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 1 Features 2
Metric Value
c 5
b 1
f 2
dl 0
loc 36
rs 8.439
cc 6
eloc 24
nc 7
nop 0
1
<?php
2
/**
3
 * FinanCalc
4
 *
5
 * A lightweight, simple and easy PHP library for calculating annuities (e.g., mortgages)
6
 * and other financial instruments according to various input data
7
 *
8
 *
9
 * DISCLAIMER
10
 * You are free to use/modify/extend the library as you please - for it to serve your purpose.
11
 * As per the (un)license, the software is provided as is and the original author cannot be held liable
12
 * for any losses/damages directly or indirectly resulting from using thereof.
13
 * Attribution is welcome, but certainly not required.
14
 *
15
 * NOTE
16
 * The library is currently work-in-progress and it is certain that new features will be added in the process.
17
 * Consider this, therefore, as a preview product prone to abrupt and extensive changes that may affect functionality
18
 * of an external code adapted to a prior version(s) of the library.
19
 * Always explore the provisional compatibility of the library with your project in case you upgrade to a new version
20
 * of the library (by means of an extensive testing of the code in which you are exerting the library's features).
21
 *
22
 * PREREQUISITES
23
 * PHP 5.5+
24
 * Module php-bcmath
25
 *
26
 * @author Václav Uruba
27
 * @version 0.3
28
 * @license http://unlicense.org The Unlicense
29
 */
30
namespace FinanCalc {
31
32
    use Exception;
33
    use FinanCalc\Constants\ErrorMessages;
34
    use FinanCalc\Interfaces\Calculator\CalculatorFactoryAbstract;
35
    use FinanCalc\Utils\Config;
36
    use ReflectionClass;
37
    use ReflectionException;
38
39
    /**
40
     * Class FinanCalc
41
     * @package FinanCalc
42
     */
43
    final class FinanCalc
44
    {
45
        private $factoryClasses = array();
46
        private static $instance = null;
47
48
        /**
49
         *
50
         * Serve the class as a singleton
51
         *
52
         */
53
54
        private function __construct()
55
        {
56
            $this->populateFactoryClassesArray();
57
        }
58
59
        protected function __clone()
60
        {
61
            // we do not want the singleton object to be cloned
62
        }
63
64
        /**
65
         * @return FinanCalc
66
         */
67
        public static function getInstance()
68
        {
69
            if (self::$instance === null) {
70
                self::$instance = new FinanCalc();
71
            }
72
            return self::$instance;
73
        }
74
75
        /**
76
         * @return string
77
         */
78
        public static function getPath()
79
        {
80
            return __DIR__;
81
        }
82
83
        /**
84
         *
85
         * Business logic IMPLEMENTATION
86
         *
87
         */
88
89
        /**
90
         * @return CalculatorFactoryAbstract[]
91
         */
92
        public function getFactories()
93
        {
94
            return $this->factoryClasses;
95
        }
96
97
        /**
98
         * @param $factoryClassName
99
         * @return CalculatorFactoryAbstract
100
         * @throws Exception
101
         */
102
        public function getFactory($factoryClassName)
103
        {
104
            if (array_key_exists($factoryClassName, $this->factoryClasses)) {
105
                return $this->factoryClasses[$factoryClassName];
106
            } else {
107
                throw new Exception(ErrorMessages::getFactoryClassNotInitializedMessage($factoryClassName));
108
            }
109
        }
110
111
        /**
112
         * @param $configArray
113
         */
114
        public function setConfig($configArray = null)
115
        {
116
            Config::init($configArray);
117
        }
118
119
        /**
120
         *
121
         * PRIVATE functions
122
         *
123
         */
124
125
        private function populateFactoryClassesArray()
126
        {
127
            $factoryFiles = glob(FinanCalc::getPath() . Config::getConfigField('factories_relative_path') . '/*.php');
128
            $factoriesNamespace = Config::getConfigField('factories_namespace');
129
130
            foreach ($factoryFiles as $factoryFile) {
131
                $factoryFileContents = file_get_contents($factoryFile);
132
                $fileTokens = token_get_all($factoryFileContents);
133
134
                $numTokens = count($fileTokens);
135
                for ($i = 2; $i < $numTokens; $i++) {
136
                    if ($fileTokens[$i - 2][0] == T_CLASS) {
137
                        $factoryClassName = $fileTokens[$i][1];
138
                        try {
139
                            /** @noinspection PhpIncludeInspection */
140
                            require_once($factoryFile);
141
                            $factoryClassReflector = new ReflectionClass($factoriesNamespace . '\\' . $factoryClassName);
142
                        } catch (ReflectionException $e) {
143
                            error_log(ErrorMessages::getFactoryClassExpectedInNamespaceMessage($factoryClassName,
144
                                $factoriesNamespace));
145
                            continue;
146
                        }
147
148
                        $factoryAbstractClass = 'FinanCalc\\Interfaces\\Calculator\\CalculatorFactoryAbstract';
149
150
                        if ($factoryClassReflector->isSubclassOf($factoryAbstractClass)) {
151
                            $this->factoryClasses[$factoryClassName] = $factoryClassReflector->newInstance();
152
                            break;
153
                        } else {
154
                            error_log(ErrorMessages::getFactoryClassExpectedAncestorMessage($factoryClassName,
155
                                $factoryAbstractClass));
156
                        }
157
                    }
158
                }
159
            }
160
        }
161
    }
162
163
164
}
165