1: <?php
2: /**
3: * This file is part of the Pipeliner API client library for PHP
4: *
5: * Copyright 2014 Pipelinersales, Inc. All Rights Reserved.
6: * For the full license information, see the attached LICENSE file.
7: */
8:
9: namespace PipelinerSales\ApiClient;
10:
11: /**
12: * Represents an entity.
13: *
14: * Aside from being able to set entity fields via the {@see setField} method, it also
15: * has automatic getters/setters in camel case and supports array access. These three
16: * ways of setting a field are therefore equivalent:
17: * <code>
18: * $entity->setOwnerId(1);
19: * $entity->setField('OWNER_ID', 1);
20: * $entity['OWNER_ID'] = 1;
21: * </code>
22: *
23: * For standard fields, the magic getters/setters are considered the preferred method.
24: *
25: * For a full list of supported entities and their fields, see the
26: * {@link http://workspace.pipelinersales.com/community/api/data/Entities.html API documentation}.
27: */
28: class Entity implements \ArrayAccess
29: {
30:
31: private $type;
32: private $values = array();
33: private $modified = array();
34: private $dateTimeFormat;
35:
36: /**
37: * @param string $type type of the entity, e.g. Account, see
38: * {@link http://workspace.pipelinersales.com/community/api/data/Entities.html
39: * list of entities}
40: * @param string $dateTimeFormat the format for converting DateTime objects into strings
41: */
42: public function __construct($type, $dateTimeFormat)
43: {
44: $this->type = $type;
45: $this->dateTimeFormat = $dateTimeFormat;
46: }
47:
48: public function __call($name, $arguments)
49: {
50: $prefix = substr($name, 0, 3);
51: if ($prefix == 'get' or $prefix == 'set') {
52: $fieldName = $this->nameFromCamelCase(substr($name, 3));
53:
54: if ($prefix == 'set') {
55: return $this->setField($fieldName, $arguments[0]);
56: } else {
57: return $this->getField($fieldName);
58: }
59: }
60: throw new \BadMethodCallException('Call to a non-existent method \'' . $name . '\'');
61: }
62:
63: /**
64: * Sets this entity's field and adds it to the list of modified fields.
65: * Returns $this, which allows for chaining of setters.
66: *
67: * @param string $fieldName Name of the field to set, see
68: * {@link http://workspace.pipelinersales.com/community/api/data/Entities.html API documentation}.
69: * All standard fields are in upper-case, with underscore between the words (e.g. FORM_TYPE).
70: * Custom fields don't have this requirement.
71: * @param mixed $value Value to set the fields to. DateTime objects are automatically converted
72: * to strings according to the configured format (so calling a getter afterwards will only
73: * return this string). Other types of values are used directly.
74: * @return Entity
75: */
76: public function setField($fieldName, $value)
77: {
78: if ($value instanceof \DateTime) {
79: $value = $this->convertDateTime($value);
80: }
81:
82: $this->values[$fieldName] = $value;
83: $this->modified[$fieldName] = true;
84: return $this;
85: }
86:
87: /**
88: * Sets values of multiple fields at once. Fields not present in the array
89: * will not be changed in any way.
90: * @param array $values an associative array of fields to values
91: */
92: public function setFields($values)
93: {
94: foreach ($values as $field => $value) {
95: $this->setField($field, $value);
96: }
97: }
98:
99: /**
100: * Unsets the specified field. This means that the field will not be
101: * changed upon saving. This affects both the "full update" and the
102: * "modified only" update.
103: * @return Entity
104: */
105: public function unsetField($fieldName)
106: {
107: unset($this->values[$fieldName]);
108: unset($this->modified[$fieldName]);
109: return $this;
110: }
111:
112: /**
113: * Returns the value of the specified field in this entity. A PHP notice will be raised
114: * if the value hasn't been set yet.
115: * @param string $fieldName Name of the field, see the
116: * {@link http://workspace.pipelinersales.com/community/api/data/Entities.html API documentation}.
117: * @return mixed
118: */
119: public function getField($fieldName)
120: {
121: return $this->values[$fieldName];
122: }
123:
124: /**
125: * Returns an associative array of all fields and their values
126: * @return array
127: */
128: public function getFields()
129: {
130: return $this->values;
131: }
132:
133: /**
134: * Returns an associative array of fields which were modified since the entity was created/loaded,
135: * and their values
136: * @return string[]
137: */
138: public function getModifiedFields()
139: {
140: return array_intersect_key($this->values, $this->modified);
141: }
142:
143: /**
144: * Returns true if this field has some configured value.
145: * @param string $fieldName
146: * @return boolean
147: */
148: public function isFieldSet($fieldName)
149: {
150: return isset($this->values[$fieldName]);
151: }
152:
153: private function convertDateTime(\DateTime $dateTime)
154: {
155: $dateTimeCopy = clone $dateTime;
156: $dateTimeCopy->setTimezone(new \DateTimeZone('UTC'));
157: return $dateTimeCopy->format($this->dateTimeFormat);
158: }
159:
160: /**
161: * Converts a NameLikeThis (used in getters/setters) into a NAME_LIKE_THIS (used in fields)
162: */
163: private function nameFromCamelCase($name)
164: {
165: return strtoupper(substr(preg_replace('/([A-Z])/', '_\1', $name), 1));
166: }
167:
168: /**
169: * Returns a JSON-encoded string representing this entity. It will contain all
170: * of this entity's fields.
171: *
172: * @return string
173: */
174: public function allToJson()
175: {
176: return json_encode($this->values);
177: }
178:
179: /**
180: * Returns a JSON-encoded string representing this entity, which will only contain
181: * fields that have been modified since the entity was last loaded or saved.
182: *
183: * @return string
184: */
185: public function modifiedToJson()
186: {
187: return json_encode(array_intersect_key($this->values, $this->modified));
188: }
189:
190: /**
191: * Resets the list of modified fields. All fields will be considered "not modified".
192: * {@see RestRepository} calls this automatically after successfully saving on the server.
193: */
194: public function resetModified()
195: {
196: $this->modified = array();
197: }
198:
199: /**
200: * Returns the type of this entity.
201: * @return string
202: */
203: public function getType()
204: {
205: return $this->type;
206: }
207:
208: public function offsetExists($offset)
209: {
210: return $this->isFieldSet($offset);
211: }
212:
213: public function offsetGet($offset)
214: {
215: return $this->getField($offset);
216: }
217:
218: public function offsetSet($offset, $value)
219: {
220: $this->setField($offset, $value);
221: }
222:
223: public function offsetUnset($offset)
224: {
225: $this->unsetField($offset);
226: }
227: }
228: