DescribableTrait::metadataIdent()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Charcoal\Model;
4
5
use RuntimeException;
6
use InvalidArgumentException;
7
8
// From 'charcoal-core'
9
use Charcoal\Model\MetadataInterface;
10
use Charcoal\Model\Service\MetadataLoader;
11
12
/**
13
 * Default implementation, as trait, of the `DescribableInterface`.
14
 */
15
trait DescribableTrait
16
{
17
    /**
18
     * @var MetadataLoader $metadataLoader
19
     */
20
    protected $metadataLoader = null;
21
22
    /**
23
     * @var MetadataInterface $metadata
24
     */
25
    protected $metadata;
26
27
    /**
28
     * @var string $metadataIdent
29
     */
30
    protected $metadataIdent;
31
32
    /**
33
     * Describable object needs to have a `setData()` method to allow a global setter from array.
34
     *
35
     * @param array $data The object's data.
36
     * @return self
37
     */
38
    abstract public function setData(array $data);
39
40
41
    /**
42
     * @param array|MetadataInterface $metadata The object's metadata.
43
     * @throws InvalidArgumentException If the parameter is not an array or MetadataInterface.
44
     * @return self
45
     */
46
    public function setMetadata($metadata)
47
    {
48
        if (is_array($metadata)) {
49
            $meta = $this->createMetadata();
50
            $meta->merge($metadata);
51
            $this->metadata = $meta;
52
        } elseif ($metadata instanceof MetadataInterface) {
0 ignored issues
show
introduced by
$metadata is always a sub-type of Charcoal\Model\MetadataInterface.
Loading history...
53
            $this->metadata = $metadata;
54
        } else {
55
            throw new InvalidArgumentException(
56
                'Metadata argument is invalid (must be array or Metadata object).'
57
            );
58
        }
59
60
        return $this;
61
    }
62
63
    /**
64
     * Retrieve metadata, or load it if it was not explicitly set.
65
     *
66
     * @return MetadataInterface
67
     */
68
    public function metadata()
69
    {
70
        if ($this->metadata === null) {
71
            return $this->loadMetadata();
72
        }
73
        return $this->metadata;
74
    }
75
76
    /**
77
     * Load a metadata file and store it as a static var.
78
     *
79
     * Use a `MetadataLoader` object and the object's metadataIdent
80
     * to load the metadata content (typically from the filesystem, as json).
81
     *
82
     * @param  string $metadataIdent Optional ident. If none is provided then it will use the auto-genereated one.
83
     * @return MetadataInterface
84
     */
85
    public function loadMetadata($metadataIdent = null)
86
    {
87
        if ($metadataIdent === null) {
88
            $metadataIdent = $this->metadataIdent();
89
        }
90
91
        $metadata = $this->metadataLoader()->load($metadataIdent, $this->metadataClass());
92
        $this->setMetadata($metadata);
93
94
        return $metadata;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $metadata also could return the type array which is incompatible with the documented return type Charcoal\Model\MetadataInterface.
Loading history...
95
    }
96
97
    /**
98
     * @param string $metadataIdent The metadata ident.
99
     * @return self
100
     */
101
    public function setMetadataIdent($metadataIdent)
102
    {
103
        $this->metadataIdent = $metadataIdent;
104
        return $this;
105
    }
106
107
    /**
108
     * Get the metadata ident, or generate it from class name if it was not set explicitly.
109
     *
110
     * @return string
111
     */
112
    public function metadataIdent()
113
    {
114
        if ($this->metadataIdent === null) {
115
            $this->metadataIdent = $this->generateMetadataIdent();
116
        }
117
        return $this->metadataIdent;
118
    }
119
120
    /**
121
     * Create a new metadata object.
122
     *
123
     * @return MetadataInterface
124
     */
125
    abstract protected function createMetadata();
126
127
    /**
128
     * Retrieve the class name of the metadata object.
129
     *
130
     * @return string
131
     */
132
    abstract protected function metadataClass();
133
134
    /**
135
     * @param MetadataLoader $loader The loader instance, used to load metadata.
136
     * @return self
137
     */
138
    protected function setMetadataLoader(MetadataLoader $loader)
139
    {
140
        $this->metadataLoader = $loader;
141
        return $this;
142
    }
143
144
    /**
145
     * Safe MetadataLoader getter. Create the loader if it does not exist.
146
     *
147
     * @throws RuntimeException If the metadata loader was not set.
148
     * @return MetadataLoader
149
     */
150
    protected function metadataLoader()
151
    {
152
        if (!$this->metadataLoader) {
153
            throw new RuntimeException(
154
                sprintf('Metadata loader was not set for "%s"', get_class($this))
155
            );
156
        }
157
        return $this->metadataLoader;
158
    }
159
160
    /**
161
     * Generate a metadata identifier from this object's class name (FQN).
162
     *
163
     * Converts the short class name and converts it from camelCase to kebab-case.
164
     *
165
     * @return string
166
     */
167
    protected function generateMetadataIdent()
168
    {
169
        $ident = preg_replace('/([a-z])([A-Z])/', '$1-$2', static::class);
170
        $ident = strtolower(str_replace('\\', '/', $ident));
171
        return $ident;
172
    }
173
}
174