targetIterator = $targetIterator; $this->sourceConverter = $sourceConverter; $this->targetConverter = $targetConverter; parent::__construct($sourceIterator); } public function accept() { $current = $this->current(); $key = $this->sourceConverter->convert($this->normalize($current)); if (!($data = $this->getTargetData($key))) { return true; } // Ensure the Content-Length matches and it hasn't been modified since the mtime return $current->getSize() != $data[0] || $current->getMTime() > $data[1]; } /** * Returns an array of the files from the target iterator that were not found in the source iterator * * @return array */ public function getUnmatched() { return array_keys($this->cache); } /** * Get key information from the target iterator for a particular filename * * @param string $key Target iterator filename * * @return array|bool Returns an array of data, or false if the key is not in the iterator */ protected function getTargetData($key) { $key = $this->cleanKey($key); if (isset($this->cache[$key])) { $result = $this->cache[$key]; unset($this->cache[$key]); return $result; } $it = $this->targetIterator; while ($it->valid()) { $value = $it->current(); $data = array($value->getSize(), $value->getMTime()); $filename = $this->targetConverter->convert($this->normalize($value)); $filename = $this->cleanKey($filename); if ($filename == $key) { return $data; } $this->cache[$filename] = $data; $it->next(); } return false; } private function normalize($current) { $asString = (string) $current; return strpos($asString, 's3://') === 0 ? $asString : $current->getRealPath(); } private function cleanKey($key) { return ltrim($key, '/'); } }