1: <?php
2:
3: namespace Alpha\Model\Type;
4:
5: use Alpha\Model\ActiveRecord;
6: use Alpha\Model\ActiveRecordProviderFactory;
7: use Alpha\Exception\RecordNotFoundException;
8: use Alpha\Exception\AlphaException;
9: use Alpha\Exception\IllegalArguementException;
10: use Alpha\Util\Config\ConfigProvider;
11: use Alpha\Util\Logging\Logger;
12:
13: /**
14: * The DEnum (Dynamic Enum) complex data type. Similiar to Enum,
15: * except list items are stored in a database table and are editable.
16: *
17: * @since 1.0
18: *
19: * @author John Collins <dev@alphaframework.org>
20: * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
21: * @copyright Copyright (c) 2015, John Collins (founder of Alpha Framework).
22: * All rights reserved.
23: *
24: * <pre>
25: * Redistribution and use in source and binary forms, with or
26: * without modification, are permitted provided that the
27: * following conditions are met:
28: *
29: * * Redistributions of source code must retain the above
30: * copyright notice, this list of conditions and the
31: * following disclaimer.
32: * * Redistributions in binary form must reproduce the above
33: * copyright notice, this list of conditions and the
34: * following disclaimer in the documentation and/or other
35: * materials provided with the distribution.
36: * * Neither the name of the Alpha Framework nor the names
37: * of its contributors may be used to endorse or promote
38: * products derived from this software without specific
39: * prior written permission.
40: *
41: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
42: * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
43: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
44: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
45: * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
46: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
47: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
48: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
49: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
51: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
52: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
53: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54: * </pre>
55: */
56: class DEnum extends ActiveRecord implements TypeInterface
57: {
58: /**
59: * An array of valid DEnum options.
60: *
61: * @var array
62: *
63: * @since 1.0
64: */
65: protected $options = array();
66:
67: /**
68: * The currently selected DEnum option.
69: *
70: * @var int
71: *
72: * @since 1.0
73: */
74: protected $value;
75:
76: /**
77: * The name of the DEnum used in the database.
78: *
79: * @var string
80: *
81: * @since 1.0
82: */
83: protected $name;
84:
85: /**
86: * The name of the database table for the class.
87: *
88: * @var string
89: *
90: * @since 1.0
91: */
92: const TABLE_NAME = 'DEnum';
93:
94: /**
95: * An array of data display labels for the class properties.
96: *
97: * @var array
98: *
99: * @since 1.0
100: */
101: protected $dataLabels = array('OID' => 'DEnum ID#', 'name' => 'Name');
102:
103: /**
104: * The message to display to the user when validation fails.
105: *
106: * @var string
107: *
108: * @since 1.0
109: */
110: protected $helper = 'Not a valid denum option!';
111:
112: /**
113: * Trace logger.
114: *
115: * @var Alpha\Util\Logging\Logger
116: *
117: * @since 1.2
118: */
119: private static $logger = null;
120:
121: /**
122: * Constructor that sets up the DEnum options.
123: *
124: * @param Alpha\Model\Type\String $name
125: */
126: public function __construct($name = null)
127: {
128: self::$logger = new Logger('DEnum');
129:
130: // ensure to call the parent constructor
131: parent::__construct();
132:
133: $this->markTransient('options');
134: $this->markTransient('value');
135: $this->markTransient('helper');
136:
137: $this->name = new String($name);
138:
139: if (isset($name) && $this->checkTableExists()) {
140: try {
141: $this->loadByAttribute('name', $name);
142: } catch (RecordNotFoundException $e) {
143: // DEnum does not exist so create it
144: $this->save();
145: }
146:
147: try {
148: $this->getOptions();
149: } catch (AlphaException $e) {
150: self::$logger->warn($e->getMessage());
151: }
152: }
153: }
154:
155: /**
156: * Setter for the name of the DEnum used in the database.
157: *
158: * @param string $name
159: *
160: * @since 1.0
161: */
162: public function setName($name)
163: {
164: $this->name->setValue($name);
165: }
166:
167: /**
168: * Get the array of DEnum options from the database.
169: *
170: * @param bool $alphaSort
171: *
172: * @return array
173: *
174: * @since 1.0
175: *
176: * @throws Alpha\Exception\AlphaException
177: */
178: public function getOptions($alphaSort = false)
179: {
180: try {
181: $options = new self();
182: $options->loadByAttribute('name', $this->name->getValue());
183: } catch (RecordNotFoundException $e) {
184: throw new AlphaException('Failed to load DEnum '.$this->name->getValue().', not found in database.');
185: }
186:
187: // now build an array of item indexes to be returned
188: $count = 0;
189: $this->options = array();
190:
191: $tmp = new DEnumItem();
192:
193: foreach ($tmp->loadItems($options->getOID()) as $DEnumItem) {
194: $this->options[$DEnumItem->getID()] = $DEnumItem->getValue();
195: ++$count;
196: }
197:
198: if ($alphaSort) {
199: asort($this->options, SORT_STRING);
200: }
201:
202: return $this->options;
203: }
204:
205: /**
206: * Getter for the validation helper string.
207: *
208: * @return string
209: *
210: * @since 1.0
211: */
212: public function getHelper()
213: {
214: return $this->helper;
215: }
216:
217: /**
218: * Set the validation helper text.
219: *
220: * @param string $helper
221: *
222: * @since 1.0
223: */
224: public function setHelper($helper)
225: {
226: $this->helper = $helper;
227: }
228:
229: /**
230: * Getter for the name.
231: *
232: * @return string
233: *
234: * @since 1.0
235: */
236: public function getName()
237: {
238: return $this->name;
239: }
240:
241: /**
242: * Used to get the current DEnum item selected index value.
243: *
244: * @return int
245: *
246: * @since 1.0
247: */
248: public function getValue()
249: {
250: return $this->value;
251: }
252:
253: /**
254: * Used to get the current DEnum item string value.
255: *
256: * @return string
257: *
258: * @since 1.0
259: */
260: public function getDisplayValue()
261: {
262: // check to see if the options have already been loaded from the DB
263: if (empty($this->options)) {
264: $this->getOptions();
265: }
266:
267: $val = Integer::zeroPad($this->value);
268: if (isset($this->options[$val])) {
269: return $this->options[$val];
270: } else {
271: return 'Unknown';
272: }
273: }
274:
275: /**
276: * Used to select the current DEnum item.
277: *
278: * @param string $item
279: *
280: * @since 1.0
281: */
282: public function setValue($item)
283: {
284: // check to see if the options have already been loaded from the DB
285: if (empty($this->options)) {
286: $this->getOptions();
287: }
288:
289: // confirm that the item ID provided is a valid key for the options array
290: if (in_array($item, array_keys($this->options))) {
291: $this->value = $item;
292: } else {
293: throw new IllegalArguementException($this->getHelper());
294: }
295: }
296:
297: /**
298: * Gets the count from the database of the DEnumItems associated with this object.
299: *
300: * @return int
301: *
302: * @since 1.0
303: *
304: * @throws Alpha\Exception\AlphaException
305: */
306: public function getItemCount()
307: {
308: $config = ConfigProvider::getInstance();
309:
310: $provider = ActiveRecordProviderFactory::getInstance($config->get('db.provider.name'), $this);
311:
312: $sqlQuery = 'SELECT COUNT(OID) AS item_count FROM DEnumItem WHERE DEnumID = \''.$this->getID().'\';';
313:
314: $this->setLastQuery($sqlQuery);
315:
316: $result = $provider->query($sqlQuery);
317:
318: if (count($result) > 0 && isset($result[0]['item_count'])) {
319: return $result[0]['item_count'];
320: } else {
321: throw new AlphaException('Failed to get the item count for the DEnum. Database error string is ['.$provider->getLastDatabaseError().']');
322: }
323: }
324:
325: /**
326: * Used to get the DenumItem ID for the given option name.
327: *
328: * @param string $optionName
329: *
330: * @return int
331: *
332: * @since 1.0
333: */
334: public function getOptionID($optionName)
335: {
336: $denumItem = new DEnumItem();
337: $denumItem->loadByAttribute('value', $optionName);
338: $id = $denumItem->getID();
339:
340: if (!empty($id)) {
341: return $id;
342: } else {
343: return 0;
344: }
345: }
346:
347: /**
348: * Used to convert the object to a printable string.
349: *
350: * @return string
351: *
352: * @since 1.0
353: */
354: public function __toString()
355: {
356: return strval($this->value);
357: }
358: }
359: