/**
  * Install files or folders represented by and stored in this vehicle.
  *
  * @access protected
  * @param xPDOTransport &$transport A reference the transport this vehicle is stored in.
  * @param array $options Optional attributes that can be applied to vehicle install process.
  * @return boolean True if the files are installed successfully.
  */
 protected function _installFiles(& $transport, $options) {
     $installed = false;
     $copied = false;
     $vOptions = $this->get($transport, $options);
     if (isset ($vOptions['object']) && isset ($vOptions['object']['source']) && isset ($vOptions['object']['target'])) {
         $object = $vOptions['object'];
         $fileName = $object['name'];
         $fileSource = $transport->path . $object['source'];
         $fileTarget = eval ($object['target']);
         $fileTargetPath = $fileTarget . $fileName;
         $preExistingMode = xPDOTransport::PRESERVE_PREEXISTING;
         if (isset ($vOptions[xPDOTransport::PREEXISTING_MODE])) {
             $preExistingMode = (integer) $vOptions[xPDOTransport::PREEXISTING_MODE];
         }
         $cacheManager = $transport->xpdo->getCacheManager();
         if ($this->validate($transport, $object, $vOptions)) {
             if (isset ($vOptions[xPDOTransport::INSTALL_FILES]) && !$vOptions[xPDOTransport::INSTALL_FILES]) {
                 $transport->xpdo->log(xPDO::LOG_LEVEL_INFO, "Skipping installion of files from {$fileSource} to {$fileTargetPath}");
                 $installed = true;
             } elseif ($cacheManager && file_exists($fileSource) && !empty ($fileTarget)) {
                 $transport->xpdo->log(xPDO::LOG_LEVEL_INFO, "Installing files from {$fileSource} to {$fileTargetPath}");
                 $copied = array();
                 if ($preExistingMode === xPDOTransport::PRESERVE_PREEXISTING && file_exists($fileTargetPath)) {
                     $preservedArchive = $transport->path . $transport->signature . '/' . $this->payload['class'] . '/' . $this->payload['signature'] . '.preserved.zip';
                     $transport->xpdo->log(xPDO::LOG_LEVEL_INFO, "Attempting to preserve files at {$fileTargetPath} into archive {$preservedArchive}");
                     $preserved = xPDOTransport::_pack($transport->xpdo, $preservedArchive, $fileTarget, $fileName);
                 }
                 if (is_dir($fileSource)) {
                     $copied = $cacheManager->copyTree($fileSource, $fileTarget, array_merge($vOptions, array('copy_return_file_stat' => true)));
                 } elseif (is_file($fileSource)) {
                     $copied = $cacheManager->copyFile($fileSource, $fileTarget, array_merge($vOptions, array('copy_return_file_stat' => true)));
                 }
                 if (empty($copied)) {
                     $transport->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Error copying files from {$fileSource} to {$fileTargetPath}");
                 } else {
                     if ($preExistingMode === xPDOTransport::PRESERVE_PREEXISTING && is_array($copied)) {
                         foreach ($copied as $copiedFile => $stat) {
                             if (isset($stat['overwritten'])) $transport->_preserved[$vOptions['guid']]['files'][$copiedFile]= $stat;
                         }
                     }
                     $installed = true;
                 }
             } else {
                 $transport->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Could not install files from {$fileSource} to {$fileTarget}");
             }
             if (!$this->resolve($transport, $object, $vOptions)) {
                 $transport->xpdo->log(xPDO::LOG_LEVEL_ERROR, 'Could not resolve vehicle for object: ' . print_r($object, true));
                 if ($transport->xpdo->getDebug() === true) $transport->xpdo->log(xPDO::LOG_LEVEL_DEBUG, 'Could not resolve vehicle: ' . print_r($vOptions, true));
             }
         } else {
             $transport->xpdo->log(xPDO::LOG_LEVEL_ERROR, 'Could not validate vehicle for object: ' . print_r($object, true));
             if ($transport->xpdo->getDebug() === true) $transport->xpdo->log(xPDO::LOG_LEVEL_DEBUG, 'Could not validate vehicle: ' . print_r($vOptions, true));
         }
     }
     return $installed;
 }
 /**
  * Resolve any dependencies of the artifact represented in this vehicle.
  *
  * @param xPDOTransport &$transport A reference to the xPDOTransport in
  * which this vehicle is stored.
  * @param mixed &$object An object reference to resolve dependencies for.
  * Use this to make the artifact or other important data available to the
  * resolver scripts.
  * @param array $options Additional options for the resolution process.
  * @return boolean Indicates if the resolution was successful.
  */
 public function resolve(&$transport, &$object, $options = array())
 {
     $resolved = false;
     if (isset($this->payload['resolve'])) {
         while (list($rKey, $r) = each($this->payload['resolve'])) {
             $type = $r['type'];
             $body = $r['body'];
             $preExistingMode = xPDOTransport::PRESERVE_PREEXISTING;
             if (!empty($options[xPDOTransport::PREEXISTING_MODE])) {
                 $preExistingMode = intval($options[xPDOTransport::PREEXISTING_MODE]);
             }
             switch ($type) {
                 case 'file':
                     if (isset($options[xPDOTransport::RESOLVE_FILES]) && !$options[xPDOTransport::RESOLVE_FILES]) {
                         $resolved = true;
                         continue;
                     }
                     if ($transport->xpdo->getDebug() === true) {
                         $transport->xpdo->log(xPDO::LOG_LEVEL_DEBUG, "Resolving transport files: " . print_r($this, true));
                     }
                     $fileMeta = $transport->xpdo->fromJSON($body, true);
                     $fileName = $fileMeta['name'];
                     $fileSource = $transport->path . $fileMeta['source'];
                     $fileTarget = eval($fileMeta['target']);
                     $fileTargetPath = $fileTarget . $fileName;
                     $preservedArchive = $transport->path . $transport->signature . '/' . $this->payload['class'] . '/' . $this->payload['signature'] . '.' . $rKey . '.preserved.zip';
                     $cacheManager = $transport->xpdo->getCacheManager();
                     switch ($options[xPDOTransport::PACKAGE_ACTION]) {
                         case xPDOTransport::ACTION_UPGRADE:
                         case xPDOTransport::ACTION_INSTALL:
                             // if package is installing
                             if ($cacheManager && file_exists($fileSource) && !empty($fileTarget)) {
                                 $copied = array();
                                 if ($preExistingMode === xPDOTransport::PRESERVE_PREEXISTING && file_exists($fileTargetPath)) {
                                     $transport->xpdo->log(xPDO::LOG_LEVEL_INFO, "Attempting to preserve files at {$fileTargetPath} into archive {$preservedArchive}");
                                     $preserved = xPDOTransport::_pack($transport->xpdo, $preservedArchive, $fileTarget, $fileName);
                                 }
                                 if (is_dir($fileSource)) {
                                     $copied = $cacheManager->copyTree($fileSource, $fileTarget, array_merge($options, array('copy_return_file_stat' => true)));
                                 } elseif (is_file($fileSource)) {
                                     $copied = $cacheManager->copyFile($fileSource, $fileTarget, array_merge($options, array('copy_return_file_stat' => true)));
                                 }
                                 if (empty($copied)) {
                                     $transport->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Could not copy {$fileSource} to {$fileTargetPath}");
                                 } else {
                                     if ($preExistingMode === xPDOTransport::PRESERVE_PREEXISTING && is_array($copied)) {
                                         foreach ($copied as $copiedFile => $stat) {
                                             if (isset($stat['overwritten'])) {
                                                 $transport->_preserved[$options['guid']]['files'][substr($copiedFile, strlen($fileTarget))] = $stat;
                                             }
                                         }
                                     }
                                     $resolved = true;
                                 }
                             } else {
                                 $transport->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Could not copy {$fileSource} to {$fileTargetPath}");
                             }
                             break;
                         case xPDOTransport::ACTION_UNINSTALL:
                             /* if package is uninstalling
                                user can override whether or not files from resolver are removed
                                however default action is to remove */
                             if (!isset($options[xPDOTransport::RESOLVE_FILES_REMOVE]) || $options[xPDOTransport::RESOLVE_FILES_REMOVE] !== false) {
                                 $path = $fileTarget . $fileName;
                                 $transport->xpdo->log(xPDO::LOG_LEVEL_INFO, 'Removing files in file resolver: ' . $path);
                                 if ($cacheManager && file_exists($path)) {
                                     if (is_dir($path) && $cacheManager->deleteTree($path, array_merge(array('deleteTop' => true, 'skipDirs' => false, 'extensions' => array()), $options))) {
                                         $resolved = true;
                                     } elseif (is_file($path) && unlink($path)) {
                                         $resolved = true;
                                     } else {
                                         $transport->xpdo->log(xPDO::LOG_LEVEL_ERROR, 'Could not remove files from path: ' . $path);
                                     }
                                 } else {
                                     $transport->xpdo->log(xPDO::LOG_LEVEL_ERROR, 'Could not find files to remove.');
                                 }
                             } else {
                                 /* action was chosen not to remove, send log message and continue */
                                 $transport->xpdo->log(xPDO::LOG_LEVEL_INFO, 'Skipping removing of files according to vehicle attributes.');
                                 $resolved = true;
                             }
                             if ($preExistingMode === xPDOTransport::RESTORE_PREEXISTING && file_exists($preservedArchive)) {
                                 $transport->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Attempting to restore files to {$fileTarget} from archive {$preservedArchive}");
                                 $unpackedResult = xPDOTransport::_unpack($transport->xpdo, $preservedArchive, $fileTarget);
                                 if ($unpackedResult > 0) {
                                     $resolved = true;
                                 } else {
                                     $transport->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Error unpacking preserved files from archive {$preservedArchive}");
                                 }
                             }
                             break;
                     }
                     break;
                 case 'php':
                     if (isset($options[xPDOTransport::RESOLVE_PHP]) && !$options[xPDOTransport::RESOLVE_PHP]) {
                         continue;
                     }
                     $fileMeta = $transport->xpdo->fromJSON($body, true);
                     $fileName = $fileMeta['name'];
                     $fileSource = $transport->path . $fileMeta['source'];
                     if (!($resolved = (include $fileSource))) {
                         $transport->xpdo->log(xPDO::LOG_LEVEL_ERROR, "xPDOVehicle resolver failed: type php ({$fileSource})");
                     }
                     break;
                 default:
                     $transport->xpdo->log(xPDO::LOG_LEVEL_WARN, "xPDOVehicle does not support resolvers of type {$type}.");
                     break;
             }
         }
     } else {
         $resolved = true;
     }
     return $resolved;
 }
 /**
  * Pack the {@link xPDOTransport} instance in preparation for distribution.
  *
  * @return boolean Indicates if the transport was packed successfully.
  */
 public function pack()
 {
     if (empty($this->vehicles)) {
         $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, 'Attempt to pack a transport package with no vehicles.');
         return false;
     }
     $this->writeManifest();
     $path = $this->path;
     $pos = strpos($path, ':');
     if ($pos !== false) {
         $path = substr($path, $pos + 1);
     }
     $fileName = $path . $this->signature . '.transport.zip';
     return xPDOTransport::_pack($this->xpdo, $fileName, $path, $this->signature);
 }