/** * Called when this object is called as a function * * @param Context $context * @param OptionsFactory $optionsFactory * @throws \Exception if haltOnError setting is true */ public function __invoke(Context $context, OptionsFactory $optionsFactory) { $getopt = $context->getopt(array_keys(self::$options)); // Get directory list $dirListFactory = new DirectoryListFactory(); $dirListFactory->loadFromCommandline($getopt->get(), 2); $dirListFactory->loadFromStdin(new StdinReader(3)); $dirList = $dirListFactory->getList(); $this->logger->addDebug('Found directories', [count($dirList)]); // Load base options $baseOptions = $optionsFactory->newInstance(); $baseOptions->validateAllRequired(); if ($baseOptions->preview) { $this->logger->addNotice('PREVIEW MODE'); } foreach ($dirList as $dir) { try { $this->logger->addNotice('In directory', [$dir]); $this->processDirectory($dir, $baseOptions, $optionsFactory); } catch (\Exception $e) { if ($baseOptions->haltOnError) { throw $e; } elseif ($baseOptions->verbosity == 2) { $this->logger->addError($e, []); } else { $this->logger->addError($e->getMessage(), []); } } } }
/** * Called when this object is called as a function * * @param Context $context * @param OptionsFactory $optionsFactory * @throws \Exception if haltOnError setting is true */ public function __invoke(Context $context, OptionsFactory $optionsFactory) { $getopt = $context->getopt(array_keys(self::$options)); // Load base options $baseOptions = $optionsFactory->newInstance(); $baseOptions->validateAllRequired(); $result = $this->api->getBrands(); $this->stdio->outln(json_encode($result['brands'], JSON_PRETTY_PRINT)); }
/** * Changes the access level for a ShootProof gallery (event) * * If no event option is specified and a .shootproof file exists in the * directory, then event will be read from that file. * * @param string $dir The directory to process * @param Options $baseOptions * @param OptionsFactory $optionsFactory */ protected function processDirectory($dir, Options $baseOptions, OptionsFactory $optionsFactory) { // Reload the options and read the directory config file $options = $optionsFactory->newInstance([], $this->getValidators()); $configPath = new TildeExpander($dir) . '/.shootproof'; $configLoader = new DotenvLoader((string) $configPath); try { $configData = $configLoader->parse()->toArray(); $options->loadOptionData($configData, false); // don't overwrite CLI data $this->logger->addDebug('ShootProof settings file found', [$configPath, $configData]); } catch (\InvalidArgumentException $e) { // ignore $this->logger->addDebug('ShootProof settings file not found', [$configPath]); } // Make sure all required options are present $options->validateAllRequired(); $options->validate('password', $options->password); // Set the event access level $this->logger->addNotice('Setting access level', ['event' => $options->event, 'level' => $options->accessLevel, 'password' => $options->password ? str_repeat('*', strlen($options->password)) : null]); if (!$baseOptions->preview) { $result = $this->api->setEventAccessLevel($options->event, $options->accessLevel, $options->password); $this->logger->addDebug('Operation completed', $result); } }
/** * Pushes (uploads) files to ShootProof from the specified local directory * * @param string $dir The directory to process * @param Options $baseOptions * @param OptionsFactory $optionsFactory */ protected function processDirectory($dir, Options $baseOptions, OptionsFactory $optionsFactory) { // Reload the options and read the directory config file $options = $optionsFactory->newInstance([], $this->getValidators(), $this->getDefaults()); $configPath = new TildeExpander($dir) . '/.shootproof'; $configLoader = new DotenvLoader((string) $configPath); try { $configData = $configLoader->parse()->toArray(); $options->loadOptionData($configData, false); // don't overwrite CLI data $this->logger->addDebug('Config file found', [$configPath, $configData]); } catch (\InvalidArgumentException $e) { // ignore $this->logger->addDebug('Config file not found', [$configPath]); } // Make sure all required options are present $options->validateAllRequired(); // Get local file list $localFiles = array_map('basename', $this->getFileList($dir)); $eventId = $options->event ? $options->event : null; $albumId = $options->album ? $options->album : null; // Get remote file list switch ($options->target) { case 'album': // Create the album if (!$albumId) { list($eventId, $albumId) = $this->createAlbum($options, basename($dir)); } $this->logger->addDebug('Fetching album photos', [$albumId]); if ($baseOptions->preview) { $remoteFiles = new \ArrayObject(); } else { $remoteFiles = new ResultPager(function ($page) use($albumId) { $response = $this->api->getAlbumPhotos($albumId, $page + 1); return [(int) $response['total_pages'], $response['photos']]; }); } break; case 'event': // Create the event if (!$eventId) { $eventId = $this->createEvent($options, basename($dir)); } $this->logger->addDebug('Fetching event photos', [$eventId]); if ($baseOptions->preview) { $remoteFiles = new \ArrayObject(); } else { $remoteFiles = new ResultPager(function ($page) use($eventId) { $response = $this->api->getEventPhotos($eventId, $page + 1); return [(int) $response['total_pages'], $response['photos']]; }); } break; } // Turn the response into an array of stringifiable objects so we can compare file names $remoteFiles = array_map([new ShootProofFile(), 'arrayFactory'], $remoteFiles->getArrayCopy()); // Compute files to add, remove, and replace $calculator = new FileSetCalculator($localFiles, $remoteFiles, $options->replace); foreach ($calculator->add() as $file) { $filePath = $dir . DIRECTORY_SEPARATOR . $file; $this->logger->addNotice('Uploading new file to ShootProof', [$filePath]); if (!$baseOptions->preview) { $this->uploadFile($filePath, $eventId, $albumId, $options->retryLimit); } } foreach ($calculator->remove() as $file) { $this->logger->addNotice('Deleting remote file', [$file->getId(), (string) $file]); if (!$baseOptions->preview) { $this->deleteFile($file->getId(), $options->retryLimit); } } foreach ($calculator->replace() as $file) { $filePath = $dir . DIRECTORY_SEPARATOR . $file; $this->logger->addNotice('Replacing remote file', [$file->getId(), $filePath]); if (!$baseOptions->preview) { $this->updateFile($filePath, $file->getId(), $options->retryLimit); } } // Write ShootProof metadata to the directory try { $writer = new ConfigWriter(['target' => $options->target, 'event' => $eventId, 'album' => $albumId]); if (!$baseOptions->preview) { $writer->write($configPath); } $this->logger->addDebug('ShootProof settings file saved', [$configPath]); } catch (\InvalidArgumentException $e) { $this->logger->addWarning('ShootProof settings file is unwritable', [$configPath]); } catch (\RuntimeException $e) { $this->logger->addWarning('Failed writing ShootProof settings file', [$configPath]); } }
/** * Pulls (downloads) files from ShootProof to the specified local directory * * @param string $dir The directory to process * @param Options $baseOptions * @param OptionsFactory $optionsFactory * @throws ValidatorException if event or album options are not provided */ protected function processDirectory($dir, Options $baseOptions, OptionsFactory $optionsFactory) { // If the directory doesn't exist, create it and any parent dirs if (!file_exists($dir)) { if ($baseOptions->preview || @mkdir($dir, 0777, true)) { $this->logger->addNotice('Created directory', [$dir]); } else { $this->logger->addError('Failed to create directory', [$dir]); return; } } // Reload the options and read the directory config file $options = $optionsFactory->newInstance([], $this->getValidators(), $this->getDefaults()); $configPath = new TildeExpander($dir) . '/.shootproof'; $configLoader = new DotenvLoader((string) $configPath); try { $configData = $configLoader->parse()->toArray(); $options->loadOptionData($configData, false); // don't overwrite CLI data $this->logger->addDebug('ShootProof settings file found', [$configPath, $configData]); } catch (\InvalidArgumentException $e) { // ignore $this->logger->addDebug('ShootProof settings file not found', [$configPath]); } // Make sure all required options are present $options->validateAllRequired(); if (!$options->event && !$options->album) { throw new ValidatorException('Either --event or --album is required'); } // Get local file list $localFiles = array_map('basename', $this->getFileList($dir)); // Get remote file list switch ($options->target) { case 'album': $this->logger->addDebug('Fetching album photos', [$options->album]); $remoteFiles = new ResultPager(function ($page) use($options) { $response = $this->api->getAlbumPhotos($options->album, $page + 1); return [(int) $response['total_pages'], $response['photos']]; }); break; case 'event': $this->logger->addDebug('Fetching event photos', [$options->event]); $remoteFiles = new ResultPager(function ($page) use($options) { $response = $this->api->getEventPhotos($options->event, $page + 1); return [(int) $response['total_pages'], $response['photos']]; }); break; } // Turn the response into an array of stringifiable objects so we can compare file names $remoteFiles = array_map([new ShootProofFile(), 'arrayFactory'], $remoteFiles->getArrayCopy()); // Compute files to add, remove, and replace $calculator = new FileSetCalculator($remoteFiles, $localFiles, $options->replace); foreach ($calculator->add() as $file) { // download $filePath = $dir . DIRECTORY_SEPARATOR . $file; $this->logger->addNotice('Downloading new file from ShootProof', [$filePath]); if (!$baseOptions->preview) { $this->downloadFile($file->getUrl('original'), $filePath, $baseOptions); } } foreach ($calculator->remove() as $file) { $filePath = $dir . DIRECTORY_SEPARATOR . $file; $this->logger->addNotice('Deleting local file', [$filePath]); if (!$baseOptions->preview) { @unlink($filePath); } } foreach ($calculator->replace() as $file) { $filePath = $dir . DIRECTORY_SEPARATOR . $file; $this->logger->addNotice('Replacing local file', [$filePath]); if (!$baseOptions->preview) { @unlink($filePath); $this->downloadFile($file->getUrl('original'), $filePath, $baseOptions); } } // Write ShootProof metadata to the directory try { $writer = new ConfigWriter(['target' => $options->target, $options->target => $options->{$options->target}]); if (!$baseOptions->preview) { $writer->write($configPath); } $this->logger->addDebug('ShootProof settings file saved', [$configPath]); } catch (\InvalidArgumentException $e) { $this->logger->addWarning('ShootProof settings file is unwritable', [$configPath]); } catch (\RuntimeException $e) { $this->logger->addWarning('Failed writing ShootProof settings file', [$configPath]); } }