Example #1
0
 /**
  * Generate a diff beetween to variable
  *
  * @param mixed  $old    An object
  * @param mixed  $new    An object
  * @param string $identifier   A name for the variable
  * @param string $status Force a status
  *
  * @return Diff
  */
 public function compare($old, $new, $identifier = null)
 {
     $diff = new Diff($old, $new, $identifier);
     if (null === $new) {
         if (null === $old) {
             //same type, same value
             //nothing to do
         } else {
             //new variable is null but not the old
             $diff->setStatus(Diff::STATUS_DELETED);
         }
     } else {
         if (is_object($new)) {
             if (null === $old) {
                 //the new variable is an object but the old is null
                 $diff->setStatus(Diff::STATUS_CREATED);
             } else {
                 if (is_object($old)) {
                     //the both variables are objects
                     $reflectionOld = new \ReflectionClass($old);
                     $reflectionNew = new \ReflectionClass($new);
                     if ($reflectionNew->getName() !== $reflectionOld->getName()) {
                         //not the same class
                         $diff->setStatus(Diff::STATUS_TYPE_CHANGED);
                     } else {
                         //same class
                         //check if a compare closure exists
                         if (isset($this->compares[$reflectionNew->getName()])) {
                             $this->compares[$reflectionNew->getName()]($diff);
                         } else {
                             //this is a map of properties to check when comparing
                             $map = array_merge($this->buildMap($reflectionOld), $this->buildMap($reflectionNew));
                             $done = array();
                             //parse new object
                             if (isset($map[$reflectionNew->getName()])) {
                                 foreach ($map[$reflectionNew->getName()] as $propertyName) {
                                     if (isset($this->excludes[$reflectionNew->getName()])) {
                                         if (in_array($propertyName, $this->excludes[$reflectionNew->getName()])) {
                                             //be sure to not do the test again
                                             unset($map[$reflectionNew->getName()][$propertyName]);
                                             continue;
                                         }
                                     }
                                     $property = $reflectionNew->getProperty($propertyName);
                                     $property->setAccessible(true);
                                     if ($reflectionOld->hasProperty($propertyName)) {
                                         $oldProperty = $reflectionOld->getProperty($propertyName);
                                         $oldProperty->setAccessible(true);
                                         $subdiff = $this->compare($oldProperty->getValue($old), $property->getValue($new), $propertyName);
                                         if ($subdiff->isModified()) {
                                             $diff->setStatus(Diff::STATUS_MODIFIED);
                                         }
                                     } else {
                                         $subdiff = $this->compare(null, $property->getValue($new), $propertyName);
                                         $subdiff->setStatus(Diff::STATUS_CREATED);
                                         $diff->setStatus(Diff::STATUS_MODIFIED);
                                     }
                                     $diff->addProperty($propertyName, $subdiff);
                                     $done[$propertyName] = true;
                                 }
                             }
                         }
                     }
                 } else {
                     //array or scalar variable (integer, boolean, string)
                     $diff->setStatus(Diff::STATUS_TYPE_CHANGED);
                 }
             }
         } else {
             if (is_array($new)) {
                 if (null === $old) {
                     //the new variable is an array but the old is null
                     $diff->setStatus(Diff::STATUS_CREATED);
                 } else {
                     if (is_object($old)) {
                         //the new variable is an array but the old is an object
                         $diff->setStatus(Diff::STATUS_TYPE_CHANGED);
                     } else {
                         if (is_array($old)) {
                             //the both variables are arrays
                             $done = array();
                             //parse new array
                             foreach ($new as $key => $value) {
                                 if (isset($old[$key])) {
                                     //an old value exists
                                     $subdiff = $this->compare($old[$key], $value, $key);
                                     if ($subdiff->isModified() || $subdiff->isCreated() || $subdiff->isDeleted()) {
                                         $diff->setStatus(Diff::STATUS_MODIFIED);
                                     }
                                 } else {
                                     $subdiff = new Diff(null, $value, $key);
                                     $subdiff->setStatus(Diff::STATUS_CREATED);
                                     $diff->setStatus(Diff::STATUS_MODIFIED);
                                 }
                                 $diff[$key] = $subdiff;
                                 $done[$key] = true;
                             }
                             //parse old array
                             foreach ($old as $key => $value) {
                                 if (!isset($done[$key])) {
                                     //no new value exists
                                     $subdiff = new Diff($value, null, $key);
                                     $subdiff->setStatus(Diff::STATUS_DELETED);
                                     $diff->setStatus(Diff::STATUS_MODIFIED);
                                     $diff[$key] = $subdiff;
                                 }
                             }
                         } else {
                             //scalar variable (integer, boolean, string)
                             $diff->setStatus(Diff::STATUS_TYPE_CHANGED);
                         }
                     }
                 }
             } else {
                 //scalar variable (integer, boolean, string)
                 if (null === $old) {
                     //the new variable is a scalar but the old is null
                     // $diff->setStatus(Diff::STATUS_CREATED);
                     $diff->setStatus(Diff::STATUS_MODIFIED);
                 } else {
                     if (is_object($old)) {
                         //the new variable is a scalar but the old is an object
                         $diff->setStatus(Diff::STATUS_TYPE_CHANGED);
                     } else {
                         if (is_array($old)) {
                             $diff->setStatus(Diff::STATUS_TYPE_CHANGED);
                         } else {
                             if ($old !== $new) {
                                 $diff->setStatus(Diff::STATUS_MODIFIED);
                             }
                         }
                     }
                 }
             }
         }
     }
     return $diff;
 }