Skip to content

Commit

Permalink
Replace serialization approach with recursive comp
Browse files Browse the repository at this point in the history
Signed-off-by: Josh <josh.t.richards@gmail.com>
  • Loading branch information
joshtrichards authored May 4, 2024
1 parent e70375b commit 0c018d5
Showing 1 changed file with 59 additions and 9 deletions.
68 changes: 59 additions & 9 deletions lib/private/Files/Cache/Scanner.php
Original file line number Diff line number Diff line change
Expand Up @@ -222,15 +222,7 @@ public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData =

// Only update metadata that has changed
// i.e. get all the values in $data that are not present in the cache already
// NOTE: we serialize then unserialize here because array_diff_assoc() doesn't
// support multidimensional arrays on its own (and otherwise internally casts any
// embedded array elements to attempt to compare them - not only generating warnings
// like "Array to string conversion" but also, as a resut, overlooking real differences)
$newData = array_diff_assoc(
array_map('serialize', $data),
array_map('serialize', $cacheData->getData())
);
$newData = array_map('unserialize', $newData);
$newData = $this->array_diff_assoc_multi($data, $cacheData->getData());

// make it known to the caller that etag has been changed and needs propagation
if (isset($newData['etag'])) {
Expand Down Expand Up @@ -378,6 +370,64 @@ public function scan($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1, $loc
return $data;
}

/**
* Compares $array1 against $array2 and returns all the values in $array1 that are not in $array2
* Note this is a one-way check - i.e. we don't care about things that are in $array2 that aren't in $array1
*
* Supports multi-dimensional arrays
* Also checks keys/indexes
* Comparisons are strict just like array_diff_assoc
* Order of keys/values does not matter
*
* @param array $array1
* @param array|? $array2

Check failure on line 383 in lib/private/Files/Cache/Scanner.php

View workflow job for this annotation

GitHub Actions / static-code-analysis

InvalidDocblock

lib/private/Files/Cache/Scanner.php:383:12: InvalidDocblock: Unexpected token ? in docblock for OC\Files\Cache\Scanner::array_diff_assoc_multi (see https://psalm.dev/008)

Check failure

Code scanning / Psalm

InvalidDocblock Error

Unexpected token ? in docblock for OC\Files\Cache\Scanner::array_diff_assoc_multi
* @return array with the differences between $array1 and $array1
* @throws \InvalidArgumentException if $array1 isn't an actual array
*
*/
protected function array_diff_assoc_multi($array1, $array2) {
if (!is_array($array1)) {
// this ain't gonna work
throw new \InvalidArgumentException('$array1 must be an array!');
}

if (!is_array($array2)) {
// everything is different
return $array1;
}

$result = [];

foreach ($array1 as $key => $value) {

// if $array2 doesn't have the same key, that's a result
if (!array_key_exists($key, $array2)) {
$result[$key] = $value;
continue;
}

// if $array2's value for the same key is different, that's a result
if ($array2[$key] !== $value && !is_array($value)) {
$result[$key] = $value;
continue;
}

if (is_array($value)) {
$nestedDiff = $this->array_diff_assoc_multi($value, $array2[$key]);
if (!empty($nestedDiff)) {
$result[$key] = $nestedDiff;
continue;
}
} else { // not an array
if ($array2[$key] != $value) {
$result[$key] = $value;
continue;
}
}
}
return $result;
}

/**
* Get the children currently in the cache
*
Expand Down

0 comments on commit 0c018d5

Please sign in to comment.