Skip to content

Instantly share code, notes, and snippets.

@albe
Created February 26, 2015 10:09
Show Gist options
  • Save albe/adfb00e4c7f10ebf5379 to your computer and use it in GitHub Desktop.
Save albe/adfb00e4c7f10ebf5379 to your computer and use it in GitHub Desktop.
Classes/TYPO3/Flow/Reflection/ObjectAccess.php | 47 ++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/Classes/TYPO3/Flow/Reflection/ObjectAccess.php b/Classes/TYPO3/Flow/Reflection/ObjectAccess.php
index 014e2f3..0c84937 100644
--- a/Classes/TYPO3/Flow/Reflection/ObjectAccess.php
+++ b/Classes/TYPO3/Flow/Reflection/ObjectAccess.php
@@ -206,6 +206,7 @@ class ObjectAccess {
* Tries to set the property the following ways:
* - if target is an array, set value
* - if super cow powers should be used, set value through reflection
+ * - if property value is a collection and add/remove methods exist, call them.
* - if public setter method exists, call it.
* - if public property exists, set it directly.
* - if the target object is an instance of ArrayAccess, it sets the property
@@ -239,6 +240,30 @@ class ObjectAccess {
} else {
$subject->$propertyName = $propertyValue;
}
+ } elseif ((is_array($propertyValue) || $propertyValue instanceof \Traversable) &&
+ is_callable(array($subject, $addMethodName = self::buildAdderMethodName($propertyName))) &&
+ is_callable(array($subject, $removeMethodName = self::buildRemoverMethodName($propertyName)))) {
+ $itemsToAdd = is_array($propertyValue) ? $propertyValue : iterator_to_array($propertyValue);
+ $itemsToRemove = array();
+ $currentValue = self::getProperty($subject, $propertyName);
+ if (is_array($currentValue) || $currentValue instanceof \Traversable) {
+ foreach ($currentValue as $currentItem) {
+ foreach ($itemsToAdd as $key => $newItem) {
+ if ($currentItem === $newItem) {
+ unset($itemsToAdd[$key]);
+ // Continue to next $currentItem
+ continue 2;
+ }
+ }
+ $itemsToRemove[] = $currentItem;
+ }
+ }
+ foreach ($itemsToRemove as $item) {
+ $subject->$removeMethodName($item);
+ }
+ foreach ($itemsToAdd as $item) {
+ $subject->$addMethodName($item);
+ }
} elseif (is_callable(array($subject, $setterMethodName = self::buildSetterMethodName($propertyName)))) {
$subject->$setterMethodName($propertyValue);
} elseif ($subject instanceof \ArrayAccess) {
@@ -413,4 +438,26 @@ class ObjectAccess {
static public function buildSetterMethodName($propertyName) {
return 'set' . ucfirst($propertyName);
}
+
+ /**
+ * Build the remover method name for a given property by singularizing the name
+ * and capitalizing the first letter of the property, then prepending it with "remove".
+ *
+ * @param string $propertyName Name of the property
+ * @return string Name of the remover method name
+ */
+ static public function buildRemoverMethodName($propertyName) {
+ return 'remove' . ucfirst(\Doctrine\Common\Inflector\Inflector::singularize($propertyName));
+ }
+
+ /**
+ * Build the adder method name for a given property by singularizing the name
+ * and capitalizing the first letter of the property, then prepending it with "add".
+ *
+ * @param string $propertyName Name of the property
+ * @return string Name of the adder method name
+ */
+ static public function buildAdderMethodName($propertyName) {
+ return 'add' . ucfirst(\Doctrine\Common\Inflector\Inflector::singularize($propertyName));
+ }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment