From bf7f2ffd1476dd4f65b373df0de23a5208bb8e57 Mon Sep 17 00:00:00 2001 From: Black Senator Date: Tue, 14 Apr 2020 22:28:20 +0200 Subject: [PATCH] symfony output Fix #199 --- src/BackgroundCommand.php | 18 ++++----- src/CardDav/Backend.php | 10 +++-- src/CardDav/VcardFile.php | 16 +++++--- src/ConvertCommand.php | 27 +++++++------ src/DownloadCommand.php | 12 +++--- src/DownloadTrait.php | 48 +++++++++++++++------- src/FritzBox/BackgroundImage.php | 14 +++++-- src/FritzBox/Converter.php | 18 ++++++--- src/FritzBox/Restorer.php | 11 +++-- src/RunCommand.php | 44 ++++++++++---------- src/UploadCommand.php | 10 ++--- src/functions.php | 69 +++++++++++++++++++------------- tests/ConverterTest.php | 16 ++++++-- tests/FunctionsTest.php | 16 ++++++-- tests/RestorerTest.php | 3 +- 15 files changed, 204 insertions(+), 128 deletions(-) diff --git a/src/BackgroundCommand.php b/src/BackgroundCommand.php index c3f3aa4a..b7934426 100644 --- a/src/BackgroundCommand.php +++ b/src/BackgroundCommand.php @@ -3,12 +3,8 @@ namespace Andig; use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Helper\ProgressBar; class BackgroundCommand extends Command { @@ -31,16 +27,16 @@ protected function execute(InputInterface $input, OutputInterface $output) $ftpDisabled = $this->config['fritzbox']['ftp']['disabled'] ?? false; if (count($this->config['fritzbox']['fritzfons']) && $this->config['phonebook']['id'] == 0 && !$ftpDisabled) { - error_log('Downloading FRITZ!Box phonebook'); - $xmlPhonebook = downloadPhonebook($this->config['fritzbox'], $this->config['phonebook']); - if (count($savedAttributes = uploadAttributes($xmlPhonebook, $this->config))) { - error_log('Numbers with special attributes saved' . PHP_EOL); + $output->writeln('Downloading recent FRITZ!Box phonebook'); + $xmlPhonebook = downloadPhonebook($this->config['fritzbox'], $this->config['phonebook'], $output); + if (count($savedAttributes = uploadAttributes($xmlPhonebook, $this->config, $output))) { + $output->writeln('Phone numbers with special attributes saved'); } else { // no attributes are set in the FRITZ!Box or lost - $savedAttributes = downloadAttributes($this->config['fritzbox']); // try to get last saved attributes + $savedAttributes = downloadAttributes($this->config['fritzbox'], $output); // try to get last saved attributes } - uploadBackgroundImage($savedAttributes, $this->config['fritzbox']); + uploadBackgroundImage($savedAttributes, $this->config['fritzbox'], $output); } else { - error_log('No destination phones are defined and/or the first phone book is not selected!'); + $output->writeln('No destination phones are defined and/or the first phone book is not selected!'); } return 0; diff --git a/src/CardDav/Backend.php b/src/CardDav/Backend.php index 2a169343..438af4d4 100644 --- a/src/CardDav/Backend.php +++ b/src/CardDav/Backend.php @@ -7,6 +7,7 @@ use Sabre\VObject\Reader; use GuzzleHttp\Client; use GuzzleHttp\Exception\RequestException; +use Symfony\Component\Console\Output\OutputInterface; /** * @author Christian Putzke @@ -50,23 +51,26 @@ class Backend */ private $client; + /** @var OutputInterface */ + private $output; + /** * Constructor * Sets the CardDAV server url * * @param string $url CardDAV server url */ - public function __construct(string $url=null) + public function __construct(OutputInterface $output, string $url = null) { if ($url) { $this->setUrl($url); } - $this->setClientOptions([ 'headers' => [ 'Depth' => 1 ] ]); + $this->output = $output; } /** @@ -152,7 +156,7 @@ public function getVcards(): array ]); } catch (RequestException $e) { if ($e->hasResponse() && 404 == $e->getResponse()->getStatusCode()) { - error_log('Ignoring empty response from carddav REPORT request'); + $this->output->writeln('Ignoring empty response from carddav REPORT request'); return []; } diff --git a/src/CardDav/VcardFile.php b/src/CardDav/VcardFile.php index b7db9013..e2a73eea 100644 --- a/src/CardDav/VcardFile.php +++ b/src/CardDav/VcardFile.php @@ -5,6 +5,7 @@ use Andig\CardDav\Backend; use Sabre\VObject\Document; use Sabre\VObject\Splitter\VCard; +use Symfony\Component\Console\Output\OutputInterface; /** * @author Volker Püschel @@ -19,9 +20,9 @@ class VcardFile extends Backend */ private $fullpath; - public function __construct(string $fullpath = null) + public function __construct(OutputInterface $output, string $fullpath = null) { - parent::__construct(); + parent::__construct($output); $this->fullpath = $fullpath; } @@ -36,12 +37,16 @@ public function getVcards(): array return []; } if (!file_exists($this->fullpath)) { - error_log(sprintf('File %s not found!', $this->fullpath)); + $error = sprintf('File %s not found!', $this->fullpath); + $this->output->writeln('' . $error . ''); + return []; } $vcf = fopen($this->fullpath, 'r'); if (!$vcf) { - error_log(sprintf('File %s open failed!', $this->fullpath)); + $error = sprintf('File %s open failed!', $this->fullpath); + $this->output->writeln('' . $error . ''); + return []; } $cards = []; @@ -50,7 +55,8 @@ public function getVcards(): array if ($vCard instanceof Document) { $cards[] = $this->enrichVcard($vCard); } else { - error_log('Unexpected type: ' . get_class($vCard)); + $error = 'Unexpected type: ' . get_class($vCard); + $this->output->writeln('' . $error . ''); } $this->progress(); diff --git a/src/ConvertCommand.php b/src/ConvertCommand.php index d3a02d87..520f8802 100644 --- a/src/ConvertCommand.php +++ b/src/ConvertCommand.php @@ -3,12 +3,10 @@ namespace Andig; use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Helper\ProgressBar; class ConvertCommand extends Command { @@ -35,7 +33,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $ftpDisabled = $this->config['fritzbox']['ftp']['disabled'] ?? false; if ($ftpDisabled) { $input->setOption('image', false); - error_log('Images can only be uploaded if ftp is enabled!'); + $output->writeln('Images can only be uploaded if ftp is enabled!'); } // we want to check for image upload show stoppers as early as possible @@ -43,39 +41,42 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->checkUploadImagePreconditions($this->config['fritzbox'], $this->config['phonebook']); } - error_log("Reading vCard(s) from file " . $filename); + $output->writeln('Reading vCard(s) from file ' . $filename . ''); $provider = localProvider($filename); $vcards = $this->downloadProvider($output, $provider); - error_log(sprintf("\nRead %d vCard(s)", count($vcards))); + $info = sprintf("\nRead %d vCard(s)", count($vcards)); + $output->writeln('' . $info . ''); // image upload if ($input->getOption('image')) { - error_log("Detaching and uploading image(s)"); + $output->writeln('Detaching and uploading image(s)'); - $progress = new ProgressBar($output); + $progress = getProgressBar($output); $progress->start(count($vcards)); - $pictures = uploadImages($vcards, $this->config['fritzbox'], $this->config['phonebook'], function () use ($progress) { + $pictures = uploadImages($vcards, $this->config['fritzbox'], $this->config['phonebook'], $output, function () use ($progress) { $progress->advance(); }); $progress->finish(); if ($pictures) { - error_log(sprintf(PHP_EOL . "Uploaded/refreshed %d of %d image file(s)", $pictures[0], $pictures[1])); + $info = sprintf(PHP_EOL . "Uploaded/refreshed %d of %d image file(s)", $pictures[0], $pictures[1]); + $output->writeln('' . $info . ''); } } // fritzbox format - $xmlPhonebook = exportPhonebook($vcards, $this->config); - error_log(sprintf(PHP_EOL."Converted %d vCard(s)", count($vcards))); + $xmlPhonebook = exportPhonebook($vcards, $this->config, $output); + $output->writeln('' . sprintf(PHP_EOL."Converted %d vCard(s)", count($vcards)) . ''); if (!count($vcards)) { - error_log("Phonebook empty - skipping write to file"); + $output->writeln('Phonebook empty - skipping write to file!'); return 1; } $filename = $input->getArgument('destination'); if ($xmlPhonebook->asXML($filename)) { - error_log(sprintf("Succesfull saved phonebook as %s", $filename)); + $info = sprintf("Succesfull saved phonebook as %s", $filename); + $output->writeln('' . $info . ''); } return 0; diff --git a/src/DownloadCommand.php b/src/DownloadCommand.php index f1654da8..0fbd51e7 100644 --- a/src/DownloadCommand.php +++ b/src/DownloadCommand.php @@ -3,12 +3,10 @@ namespace Andig; use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Helper\ProgressBar; class DownloadCommand extends Command { @@ -35,16 +33,17 @@ protected function execute(InputInterface $input, OutputInterface $output) // download from server or local files $local = $input->getOption('local'); $vcards = $this->downloadAllProviders($output, $input->getOption('image'), $local); - error_log(sprintf("Downloaded %d vCard(s) in total", count($vcards))); + $info = sprintf("Downloaded %d vCard(s) in total", count($vcards)); + $output->writeln('' . $info . ''); // dissolve if ($input->getOption('dissolve')) { - $vcards = $this->processGroups($vcards); + $vcards = $this->processGroups($vcards, $output); } // filter if ($input->getOption('filter')) { - $vcards = $this->processFilters($vcards); + $vcards = $this->processFilters($vcards, $output); } // save to file @@ -55,7 +54,8 @@ protected function execute(InputInterface $input, OutputInterface $output) $filename = $input->getArgument('filename'); if (file_put_contents($filename, $vCardContents) != false) { - error_log(sprintf("Succesfully saved vCard(s) in %s", $filename)); + $info = sprintf("Succesfully saved vCard(s) in %s", $filename); + $output->writeln('' . $info . ''); } return 0; diff --git a/src/DownloadTrait.php b/src/DownloadTrait.php index 9ede9de0..92d20cbc 100644 --- a/src/DownloadTrait.php +++ b/src/DownloadTrait.php @@ -9,6 +9,21 @@ trait DownloadTrait { + /** + * get progress bar in info scheme (green) + * + * @param OutputInterface $output + * @return ProgressBar + */ + public function getProgressBar(OutputInterface $output): ProgressBar + { + $progress = new ProgressBar($output); + $progress->setFormatDefinition('info', '%current% [%bar%]'); + $progress->setFormat('info'); + + return $progress; + } + /** * Default list of card attributes to substitute * @@ -28,7 +43,7 @@ public function getDefaultSubstitutes(): array */ public function downloadProvider(OutputInterface $output, Backend $provider): array { - $progress = new ProgressBar($output); + $progress = self::getProgressBar($output); $progress->start(); $cards = download($provider, function () use ($progress) { $progress->advance(); @@ -50,26 +65,28 @@ public function downloadAllProviders(OutputInterface $output, bool $downloadImag $vcards = []; foreach ($local as $file) { - error_log("Reading vCard(s) from file ".$file); + $output->writeln('Reading vCard(s) from file '. $file . ''); $provider = localProvider($file); $cards = $this->downloadProvider($output, $provider); - error_log(sprintf("\nRead %d vCard(s)", count($cards))); + $info = sprintf("\nRead %d vCard(s)", count($cards)); + $output->writeln('' . $info . ''); $vcards = array_merge($vcards, $cards); } foreach ($this->config['server'] as $server) { - error_log("Downloading vCard(s) from account ".$server['user']); + $output->writeln('Downloading vCard(s) from account ' . $server['user'] . ''); - $provider = backendProvider($server); + $provider = backendProvider($server, $output); if ($downloadImages) { $substitutes = $this->getDefaultSubstitutes(); $provider->setSubstitutes($substitutes); } $cards = $this->downloadProvider($output, $provider); - error_log(sprintf("\nDownloaded %d vCard(s)", count($cards))); + $info = sprintf("\nDownloaded %d vCard(s)", count($cards)); + $output->writeln('' . $info . ''); $vcards = array_merge($vcards, $cards); } @@ -82,13 +99,13 @@ public function downloadAllProviders(OutputInterface $output, bool $downloadImag * @param mixed[] $vcards * @return mixed[] */ - public function processGroups(array $vcards): array + public function processGroups(array $vcards, $output): array { $quantity = count($vcards); - - error_log("Dissolving groups (e.g. iCloud)"); + $output->writeln('Dissolving groups (e.g. iCloud)'); $vcards = dissolveGroups($vcards); - error_log(sprintf("Dissolved %d group(s)", $quantity - count($vcards))); + $info = sprintf("Dissolved %d group(s)", $quantity - count($vcards)); + $output->writeln('' . $info . ''); return $vcards; } @@ -97,15 +114,18 @@ public function processGroups(array $vcards): array * Filter included/excluded vcards * * @param mixed[] $vcards + * @param OutputInterface $output * @return mixed[] */ - public function processFilters(array $vcards): array + public function processFilters(array $vcards, OutputInterface $output): array { $quantity = count($vcards); - error_log(sprintf("Filtering %d vCard(s)", $quantity)); - $vcards = filter($vcards, $this->config['filters']); - error_log(sprintf("Filtered %d vCard(s)", $quantity - count($vcards))); + $info = sprintf("Filtering %d vCard(s)", $quantity); + $output->writeln('' . $info . ''); + $vcards = filter($vcards, $this->config['filters'], $output); + $info = sprintf("Filtered %d vCard(s)", $quantity - count($vcards)); + $output->writeln('' . $info . ''); return $vcards; } diff --git a/src/FritzBox/BackgroundImage.php b/src/FritzBox/BackgroundImage.php index 58754ee7..fe66a95d 100644 --- a/src/FritzBox/BackgroundImage.php +++ b/src/FritzBox/BackgroundImage.php @@ -3,6 +3,7 @@ namespace Andig\FritzBox; use Andig\FritzBox\Api; +use Symfony\Component\Console\Output\OutputInterface; /** * Copyright (c) 2019 Volker Püschel @@ -20,8 +21,12 @@ class BackgroundImage /** @var int */ protected $textColor; - public function __construct() + /** @var OutputInterface */ + private $output; + + public function __construct(OutputInterface $output) { + $this->output = $output; $this->bgImage = $this->getImageAsset(dirname(__DIR__, 2) . '/assets/keypad.jpg'); putenv('GDFONTPATH=' . realpath('.')); $this->setFont(dirname(__DIR__, 2) . '/assets/impact.ttf'); @@ -212,15 +217,16 @@ public function uploadImage($quickdials, $config) continue; } - error_log(sprintf("Uploading background image to FRITZ!Fon #%s", $phone)); + $info = sprintf("Uploading background image to FRITZ!Fon #%s", $phone); + $this->output->writeln('' . $info . ''); $body = $this->getBody($fritz->getSID(), $phone, $backgroundImage); $result = $fritz->postImage($body); if (strpos($result, 'Das Bild wurde erfolgreich hinzugefügt') || strpos($result, 'The image was added successfully')) { - error_log('Background image upload successful'); + $this->output->writeln('Background image upload successful'); } else { - error_log('Background image upload failed'); + $this->output->writeln('Background image upload failed'); } } } diff --git a/src/FritzBox/Converter.php b/src/FritzBox/Converter.php index 1f2ecf12..83efe648 100644 --- a/src/FritzBox/Converter.php +++ b/src/FritzBox/Converter.php @@ -4,6 +4,7 @@ use Andig; use \SimpleXMLElement; +use Symfony\Component\Console\Output\OutputInterface; class Converter { @@ -12,11 +13,15 @@ class Converter /** @var SimpleXMLElement */ private $contact; + /** @var OutputInterface */ + private $output; + private $phoneSort = []; - public function __construct(array $config) + public function __construct(array $config, OutputInterface $output) { $this->config = $config['conversions']; + $this->output = $output; $this->phoneSort = $this->getPhoneTypesSortOrder(); } @@ -33,10 +38,13 @@ public function convert($card): array $adresses = $this->getEmailAdresses($card); // get array of prequalified email adresses $contacts = []; + $realName = htmlspecialchars($this->getProperty($card, 'realName')); if (count($allNumbers) > 9) { - error_log("Contact with >9 phone numbers will be split"); + $comment = sprintf('Split "%s", >9 phone numbers', $realName); + $this->output->writeln('' . $comment . ''); } elseif (count($allNumbers) == 0) { - error_log("Contact without phone numbers will be skipped"); + $comment = sprintf('Skipped "%s", no phone numbers', $realName); + $this->output->writeln('' . $comment . ''); } foreach (array_chunk($allNumbers, 9) as $numbers) { @@ -53,7 +61,7 @@ public function convert($card): array // add Person $person = $this->contact->addChild('person'); - $realName = htmlspecialchars($this->getProperty($card, 'realName')); + //$realName = htmlspecialchars($this->getProperty($card, 'realName')); $person->addChild('realName', $realName); // add photo @@ -292,7 +300,7 @@ private function getProperty($card, string $property): string }, $rule); } - error_log("No data for conversion `$property`"); + $this->output->writeln('No data for conversion `' . $property . '`'); return ''; } } diff --git a/src/FritzBox/Restorer.php b/src/FritzBox/Restorer.php index 83249287..6cccf364 100644 --- a/src/FritzBox/Restorer.php +++ b/src/FritzBox/Restorer.php @@ -5,6 +5,7 @@ use Andig\FritzBox\Converter; use Sabre\VObject\Document; use \SimpleXMLElement; +use Symfony\Component\Console\Output\OutputInterface; /** * Copyright (c) 2019 Volker Püschel @@ -17,9 +18,13 @@ class Restorer private $collums = []; - public function __construct() + /** @var OutputInterface */ + private $output; + + public function __construct(OutputInterface $output) { $this->collums = explode(',', self::CSV_HEADER); + $this->output = $output; } /** @@ -65,7 +70,7 @@ public function getPhonebookData(SimpleXMLElement $xmlPhonebook, array $conversi return []; } - $converter = new Converter($conversions); + $converter = new Converter($conversions, $this->output); $phonebookData = []; $numbers = $xmlPhonebook->xpath('//number[@quickdial or @vanity] | //number[starts-with(text(),"**")]'); foreach ($numbers as $number) { @@ -137,7 +142,7 @@ public function setPhonebookData(SimpleXMLElement $xmlTargetPhoneBook, array $at { $root = $xmlTargetPhoneBook->xpath('//phonebook')[0]; - error_log('Restoring saved attributes (quickdial, vanity) and internal numbers'); + $this->output->writeln('Restoring saved attributes (quickdial, vanity) and internal numbers'); foreach ($attributes as $key => $values) { if (substr($values['number'], 0, 2) == '**') { // internal number $contact = $this->getInternalContact($key, $values); diff --git a/src/RunCommand.php b/src/RunCommand.php index 2d885128..22161d73 100644 --- a/src/RunCommand.php +++ b/src/RunCommand.php @@ -3,12 +3,9 @@ namespace Andig; use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Helper\ProgressBar; class RunCommand extends Command { @@ -32,7 +29,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $ftpDisabled = $this->config['fritzbox']['ftp']['disabled'] ?? false; if ($ftpDisabled) { $input->setOption('image', false); - error_log('Images can only be uploaded if ftp is enabled!'); + $output->writeln('Images can only be uploaded if ftp is enabled!'); } // we want to check for image upload show stoppers as early as possible @@ -42,62 +39,63 @@ protected function execute(InputInterface $input, OutputInterface $output) // download recent phonebook and save special attributes $savedAttributes = []; - error_log("Downloading recent FRITZ!Box phonebook"); - $recentPhonebook = downloadPhonebook($this->config['fritzbox'], $this->config['phonebook']); - if (count($savedAttributes = uploadAttributes($recentPhonebook, $this->config))) { - error_log('Phone numbers with special attributes saved'); + $output->writeln('Downloading recent FRITZ!Box phonebook'); + $recentPhonebook = downloadPhonebook($this->config['fritzbox'], $this->config['phonebook'], $output); + if (count($savedAttributes = uploadAttributes($recentPhonebook, $this->config, $output))) { + $output->writeln('Phone numbers with special attributes saved'); } else { // no attributes are set in the FRITZ!Box or lost -> try to download them - $savedAttributes = downloadAttributes($this->config['fritzbox']); // try to get last saved attributes + $savedAttributes = downloadAttributes($this->config['fritzbox'], $output); // try to get last saved attributes } // download from server or local files $local = $input->getOption('local'); $vcards = $this->downloadAllProviders($output, $input->getOption('image'), $local); - error_log(sprintf("Downloaded %d vCard(s) in total", count($vcards))); + $output->writeln('' . sprintf("Downloaded %d vCard(s) in total", count($vcards)) . ''); // process groups & filters - $vcards = $this->processGroups($vcards); - $vcards = $this->processFilters($vcards); + $vcards = $this->processGroups($vcards, $output); + $vcards = $this->processFilters($vcards, $output); // image upload if ($input->getOption('image')) { - error_log("Detaching and uploading image(s)"); + $output->writeln('Detaching and uploading image(s)'); - $progress = new ProgressBar($output); + $progress = getProgressBar($output); $progress->start(count($vcards)); - $pictures = uploadImages($vcards, $this->config['fritzbox'], $this->config['phonebook'], function () use ($progress) { + $pictures = uploadImages($vcards, $this->config['fritzbox'], $this->config['phonebook'], $output, function () use ($progress) { $progress->advance(); }); $progress->finish(); if ($pictures) { - error_log(sprintf(PHP_EOL . "Uploaded/refreshed %d of %d image file(s)", $pictures[0], $pictures[1])); + $info = sprintf(PHP_EOL . "Uploaded/refreshed %d of %d image file(s)", $pictures[0], $pictures[1]); + $output->writeln('' . $info . ''); } } // fritzbox format - $xmlPhonebook = exportPhonebook($vcards, $this->config); - error_log(sprintf(PHP_EOL."Converted %d vCard(s)", count($vcards))); + $xmlPhonebook = exportPhonebook($vcards, $this->config, $output); + $output->writeln('' . sprintf(PHP_EOL."Converted %d vCard(s)", count($vcards)) . ''); if (!count($vcards)) { - error_log("Phonebook empty - skipping upload"); + $output->writeln('Phonebook empty - skipping upload!'); return 1; } // write back saved attributes - $xmlPhonebook = mergeAttributes($xmlPhonebook, $savedAttributes); + $xmlPhonebook = mergeAttributes($xmlPhonebook, $savedAttributes, $output); // upload - error_log("Uploading new phonebook to FRITZ!Box"); + $output->writeln('Uploading new phonebook to FRITZ!Box'); uploadPhonebook($xmlPhonebook, $this->config); - error_log("Successful uploaded new FRITZ!Box phonebook"); + $output->writeln('Successful uploaded new FRITZ!Box phonebook'); // uploading background image if (count($this->config['fritzbox']['fritzfons']) && $this->config['phonebook']['id'] == 0 && !$ftpDisabled) { - uploadBackgroundImage($savedAttributes, $this->config['fritzbox']); + uploadBackgroundImage($savedAttributes, $this->config['fritzbox'], $output); } return 0; diff --git a/src/UploadCommand.php b/src/UploadCommand.php index 92d6baba..732afb61 100644 --- a/src/UploadCommand.php +++ b/src/UploadCommand.php @@ -3,9 +3,7 @@ namespace Andig; use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -32,13 +30,13 @@ protected function execute(InputInterface $input, OutputInterface $output) $xmlPhonebook = simplexml_load_string($xmlPhonebookStr); if ($this->config['phonebook']['id'] == 0) { // only the first phonebook has special attributes - $savedAttributes = downloadAttributes($this->config['fritzbox']); // try to get last saved attributes - $xmlPhonebook = mergeAttributes($xmlPhonebook, $savedAttributes); + $savedAttributes = downloadAttributes($this->config['fritzbox'], $output); // try to get last saved attributes + $xmlPhonebook = mergeAttributes($xmlPhonebook, $savedAttributes, $output); } - error_log("Uploading FRITZ!Box phonebook"); + $output->writeln('Uploading FRITZ!Box phonebook'); uploadPhonebook($xmlPhonebook, $this->config); - error_log("Successful uploaded new FRITZ!Box phonebook"); + $output->writeln('Successful uploaded new FRITZ!Box phonebook'); return 1; } diff --git a/src/functions.php b/src/functions.php index 56542b91..7c94ae3d 100644 --- a/src/functions.php +++ b/src/functions.php @@ -10,6 +10,7 @@ use Andig\FritzBox\Restorer; use Sabre\VObject\Document; use \SimpleXMLElement; +use Symfony\Component\Console\Output\OutputInterface; // see: https://avm.de/service/fritzbox/fritzbox-7490/wissensdatenbank/publication/show/300_Hintergrund-und-Anruferbilder-in-FRITZ-Fon-einrichten/ define("MAX_IMAGE_COUNT", 150); @@ -20,11 +21,11 @@ * @param array $config * @return Backend */ -function backendProvider(array $config): Backend +function backendProvider(array $config, $output): Backend { $options = $config['server'] ?? $config; - $backend = new Backend($options['url']); + $backend = new Backend($output, $options['url']); $backend->setAuth($options['user'], $options['password']); $backend->mergeClientOptions($options['http'] ?? []); @@ -203,10 +204,11 @@ function getJPEGimage($vcard) * @param Document[] $vcards downloaded vCards * @param array $config * @param array $phonebook + * @param OutputInterface $output * @param callable $callback * @return mixed false or [number of uploaded images, number of total found images] */ -function uploadImages(array $vcards, array $config, array $phonebook, callable $callback=null) +function uploadImages(array $vcards, array $config, array $phonebook, OutputInterface $output, callable $callback=null) { $countUploadedImages = 0; $countAllImages = 0; @@ -247,7 +249,8 @@ function uploadImages(array $vcards, array $config, array $phonebook, callable $ // Occurs when embedding was not possible during download (for example, no access to linked data) if (preg_match("/^http/", $vcard->PHOTO)) { // if the embed failed - error_log(sprintf(PHP_EOL . 'The image for UID %s can not be accessed! ', $uid)); + $comment = sprintf(PHP_EOL . 'The image for UID %s can not be accessed! ', $uid); + $output->writeln('' . $comment . ''); continue; } // Fritz!Box only accept jpg-files @@ -281,7 +284,8 @@ function uploadImages(array $vcards, array $config, array $phonebook, callable $ // upload of new image done, now store new image URL in vCard (new Random Postfix!) $vcard->IMAGEURL = $imgPath . $newFTPimage; } else { - error_log(PHP_EOL."Error uploading $newFTPimage."); + $comment = PHP_EOL . 'Error uploading ' . $newFTPimage . '!'; + $output->writeln('' . $comment . ''); unset($vcard->PHOTO); // no wrong link will set in phonebook unset($vcard->IMAGEURL); // no wrong link will set in phonebook } @@ -290,11 +294,12 @@ function uploadImages(array $vcards, array $config, array $phonebook, callable $ @ftp_close($ftp_conn); if ($countAllImages > MAX_IMAGE_COUNT) { - error_log(sprintf(<<writeln('' . $comment. ''); } return [$countUploadedImages, $countAllImages]; @@ -347,9 +352,10 @@ function dissolveGroups(array $vcards): array * * @param mixed[] $vcards * @param array $filters + * @param OutputInterface $output * @return mixed[] */ -function filter(array $vcards, array $filters): array +function filter(array $vcards, array $filters, OutputInterface $output): array { // include selected $includeFilter = $filters['include'] ?? []; @@ -364,7 +370,7 @@ function filter(array $vcards, array $filters): array } else { // filter defined but empty sub-rules? if (count($includeFilter)) { - error_log('Include filter is empty: including all downloaded vCards'); + $output->writeln('Include filter is empty: including all downloaded vCards'); } // include all by default @@ -431,9 +437,10 @@ function filtersMatch(Document $vcard, array $filters): bool * * @param Document[] $cards * @param array $conversions + * @param OutputInterface $output * @return SimpleXMLElement the XML phone book in Fritz Box format */ -function exportPhonebook(array $cards, array $conversions): SimpleXMLElement +function exportPhonebook(array $cards, array $conversions, OutputInterface $output): SimpleXMLElement { $xmlPhonebook = new SimpleXMLElement( <<xpath('//phonebook')[0]; $root->addAttribute('name', $conversions['phonebook']['name']); - $converter = new Converter($conversions); - $restore = new Restorer; + $converter = new Converter($conversions, $output); + $restore = new Restorer($output); foreach ($cards as $card) { $contacts = $converter->convert($card); @@ -512,9 +519,10 @@ function uploadSuccessful(string $msg): bool * * @param array $fritzbox * @param array $phonebook + * @param OutputInterface $output * @return SimpleXMLElement|bool with the old existing phonebook */ -function downloadPhonebook(array $fritzbox, array $phonebook) +function downloadPhonebook(array $fritzbox, array $phonebook, OutputInterface $output) { $fritz = new Api($fritzbox['url']); $fritz->setAuth($fritzbox['user'], $fritzbox['password']); @@ -528,7 +536,8 @@ function downloadPhonebook(array $fritzbox, array $phonebook) ]; $result = $fritz->postFile($formfields, []); // send the command to load existing phone book if (substr($result, 0, 5) !== "writeln(''. $error .''); return false; } $xmlPhonebook = simplexml_load_string($result); @@ -572,21 +581,22 @@ function getQuickdials(array $attributes, bool $alias = false) * * @param array $attributes * @param array $config + * @param OutputInterface $output * @return void */ -function uploadBackgroundImage($attributes, array $config) +function uploadBackgroundImage($attributes, array $config, OutputInterface $output) { $quickdials = getQuickdials($attributes, $config['quickdial_alias'] ?? false); if (!count($quickdials)) { - error_log('No quickdial numbers are set for a background image upload'); + $output->writeln('No quickdial numbers are set for a background image upload'); return; } if (key($quickdials) > 9) { // usual the pointer should on the first element; with 7.3.*: array_key_first() - error_log('Quickdial numbers out of range for a background image upload'); + $output->writeln('Quickdial numbers out of range for a background image upload!'); return; } - $image = new BackgroundImage(); + $image = new BackgroundImage($output); $image->uploadImage($quickdials, $config); } @@ -595,20 +605,21 @@ function uploadBackgroundImage($attributes, array $config) * * @param SimpleXMLElement $phonebook * @param array $config + * @param OutputInterface $output * @return array */ -function uploadAttributes($phonebook, $config) +function uploadAttributes(SimpleXMLElement $phonebook, array $config, OutputInterface $output) { $fritzbox = $config['fritzbox']; - $restore = new Restorer; + $restore = new Restorer($output); $ftpDisabled = $fritzbox['ftp']['disabled'] ?? false; if ($ftpDisabled || !count($specialAttributes = $restore->getPhonebookData($phonebook, $config))) { - error_log('No special attributes are saved!'); + $output->writeln('No special attributes are saved!'); return []; } - error_log('Save internal data from recent FRITZ!Box phonebook!'); + $output->writeln('Save internal data from recent FRITZ!Box phonebook'); // Prepare FTP connection $secure = $fritzbox['ftp']['plain'] ?? false; $ftp_conn = getFtpConnection($fritzbox['url'], $fritzbox['user'], $fritzbox['password'], '/FRITZ/mediabox', $secure); @@ -626,7 +637,7 @@ function uploadAttributes($phonebook, $config) fputs($memstream, $rows); rewind($memstream); if (!ftp_fput($ftp_conn, 'Attributes.csv', $memstream, FTP_BINARY)) { - error_log('Error uploading Attributes.csv!' . PHP_EOL); + $output->writeln('Error uploading Attributes.csv!'); } fclose($memstream); @ftp_close($ftp_conn); @@ -638,13 +649,14 @@ function uploadAttributes($phonebook, $config) * get saved special attributes from internal FRITZ!Box memory (../FRITZ/mediabox) * * @param array $config + * @param OutputInterface $output * @return array */ -function downloadAttributes($config) +function downloadAttributes(array $config, OutputInterface $output) { $ftpDisabled = $config['ftp']['disabled'] ?? false; if ($ftpDisabled) { - error_log('Ftp is not available or disabled. Special attributes cannot be loaded!'); + $output->writeln('Ftp is not available or disabled. Special attributes cannot be loaded!'); return []; } @@ -655,7 +667,7 @@ function downloadAttributes($config) return []; } - $restore = new Restorer; + $restore = new Restorer($output); $specialAttributes = []; $csvFile = fopen('php://temp', 'r+'); if (ftp_fget($ftp_conn, $csvFile, 'Attributes.csv', FTP_BINARY)) { @@ -676,14 +688,15 @@ function downloadAttributes($config) * * @param SimpleXMLElement $xmlTargetPhoneBook * @param array $attributes array of special attributes + * @param OutputInterface $output * @return SimpleXMLElement phonebook with restored special attributes */ -function mergeAttributes(SimpleXMLElement $xmlTargetPhoneBook, array $attributes) +function mergeAttributes(SimpleXMLElement $xmlTargetPhoneBook, array $attributes, OutputInterface $output) { if (!$attributes) { return $xmlTargetPhoneBook; } - $restore = new Restorer; + $restore = new Restorer($output); $xmlTargetPhoneBook = $restore->setPhonebookData($xmlTargetPhoneBook, $attributes); return $xmlTargetPhoneBook; diff --git a/tests/ConverterTest.php b/tests/ConverterTest.php index dc5f5604..8e329a5d 100644 --- a/tests/ConverterTest.php +++ b/tests/ConverterTest.php @@ -2,6 +2,7 @@ use \Andig\FritzBox\Converter; use \PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Output\OutputInterface; use Sabre\VObject; class ConverterTest extends TestCase @@ -12,12 +13,21 @@ class ConverterTest extends TestCase /** @var \stdClass */ public $contact; + /** @var OutputInterface */ + public $output; + public function setUp() { - $this->converter = new Converter($this->defaultConfig()); + $this->output = $this->getOutputInterface(); + $this->converter = new Converter($this->defaultConfig(), $this->output); $this->contact = $this->defaultContact(); } + private function getOutputInterface(): OutputInterface + { + return new OutputInterface; + } + private function defaultConfig(): array { return [ @@ -111,7 +121,7 @@ public function contactPropertiesProvider(): array /** * @dataProvider contactPropertiesProvider */ - public function testPropertyReplacement(array $properties, string $realName) + public function testPropertyReplacement(array $properties, string $realName, $output) { foreach ($properties as $key => $value) { $sabreKey = strtoupper($key); @@ -126,7 +136,7 @@ public function testPropertyReplacement(array $properties, string $realName) '{fullname}' ]; - $res = (new Converter($config))->convert($this->contact); + $res = (new Converter($config, $output))->convert($this->contact); $this->assertCount(1, $res); $contact = $res[0]; diff --git a/tests/FunctionsTest.php b/tests/FunctionsTest.php index b9daaf80..1d4296b3 100644 --- a/tests/FunctionsTest.php +++ b/tests/FunctionsTest.php @@ -1,19 +1,29 @@ contacts = $this->defaultContacts(); + $this->output = $this->getOutputInterface(); + } + + private function getOutputInterface(): OutputInterface + { + return new OutputInterface; } - private function defaultContacts() + private function defaultContacts(): array { // definition of the test-takers $contacts = [ @@ -130,7 +140,7 @@ public function filtersPropertiesProvider(): array */ public function testFilter(array $filter, int $residually) { - $res = Andig\filter($this->contacts, $filter); + $res = Andig\filter($this->contacts, $filter, $this->output); $this->assertCount($residually, $res); } } diff --git a/tests/RestorerTest.php b/tests/RestorerTest.php index 448f503c..5acf9808 100644 --- a/tests/RestorerTest.php +++ b/tests/RestorerTest.php @@ -2,6 +2,7 @@ use \Andig\FritzBox\Restorer; use \PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Output\OutputInterface; class RestorerTest extends TestCase { @@ -10,7 +11,7 @@ class RestorerTest extends TestCase public function setUp() { - $this->restore = new Restorer; + $this->restore = new Restorer(new OutputInterface); } private function defaultConfig(): array