Passed
Push — 1.0.x ( 8353d5...3a2c37 )
by Julien
21:28
created

Model::appendModelName()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
cc 5
eloc 9
c 0
b 0
f 0
nc 4
nop 2
dl 0
loc 18
ccs 0
cts 10
cp 0
crap 30
rs 9.6111
1
<?php
2
3
/**
4
 * This file is part of the Zemit Framework.
5
 *
6
 * (c) Zemit Team <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE.txt
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Zemit\Mvc\Controller\Traits;
13
14
use Phalcon\Mvc\ModelInterface;
15
use Zemit\Mvc\Controller\Traits\Abstracts\AbstractInjectable;
16
use Zemit\Mvc\Controller\Traits\Abstracts\AbstractModel;
17
18
trait Model
19
{
20
    use AbstractModel;
21
    
22
    use AbstractInjectable;
23
    
24
    /**
25
     * The name of the model.
26
     * @var ?string
27
     */
28
    protected ?string $modelName;
29
    
30
    /**
31
     * The namespaces for the model lookup.
32
     * @var string[]
33
     */
34
    protected ?array $modelNamespaces;
35
    
36
    /**
37
     * Retrieves the name of the model associated with the controller.
38
     *
39
     * @return string|null The name of the model associated with the controller, or null if not found.
40
     */
41
    public function getModelName(): ?string
42
    {
43
        if (!isset($this->modelName)) {
44
            $this->modelName = $this->getModelNameFromController();
45
        }
46
        
47
        return $this->modelName;
48
    }
49
    
50
    /**
51
     * Sets the name of the model to be used.
52
     *
53
     * @param string|null $modelName The name of the model to be set.
54
     *
55
     * @return void
56
     */
57
    public function setModelName(?string $modelName): void
58
    {
59
        $this->modelName = $modelName;
60
    }
61
    
62
    /**
63
     * Gets the namespaces used for the model lookup.
64
     * If no model namespace is set, the namespaces defined in the loader will be returned.
65
     *
66
     * @return array The namespaces used for the model lookup.
67
     */
68
    public function getModelNamespaces(): array
69
    {
70
        if (!isset($this->modelNamespaces)) {
71
            $this->modelNamespaces = $this->loader->getNamespaces();
72
        }
73
        
74
        return $this->modelNamespaces ?? [];
75
    }
76
    
77
    /**
78
     * Set the namespaces for the models.
79
     *
80
     * @param array|null $modelNamespaces The array of namespaces for the models.
81
     *
82
     * @return void
83
     */
84
    public function setModelNamespaces(?array $modelNamespaces): void
85
    {
86
        $this->modelNamespaces = $modelNamespaces;
87
    }
88
    
89
    /**
90
     * Retrieves the model name from the controller by following certain naming conventions.
91
     *
92
     * @param array|null $namespaces Optional. An array of namespaces to search for the model. Default is null and will use $this->getModelNamespaces().
93
     * @param string $needle Optional. The keyword to search for in the namespace. Default is 'Models'.
94
     * 
95
     * @return string|null The model name if found, otherwise null.
96
     */
97
    public function getModelNameFromController(?array $namespaces = null, string $needle = 'Models'): ?string
98
    {
99
        $model = ucfirst(
100
            $this->helper->camelize(
101
                $this->helper->uncamelize(
102
                    $this->getControllerName()
103
                )
104
            )
105
        );
106
        
107
        if (class_exists($model)) {
108
            return $model;
109
        }
110
        
111
        $namespaces ??= $this->getModelNamespaces();
112
        foreach ($namespaces as $namespace => $path) {
113
            if (str_contains($namespace, $needle)) {
114
                $possibleModel = $namespace . $model;
115
                if (class_exists($possibleModel) && is_subclass_of($possibleModel, ModelInterface::class)) {
116
                    return $possibleModel;
117
                }
118
            }
119
        }
120
        
121
        return null;
122
    }
123
    
124
    /**
125
     * Returns the name of the controller.
126
     *
127
     * If the controller name is not set in the dispatcher, it extracts the controller name from the class name
128
     * of the current instance.
129
     *
130
     * @return string The name of the controller.
131
     */
132
    public function getControllerName(): string
133
    {
134
        return $this->dispatcher->getControllerName()
135
            ?: substr(basename(str_replace('\\', '/', get_class($this))), 0, -10);
136
    }
137
    
138
    /**
139
     * Loads a model by its name using the modelsManager.
140
     *
141
     * @param string|null $modelName The name of the model to load. Default is null and will use $this->getModelName().
142
     * 
143
     * @return ModelInterface The loaded model.
144
     */
145
    public function loadModel(?string $modelName = null): ModelInterface
146
    {
147
        $modelName ??= $this->getModelName() ?? '';
148
        return $this->modelsManager->load($modelName);
149
    }
150
    
151
    /**
152
     * Appends the model name to the specified field string, if not already present.
153
     *
154
     * @param string $field The field string to append the model name to.
155
     * @param string|null $modelName The name of the model to append. If null, the default model name will be used.
156
     *
157
     * @return string The modified field string with the model name appended.
158
     */
159
    public function appendModelName(string $field, ?string $modelName = null): string
160
    {
161
        $modelName ??= $this->getModelName();
162
        
163
        if (empty($field)) {
164
            return $field;
165
        }
166
        
167
        // Add the current model name by default
168
        $explode = explode(' ', $field);
169
        if (!strpos($field, '.') !== false) {
170
            $field = trim('[' . $modelName . '].[' . array_shift($explode) . '] ' . implode(' ', $explode));
171
        }
172
        else if (!str_contains($field, ']') && !str_contains($field, '[')) {
173
            $field = trim('[' . implode('].[', explode('.', array_shift($explode))) . ']' . implode(' ', $explode));
174
        }
175
        
176
        return $field;
177
    }
178
}
179