33namespace Eniams \Spy \Property ;
44
55use Eniams \Spy \Assertion \SpyAssertion ;
6- use Eniams \Spy \Exception \UndefinedContextForBlackListPropertiesException ;
6+ use Eniams \Spy \Exception \UndefinedContextException ;
77use Eniams \Spy \Reflection \CacheClassInfoTrait ;
88use Eniams \Spy \Reflection \ClassInfo ;
99
@@ -33,17 +33,11 @@ public function isModified($initial, $current, array $context = []): bool
3333
3434 $ properties = $ this ->getFilteredProperties ($ initial , $ classInfo ->getProperties (), $ context );
3535
36- foreach ($ properties as $ property ) {
37- if ($ this ->isPropertyModified ($ initial , $ current , $ property ->getName (), $ classInfo )) {
38- return true ;
39- }
40- }
41-
42- return false ;
36+ return $ this ->doCheck ($ initial , $ current , $ classInfo , $ properties );
4337 }
4438
4539 /**
46- * object $initial and object $current will be compared to know if $initial was modified.
40+ * object $initial and object $current will be compared to know if $initial was modified in a specifc $context .
4741 *
4842 * @param object $initial
4943 * @param object $current
@@ -53,6 +47,23 @@ public function isModifiedInContext(PropertyCheckerContextInterface $initial, Pr
5347 return $ this ->isModified ($ initial , $ current , $ context );
5448 }
5549
50+ /**
51+ * object $initial and object $current will be compared to know if $initial was modified in a specifc $context.
52+ *
53+ * @param object $initial
54+ * @param object $current
55+ */
56+ public function isModifiedForProperties ($ initial , $ current , array $ propertiesToCheck = []): bool
57+ {
58+ SpyAssertion::isComparable ($ initial , $ current );
59+
60+ $ classInfo = $ this ->getCacheClassInfo ()->getClassInfo ($ initial );
61+
62+ $ properties = $ this ->filterProperties ($ classInfo ->getProperties (), $ propertiesToCheck );
63+
64+ return $ this ->doCheck ($ initial , $ current , $ classInfo , $ properties );
65+ }
66+
5667 /**
5768 * $property of object $initial and object $current will be compared to know if the property was modified.
5869 *
@@ -90,19 +101,22 @@ public function isPropertyModified($initial, $current, string $propertyName, Cla
90101 * @param object $current
91102 *
92103 * @return PropertyState[]
93- *
94- * @see PropertyCheckerBlackListInterface::propertiesBlackList()
95104 */
96105 public function getPropertiesModified ($ initial , $ current , array $ context = []): array
97106 {
98107 SpyAssertion::isComparable ($ initial , $ current );
99108
100- $ propertiesModified = [];
101-
102109 $ classInfo = $ this ->getCacheClassInfo ()->getClassInfo ($ initial );
103110
104111 $ properties = $ this ->getFilteredProperties ($ initial , $ classInfo ->getProperties (), $ context );
105112
113+ return $ this ->doExtractPropertiesModified ($ initial , $ current , $ classInfo , $ properties );
114+ }
115+
116+ public function doExtractPropertiesModified ($ initial , $ current , $ classInfo , $ properties )
117+ {
118+ $ propertiesModified = [];
119+
106120 foreach ($ properties as $ property ) {
107121 $ propertyName = $ property ->getName ();
108122
@@ -128,14 +142,20 @@ public function getPropertiesModified($initial, $current, array $context = []):
128142 }
129143
130144 /**
145+ * Return modified properties even they are excluded with the black list strategy.
146+ *
131147 * @param $initial
132148 * @param $current
133149 *
134150 * @return PropertyState[]
135151 */
136- public function getPropertiesModifiedWithBlackListContext ($ initial , $ current )
152+ public function getPropertiesModifiedWithoutBlackListContext ($ initial , $ current )
137153 {
138- return $ this ->getPropertiesModified ($ initial , $ current );
154+ SpyAssertion::isComparable ($ initial , $ current );
155+
156+ $ classInfo = $ this ->getCacheClassInfo ()->getClassInfo ($ initial );
157+
158+ return $ this ->doExtractPropertiesModified ($ initial , $ current , $ classInfo , $ classInfo ->getProperties ());
139159 }
140160
141161 /**
@@ -149,6 +169,20 @@ public function getPropertiesModifiedInContext($initial, $current, array $contex
149169 return $ this ->getPropertiesModified ($ initial , $ current , $ context );
150170 }
151171
172+ /**
173+ * @param \ReflectionProperty[]
174+ */
175+ private function doCheck ($ initial , $ current , $ classInfo , array $ properties = []): bool
176+ {
177+ foreach ($ properties as $ property ) {
178+ if ($ this ->isPropertyModified ($ initial , $ current , $ property ->getName (), $ classInfo )) {
179+ return true ;
180+ }
181+ }
182+
183+ return false ;
184+ }
185+
152186 private function compareCollection (array $ first , array $ second ): array
153187 {
154188 return array_udiff ($ first , $ second , static function () use ($ first , $ second ) {
@@ -157,7 +191,7 @@ private function compareCollection(array $first, array $second): array
157191 }
158192
159193 /**
160- * @param array $properties \ReflectionProperty[]
194+ * @param $properties \ReflectionProperty[]
161195 *
162196 * @return \ReflectionProperty[]
163197 */
@@ -178,35 +212,47 @@ private function filterBlackListedProperties(PropertyCheckerBlackListInterface $
178212 private function filterPropertiesInContext (PropertyCheckerContextInterface $ object , array $ properties = [], array $ context = []): array
179213 {
180214 $ contextProperties = $ object ::propertiesInContext ();
181- $ filteredFromContext = [];
215+ $ propertiesExtractedFromContext = [];
182216
183217 foreach ($ context as $ contextName ) {
184218 if (null === $ propertiesToCheck = $ contextProperties [$ contextName ] ?? null ) {
185- throw new UndefinedContextForBlackListPropertiesException (sprintf ('There is no properties for contex %s ' , $ contextName ));
219+ throw new UndefinedContextException (sprintf ('There is no properties for context %s ' , $ contextName ));
186220 }
187- $ filteredFromContext = array_merge ($ filteredFromContext , $ propertiesToCheck );
221+ $ propertiesExtractedFromContext = array_merge ($ propertiesExtractedFromContext , $ propertiesToCheck );
188222 }
189223
190- return array_filter ($ properties , static function (\ReflectionProperty $ property ) use ($ filteredFromContext ) {
191- return \in_array ($ property ->getName (), $ filteredFromContext );
224+ return $ this ->filterProperties ($ properties , $ propertiesExtractedFromContext );
225+ }
226+
227+ /**
228+ * @param $properties \ReflectionProperty[]
229+ *
230+ * @return \ReflectionProperty[]
231+ */
232+ private function filterProperties (array $ properties , array $ propertyToExtract ): array
233+ {
234+ return array_filter ($ properties , static function (\ReflectionProperty $ property ) use ($ propertyToExtract ) {
235+ return \in_array ($ property ->getName (), $ propertyToExtract );
192236 });
193237 }
194238
195239 /**
196240 * Filter properties with the good strategy, Blacklist, Context or no strategy.
197241 *
198242 * @param $object
243+ * @param $properties \ReflectionProperty[]
199244 *
200245 * @return \ReflectionProperty[]
201246 */
202247 private function getFilteredProperties ($ object , array $ properties = [], array $ context = []): array
203248 {
249+ if ($ object instanceof PropertyCheckerContextInterface && [] !== $ context ) {
250+ return $ this ->filterPropertiesInContext ($ object , $ properties , $ context );
251+ }
252+
204253 if ($ object instanceof PropertyCheckerBlackListInterface) {
205254 return $ this ->filterBlackListedProperties ($ object , $ properties );
206255 }
207- if ($ object instanceof PropertyCheckerContextInterface) {
208- return $ this ->filterPropertiesInContext ($ object , $ properties , $ context );
209- }
210256
211257 return $ properties ;
212258 }
0 commit comments