This method also allow you to override an existing placeholder.
public static setPlaceholderFormatterDefinition ( string $name, callable $callable ) | ||
$name | string | The placeholder name (including the delimiter char like %) |
$callable | callable | A PHP callable |
/** * @return bool */ public function download() { if ($this->isDownloaded()) { return true; } $httpClient = new Client(); $request = new Request('GET', $this->getUrl()); $response = $httpClient->send($request, [RequestOptions::PROGRESS => function ($total, $current) { if ($total <= 0 || !$this->output) { return; } if (!$this->progressBar) { $this->progressBar = new ProgressBar($this->output, $total); $this->progressBar->setPlaceholderFormatterDefinition('max', function (ProgressBar $bar) { return $this->formatSize($bar->getMaxSteps()); }); $this->progressBar->setPlaceholderFormatterDefinition('current', function (ProgressBar $bar) { return str_pad($this->formatSize($bar->getProgress()), 11, ' ', STR_PAD_LEFT); }); } $this->progressBar->setProgress($current); }]); $this->filesystem->dumpFile($this->getDestinationFile(), $response->getBody()->getContents()); $this->downloaded = true; return true; }
private function setupProgressBar() { ProgressBar::setPlaceholderFormatterDefinition('photo_size', function (ProgressBar $bar) { return $this->filesizeFormater->format($bar->getMaxSteps()); }); ProgressBar::setPlaceholderFormatterDefinition('downloaded_bytes', function (ProgressBar $bar) { return $this->filesizeFormater->format($bar->getStep()); }); }
protected function getProgressBar($nbIteration, $message) { $bar = new ProgressBar($this->output, $nbIteration); ProgressBar::setPlaceholderFormatterDefinition('memory', function (ProgressBar $bar) { static $i = 0; $mem = memory_get_usage(); $colors = $i++ ? '41;37' : '44;37'; return "[" . $colors . 'm ' . Helper::formatMemory($mem) . " [0m"; }); $bar->setFormat(" [44;37m %title:-38s% [0m\n %current%/%max% %bar% %percent:3s%%\n 🏁 %remaining:-10s% %memory:37s%\n"); $bar->setBarCharacter("[32m●[0m"); $bar->setEmptyBarCharacter("[31m●[0m"); $bar->setMessage($message, 'title'); $bar->start(); return $bar; }
/** * Download a file from the URL to the destination. * * @param string $url Fully qualified URL to the file. * @param bool $progress Show the progressbar when downloading. */ public function downloadFile($url, $progress = true) { /** @var ProgressBar|null $progressBar */ $progressBar = null; $downloadCallback = function ($size, $downloaded, $client, $request, Response $response) use(&$progressBar) { // Don't initialize the progress bar for redirects as the size is much smaller. if ($response->getStatusCode() >= 300) { return; } if (null === $progressBar) { ProgressBar::setPlaceholderFormatterDefinition('max', function (ProgressBar $bar) { return $this->formatSize($bar->getMaxSteps()); }); ProgressBar::setPlaceholderFormatterDefinition('current', function (ProgressBar $bar) { return str_pad($this->formatSize($bar->getProgress()), 11, ' ', STR_PAD_LEFT); }); $progressBar = new ProgressBar($this->output, $size); $progressBar->setFormat('%current%/%max% %bar% %percent:3s%%'); $progressBar->setRedrawFrequency(max(1, floor($size / 1000))); $progressBar->setBarWidth(60); if (!defined('PHP_WINDOWS_VERSION_BUILD')) { $progressBar->setEmptyBarCharacter('░'); // light shade character \u2591 $progressBar->setProgressCharacter(''); $progressBar->setBarCharacter('▓'); // dark shade character \u2593 } $progressBar->start(); } $progressBar->setProgress($downloaded); }; $client = $this->getGuzzleClient(); if ($progress) { $this->output->writeln(sprintf("\n Downloading %s...\n", $url)); $client->getEmitter()->attach(new Progress(null, $downloadCallback)); } $response = $client->get($url); $tmpFile = $this->filesystemHelper->newTempFilename(); $this->fs->dumpFile($tmpFile, $response->getBody()); if (null !== $progressBar) { $progressBar->finish(); $this->output->writeln("\n"); } return $tmpFile; }
public function testAnsiColorsAndEmojis() { $bar = new ProgressBar($output = $this->getOutputStream(), 15); ProgressBar::setPlaceholderFormatterDefinition('memory', function (ProgressBar $bar) { static $i = 0; $mem = 100000 * $i; $colors = $i++ ? '41;37' : '44;37'; return "[" . $colors . 'm ' . Helper::formatMemory($mem) . " [0m"; }); $bar->setFormat(" [44;37m %title:-37s% [0m\n %current%/%max% %bar% %percent:3s%%\n 🏁 %remaining:-10s% %memory:37s%"); $bar->setBarCharacter($done = "[32m●[0m"); $bar->setEmptyBarCharacter($empty = "[31m●[0m"); $bar->setProgressCharacter($progress = "[32m➤ [0m"); $bar->setMessage('Starting the demo... fingers crossed', 'title'); $bar->start(); $bar->setMessage('Looks good to me...', 'title'); $bar->advance(4); $bar->setMessage('Thanks, bye', 'title'); $bar->finish(); rewind($output->getStream()); $this->assertEquals($this->generateOutput(" [44;37m Starting the demo... fingers crossed [0m\n" . ' 0/15 ' . $progress . str_repeat($empty, 26) . " 0%\n" . " 🏁 1 sec [44;37m 0 B [0m") . $this->generateOutput(" [44;37m Looks good to me... [0m\n" . ' 4/15 ' . str_repeat($done, 7) . $progress . str_repeat($empty, 19) . " 26%\n" . " 🏁 1 sec [41;37m 97 KiB [0m") . $this->generateOutput(" [44;37m Thanks, bye [0m\n" . ' 15/15 ' . str_repeat($done, 28) . " 100%\n" . " 🏁 1 sec [41;37m 195 KiB [0m"), stream_get_contents($output->getStream())); }
/** * Chooses the best compressed file format to download (ZIP or TGZ) depending upon the * available operating system uncompressing commands and the enabled PHP extensions * and it downloads the file. * * @throws \RuntimeException if the ProcessWire archive could not be downloaded */ private function download() { $this->output->writeln("\n Downloading ProcessWire Version " . $this->branch['version'] . "..."); $distill = new Distill(); $pwArchiveFile = $distill->getChooser()->setStrategy(new MinimumSize())->addFile($this->branch['zipURL'])->getPreferredFile(); /** @var ProgressBar|null $progressBar */ $progressBar = null; $downloadCallback = function ($size, $downloaded, $client, $request, Response $response) use(&$progressBar) { // Don't initialize the progress bar for redirects as the size is much smaller if ($response->getStatusCode() >= 300) { return; } if (null === $progressBar) { ProgressBar::setPlaceholderFormatterDefinition('max', function (ProgressBar $bar) { return $this->formatSize($bar->getMaxSteps()); }); ProgressBar::setPlaceholderFormatterDefinition('current', function (ProgressBar $bar) { return str_pad($this->formatSize($bar->getStep()), 11, ' ', STR_PAD_LEFT); }); $progressBar = new ProgressBar($this->output, $size); $progressBar->setFormat('%current%/%max% %bar% %percent:3s%%'); $progressBar->setRedrawFrequency(max(1, floor($size / 1000))); $progressBar->setBarWidth(60); if (!defined('PHP_WINDOWS_VERSION_BUILD')) { $progressBar->setEmptyBarCharacter('░'); // light shade character \u2591 $progressBar->setProgressCharacter(''); $progressBar->setBarCharacter('▓'); // dark shade character \u2593 } $progressBar->start(); } $progressBar->setProgress($downloaded); }; $client = new Client(); $client->getEmitter()->attach(new Progress(null, $downloadCallback)); // store the file in a temporary hidden directory with a random name $this->compressedFilePath = getcwd() . DIRECTORY_SEPARATOR . '.' . uniqid(time()) . DIRECTORY_SEPARATOR . 'pw.' . pathinfo($pwArchiveFile, PATHINFO_EXTENSION); try { $response = $client->get($pwArchiveFile); } catch (ClientException $e) { if ($e->getCode() === 403 || $e->getCode() === 404) { throw new \RuntimeException(sprintf("The selected version (%s) cannot be installed because it does not exist.\n" . "Try the special \"latest\" version to install the latest stable ProcessWire release:\n" . '%s %s %s latest', $this->version, $_SERVER['PHP_SELF'], $this->getName(), $this->projectDir)); } else { throw new \RuntimeException(sprintf("The selected version (%s) couldn't be downloaded because of the following error:\n%s", $this->version, $e->getMessage())); } } $this->fs->dumpFile($this->compressedFilePath, $response->getBody()); if (null !== $progressBar) { $progressBar->finish(); $this->output->writeln("\n"); } return $this; }
/** * Chooses the best compressed file format to download (ZIP or TGZ) depending upon the * available operating system uncompressing commands and the enabled PHP extensions * and it downloads the file. * * @return $this * * @throws \RuntimeException If the Symfony archive could not be downloaded */ protected function download() { $this->output->writeln(sprintf("\n Downloading %s...\n", $this->getDownloadedApplicationType())); // decide which is the best compressed version to download $distill = new Distill(); $symfonyArchiveFile = $distill->getChooser()->setStrategy(new MinimumSize())->addFilesWithDifferentExtensions($this->getRemoteFileUrl(), ['tgz', 'zip'])->getPreferredFile(); /** @var ProgressBar|null $progressBar */ $progressBar = null; $downloadCallback = function (ProgressEvent $event) use(&$progressBar) { $downloadSize = $event->downloadSize; $downloaded = $event->downloaded; // progress bar is only displayed for files larger than 1MB if ($downloadSize < 1 * 1024 * 1024) { return; } if (null === $progressBar) { ProgressBar::setPlaceholderFormatterDefinition('max', function (ProgressBar $bar) { return $this->formatSize($bar->getMaxSteps()); }); ProgressBar::setPlaceholderFormatterDefinition('current', function (ProgressBar $bar) { return str_pad($this->formatSize($bar->getProgress()), 11, ' ', STR_PAD_LEFT); }); $progressBar = new ProgressBar($this->output, $downloadSize); $progressBar->setFormat('%current%/%max% %bar% %percent:3s%%'); $progressBar->setRedrawFrequency(max(1, floor($downloadSize / 1000))); $progressBar->setBarWidth(60); if (!defined('PHP_WINDOWS_VERSION_BUILD')) { $progressBar->setEmptyBarCharacter('░'); // light shade character \u2591 $progressBar->setProgressCharacter(''); $progressBar->setBarCharacter('▓'); // dark shade character \u2593 } $progressBar->start(); } $progressBar->setProgress($downloaded); }; $client = $this->getGuzzleClient(); // store the file in a temporary hidden directory with a random name $this->downloadedFilePath = rtrim(getcwd(), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . '.' . uniqid(time()) . DIRECTORY_SEPARATOR . 'symfony.' . pathinfo($symfonyArchiveFile, PATHINFO_EXTENSION); try { $request = $client->createRequest('GET', $symfonyArchiveFile); $request->getEmitter()->on('progress', $downloadCallback); $response = $client->send($request); } catch (ClientException $e) { if ('new' === $this->getName() && ($e->getCode() === 403 || $e->getCode() === 404)) { throw new \RuntimeException(sprintf("The selected version (%s) cannot be installed because it does not exist.\n" . "Execute the following command to install the latest stable Symfony release:\n" . '%s new %s', $this->version, $_SERVER['PHP_SELF'], str_replace(getcwd() . DIRECTORY_SEPARATOR, '', $this->projectDir))); } else { throw new \RuntimeException(sprintf("There was an error downloading %s from symfony.com server:\n%s", $this->getDownloadedApplicationType(), $e->getMessage()), null, $e); } } $this->fs->dumpFile($this->downloadedFilePath, $response->getBody()); if (null !== $progressBar) { $progressBar->finish(); $this->output->writeln("\n"); } return $this; }
/** * Wait for multiple activities to complete. * * A progress bar tracks the state of each activity. The activity log is * only displayed at the end, if an activity failed. * * @param Activity[] $activities * @param OutputInterface $output * * @return bool * True if all activities succeed, false otherwise. */ public static function waitMultiple(array $activities, OutputInterface $output) { $count = count($activities); if ($count == 0) { return true; } elseif ($count === 1) { return self::waitAndLog(reset($activities), $output); } $output->writeln("Waiting for {$count} activities..."); // Initialize a progress bar which will show elapsed time and all of the // activities' states. $bar = new ProgressBar($output); $states = []; foreach ($activities as $activity) { $state = $activity->state; $states[$state] = isset($states[$state]) ? $states[$state] + 1 : 1; } $bar->setPlaceholderFormatterDefinition('states', function () use(&$states) { $format = ''; foreach ($states as $state => $count) { $format .= $count . ' ' . self::formatState($state) . ', '; } return rtrim($format, ', '); }); $bar->setFormat(" [%bar%] %elapsed:6s% (%states%)"); $bar->start(); // Wait for the activities to complete, polling (refreshing) all of them // with a 1 second delay. $complete = 0; while ($complete < $count) { sleep(1); $states = []; $complete = 0; foreach ($activities as $activity) { if (!$activity->isComplete()) { $activity->refresh(); } else { $complete++; } $state = $activity->state; $states[$state] = isset($states[$state]) ? $states[$state] + 1 : 1; } $bar->advance(); } $bar->finish(); $output->writeln(''); // Display success or failure messages for each activity. $success = true; foreach ($activities as $activity) { $description = $activity->getDescription(); switch ($activity['result']) { case Activity::RESULT_SUCCESS: $output->writeln("Activity <info>{$activity->id}</info> succeeded: {$description}"); break; case Activity::RESULT_FAILURE: $success = false; $output->writeln("Activity <error>{$activity->id}</error> failed"); // If the activity failed, show the complete log. $output->writeln(" Description: {$description}"); $output->writeln(" Log:"); $output->writeln(preg_replace('/^/m', ' ', $activity->log)); break; } } return $success; }
/** * Downloads the oxid archive * * @param OutputInterface $output * @param $url * @return string */ protected function downloadOxid(OutputInterface $output, $version) { $file = sys_get_temp_dir() . '/oxrun-' . time() . '.zip'; $progressBar = null; $client = new Client(); try { $githubToken = getenv('GITHUB_TOKEN'); if ($githubToken) { $request = $client->createRequest('GET', $version['zip'] . '?access_token=' . $githubToken, array('save_to' => $file)); } else { $request = $client->createRequest('GET', $version['zip'], array('save_to' => $file)); } $request->getEmitter()->on('progress', function (ProgressEvent $e) use(&$progressBar, $output) { if (null === $progressBar && $e->downloadSize !== 0) { ProgressBar::setPlaceholderFormatterDefinition('max', function (ProgressBar $bar) { return $this->formatSize($bar->getMaxSteps()); }); ProgressBar::setPlaceholderFormatterDefinition('current', function (ProgressBar $bar) { return str_pad($this->formatSize($bar->getStep()), 11, ' ', STR_PAD_LEFT); }); $progressBar = new ProgressBar($output, $e->downloadSize); $progressBar->setFormat('%current%/%max% %bar% %percent:3s%%'); $progressBar->setRedrawFrequency(max(1, floor($e->downloadSize / 1000))); $progressBar->setBarWidth(60); if (!defined('PHP_WINDOWS_VERSION_BUILD')) { $progressBar->setEmptyBarCharacter('░'); // light shade character \u2591 $progressBar->setProgressCharacter(''); $progressBar->setBarCharacter('▓'); // dark shade character \u2593 } $progressBar->start(); } if ($progressBar) { $progressBar->setProgress($e->downloaded); } }); $client->send($request); } catch (ClientException $e) { throw new \RuntimeException(sprintf("There was an error downloading:\n%s", $e->getMessage()), null, $e); } if (null !== $progressBar) { $progressBar->finish(); $output->writeln("\n"); } return $file; }
/** * Wait for multiple activities to complete. * * A progress bar tracks the state of each activity. The activity log is * only displayed at the end, if an activity failed. * * @param Activity[] $activities * @param OutputInterface $output * @param Project $project * * @return bool * True if all activities succeed, false otherwise. */ public static function waitMultiple(array $activities, OutputInterface $output, Project $project) { $count = count($activities); if ($count == 0) { return true; } elseif ($count === 1) { return self::waitAndLog(reset($activities), $output); } $output->writeln("Waiting for {$count} activities..."); // Initialize a progress bar which will show elapsed time and all of the // activities' states. $bar = new ProgressBar($output); $states = []; foreach ($activities as $activity) { $state = $activity->state; $states[$state] = isset($states[$state]) ? $states[$state] + 1 : 1; } $bar->setPlaceholderFormatterDefinition('states', function () use(&$states) { $format = ''; foreach ($states as $state => $count) { $format .= $count . ' ' . self::formatState($state) . ', '; } return rtrim($format, ', '); }); $bar->setFormat(" [%bar%] %elapsed:6s% (%states%)"); $bar->start(); // Get the most recent created date of each of the activities, as a Unix // timestamp, so that they can be more efficiently refreshed. $mostRecentTimestamp = 0; foreach ($activities as $activity) { $created = strtotime($activity->created_at); $mostRecentTimestamp = $created > $mostRecentTimestamp ? $created : $mostRecentTimestamp; } // Wait for the activities to complete, polling (refreshing) all of them // with a 1 second delay. $complete = 0; while ($complete < $count) { sleep(1); $states = []; $complete = 0; // Get a list of activities on the project. Any of our activities // which are not contained in this list must be refreshed // individually. $projectActivities = $project->getActivities(0, null, $mostRecentTimestamp ?: null); foreach ($activities as $activity) { $refreshed = false; foreach ($projectActivities as $projectActivity) { if ($projectActivity->id === $activity->id) { $activity = $projectActivity; $refreshed = true; break; } } if (!$refreshed && !$activity->isComplete()) { $activity->refresh(); } if ($activity->isComplete()) { $complete++; } $state = $activity->state; $states[$state] = isset($states[$state]) ? $states[$state] + 1 : 1; } $bar->advance(); } $bar->finish(); $output->writeln(''); // Display success or failure messages for each activity. $success = true; foreach ($activities as $activity) { $description = $activity->getDescription(); switch ($activity['result']) { case Activity::RESULT_SUCCESS: $output->writeln("Activity <info>{$activity->id}</info> succeeded: {$description}"); break; case Activity::RESULT_FAILURE: $success = false; $output->writeln("Activity <error>{$activity->id}</error> failed"); // If the activity failed, show the complete log. $output->writeln(" Description: {$description}"); $output->writeln(" Log:"); $output->writeln(preg_replace('/^/m', ' ', $activity->log)); break; } } return $success; }
/** * Chooses the best compressed file format to download (ZIP or TGZ) depending upon the * available operating system uncompressing commands and the enabled PHP extensions * and it downloads the file. * * @param string $url * @param string $module * @param OutputInterface $output * @return NewCommand * * @throws \RuntimeException if the ProcessWire archive could not be downloaded */ public function downloadModule($url, $module, $output) { $output->writeln(" Downloading module {$module}..."); $distill = new Distill(); $pwArchiveFile = $distill->getChooser()->setStrategy(new MinimumSize())->addFile($url)->getPreferredFile(); /** @var ProgressBar|null $progressBar */ $progressBar = null; $downloadCallback = function ($size, $downloaded, $client, $request, Response $response) use(&$progressBar, &$output) { // Don't initialize the progress bar for redirects as the size is much smaller if ($response->getStatusCode() >= 300) { return; } if (null === $progressBar) { ProgressBar::setPlaceholderFormatterDefinition('max', function (ProgressBar $bar) { return $this->formatSize($bar->getMaxSteps()); }); ProgressBar::setPlaceholderFormatterDefinition('current', function (ProgressBar $bar) { return str_pad($this->formatSize($bar->getStep()), 11, ' ', STR_PAD_LEFT); }); $progressBar = new ProgressBar($output, $size); $progressBar->setFormat('%current%/%max% %bar% %percent:3s%%'); $progressBar->setRedrawFrequency(max(1, floor($size / 1000))); $progressBar->setBarWidth(60); if (!defined('PHP_WINDOWS_VERSION_BUILD')) { $progressBar->setEmptyBarCharacter('░'); // light shade character \u2591 $progressBar->setProgressCharacter(''); $progressBar->setBarCharacter('▓'); // dark shade character \u2593 } $progressBar->start(); } $progressBar->setProgress($downloaded); }; $client = new Client(); $client->getEmitter()->attach(new Progress(null, $downloadCallback)); // store the file in a temporary hidden directory with a random name $this->compressedFilePath = \ProcessWire\wire('config')->paths->siteModules . '.' . uniqid(time()) . DIRECTORY_SEPARATOR . $module . '.' . pathinfo($pwArchiveFile, PATHINFO_EXTENSION); try { $response = $client->get($pwArchiveFile); } catch (ClientException $e) { if ($e->getCode() === 403 || $e->getCode() === 404) { throw new \RuntimeException("The selected module {$module} cannot be downloaded because it does not exist.\n"); } else { throw new \RuntimeException(sprintf("The selected module (%s) couldn't be downloaded because of the following error:\n%s", $module, $e->getMessage())); } } $fs = new Filesystem(); $fs->dumpFile($this->compressedFilePath, $response->getBody()); if (null !== $progressBar) { $progressBar->finish(); $output->writeln("\n"); } return $this; }
public function getProgressBar(OutputInterface $output, $max) { if ($this->progressBar instanceof ProgressBar) { return $this->progressBar; } ProgressBar::setPlaceholderFormatterDefinition('rejected', function (ProgressBar $bar) { return \Omnislash\Helper\GuzzleHelper::$rejected; }); ProgressBar::setPlaceholderFormatterDefinition('fulfilled', function (ProgressBar $bar) { return \Omnislash\Helper\GuzzleHelper::$fulfilled; }); $progress = new ProgressBar($output, $max); $format = ' %current%/%max% [%bar%] %percent:3s%%'; $format .= ' Fulfilled: %fulfilled% / Rejected: %rejected%'; $format .= ' %elapsed:6s%/%estimated:-6s% %memory:6s%'; $progress->setFormat($format); $progress->setBarCharacter('<comment>=</comment>'); return $this->progressBar = $progress; }