1: <?php
2: /**
3: * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
4: * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
5: *
6: * Licensed under The MIT License
7: * For full copyright and license information, please see the LICENSE.txt
8: * Redistributions of files must retain the above copyright notice.
9: *
10: * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
11: * @link https://cakephp.org CakePHP(tm) Project
12: * @since 3.3.0
13: * @license https://opensource.org/licenses/mit-license.php MIT License
14: */
15: namespace Cake\ORM;
16:
17: use ArrayObject;
18: use RuntimeException;
19:
20: /**
21: * OOP style Save Option Builder.
22: *
23: * This allows you to build options to save entities in a OOP style and helps
24: * you to avoid mistakes by validating the options as you build them.
25: *
26: * @see \Cake\Datasource\RulesChecker
27: */
28: class SaveOptionsBuilder extends ArrayObject
29: {
30:
31: use AssociationsNormalizerTrait;
32:
33: /**
34: * Options
35: *
36: * @var array
37: */
38: protected $_options = [];
39:
40: /**
41: * Table object.
42: *
43: * @var \Cake\ORM\Table
44: */
45: protected $_table;
46:
47: /**
48: * Constructor.
49: *
50: * @param \Cake\ORM\Table $table A table instance.
51: * @param array $options Options to parse when instantiating.
52: */
53: public function __construct(Table $table, array $options = [])
54: {
55: $this->_table = $table;
56: $this->parseArrayOptions($options);
57:
58: parent::__construct();
59: }
60:
61: /**
62: * Takes an options array and populates the option object with the data.
63: *
64: * This can be used to turn an options array into the object.
65: *
66: * @throws \InvalidArgumentException If a given option key does not exist.
67: * @param array $array Options array.
68: * @return \Cake\ORM\SaveOptionsBuilder
69: */
70: public function parseArrayOptions($array)
71: {
72: foreach ($array as $key => $value) {
73: $this->{$key}($value);
74: }
75:
76: return $this;
77: }
78:
79: /**
80: * Set associated options.
81: *
82: * @param string|array $associated String or array of associations.
83: * @return \Cake\ORM\SaveOptionsBuilder
84: */
85: public function associated($associated)
86: {
87: $associated = $this->_normalizeAssociations($associated);
88: $this->_associated($this->_table, $associated);
89: $this->_options['associated'] = $associated;
90:
91: return $this;
92: }
93:
94: /**
95: * Checks that the associations exists recursively.
96: *
97: * @param \Cake\ORM\Table $table Table object.
98: * @param array $associations An associations array.
99: * @return void
100: */
101: protected function _associated(Table $table, array $associations)
102: {
103: foreach ($associations as $key => $associated) {
104: if (is_int($key)) {
105: $this->_checkAssociation($table, $associated);
106: continue;
107: }
108: $this->_checkAssociation($table, $key);
109: if (isset($associated['associated'])) {
110: $this->_associated($table->getAssociation($key)->getTarget(), $associated['associated']);
111: continue;
112: }
113: }
114: }
115:
116: /**
117: * Checks if an association exists.
118: *
119: * @throws \RuntimeException If no such association exists for the given table.
120: * @param \Cake\ORM\Table $table Table object.
121: * @param string $association Association name.
122: * @return void
123: */
124: protected function _checkAssociation(Table $table, $association)
125: {
126: if (!$table->associations()->has($association)) {
127: throw new RuntimeException(sprintf('Table `%s` is not associated with `%s`', get_class($table), $association));
128: }
129: }
130:
131: /**
132: * Set the guard option.
133: *
134: * @param bool $guard Guard the properties or not.
135: * @return \Cake\ORM\SaveOptionsBuilder
136: */
137: public function guard($guard)
138: {
139: $this->_options['guard'] = (bool)$guard;
140:
141: return $this;
142: }
143:
144: /**
145: * Set the validation rule set to use.
146: *
147: * @param string $validate Name of the validation rule set to use.
148: * @return \Cake\ORM\SaveOptionsBuilder
149: */
150: public function validate($validate)
151: {
152: $this->_table->getValidator($validate);
153: $this->_options['validate'] = $validate;
154:
155: return $this;
156: }
157:
158: /**
159: * Set check existing option.
160: *
161: * @param bool $checkExisting Guard the properties or not.
162: * @return \Cake\ORM\SaveOptionsBuilder
163: */
164: public function checkExisting($checkExisting)
165: {
166: $this->_options['checkExisting'] = (bool)$checkExisting;
167:
168: return $this;
169: }
170:
171: /**
172: * Option to check the rules.
173: *
174: * @param bool $checkRules Check the rules or not.
175: * @return \Cake\ORM\SaveOptionsBuilder
176: */
177: public function checkRules($checkRules)
178: {
179: $this->_options['checkRules'] = (bool)$checkRules;
180:
181: return $this;
182: }
183:
184: /**
185: * Sets the atomic option.
186: *
187: * @param bool $atomic Atomic or not.
188: * @return \Cake\ORM\SaveOptionsBuilder
189: */
190: public function atomic($atomic)
191: {
192: $this->_options['atomic'] = (bool)$atomic;
193:
194: return $this;
195: }
196:
197: /**
198: * @return array
199: */
200: public function toArray()
201: {
202: return $this->_options;
203: }
204:
205: /**
206: * Setting custom options.
207: *
208: * @param string $option Option key.
209: * @param mixed $value Option value.
210: * @return \Cake\ORM\SaveOptionsBuilder
211: */
212: public function set($option, $value)
213: {
214: if (method_exists($this, $option)) {
215: return $this->{$option}($value);
216: }
217: $this->_options[$option] = $value;
218:
219: return $this;
220: }
221: }
222: