Semi Working. Need to add tests

This commit is contained in:
R. Eric Wheeler 2017-09-01 21:06:45 -07:00
parent 4c39ba7699
commit d48096b96a
16 changed files with 1030 additions and 25 deletions

View File

@ -1 +0,0 @@
NOTI_PB=<pushbullet token>

9
.gitignore vendored
View File

@ -2,4 +2,11 @@
vendor/
*~
composer.lock
.env
/config/config.yaml
/.php_cs.cache
!/cache/.gitkeep
/cache/
!/log/.gitkeep
/log/
!/bin/pushbullet
/bin/

65
.php_cs Normal file
View File

@ -0,0 +1,65 @@
<?php
$header = <<<EOF
Pushbullet Notifier [sikofitt/pushbullet-notifier]
Copyright (C) 2017 http://blog.rewiv.com R. Eric Wheeler <sikofitt@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
EOF;
return PhpCsFixer\Config::create()
->setRiskyAllowed(true)
->setRules(
[
'@Symfony' => false,
'@PSR2' => true,
'header_comment' => ['header' => $header],
'ordered_class_elements' => true,
'ordered_imports' => true,
'no_mixed_echo_print' => ['use' => 'print'],
'strict_param' => true,
'strict_comparison' => true,
'single_import_per_statement' => false,
'phpdoc_order' => true,
'array_syntax' => ['syntax' => 'short'],
'phpdoc_add_missing_param_annotation' => true,
'psr4' => true,
'phpdoc_var_without_name' => false,
'@PHP70Migration' => true,
'@PHP70Migration:risky' => true,
'@PHP71Migration' => true,
'@PHP71Migration:risky' => true,
'no_extra_consecutive_blank_lines' => [
'break',
'continue',
'extra',
'return',
'throw',
'parenthesis_brace_block',
'square_brace_block',
'curly_brace_block'
],
]
)->setFinder(
PhpCsFixer\Finder::create()
->ignoreDotFiles(true)
->ignoreVCS(true)
->name('*.php')
->in([
'src',
'bin',
'tests',
])
);

20
app.php
View File

@ -1,20 +0,0 @@
<?php
require 'vendor/autoload.php';
$loader = new josegonzalez\Dotenv\Loader(__DIR__.'/.env');
$loader->parse();
$loader->putEnv();
$token = getenv('PB_TOKEN');
try {
$pushbullet = new Pushbullet\Pushbullet($token);
} catch (\Exception $e) {
print $e->getMessage() . PHP_EOL;
}
$pushResult = $pushbullet
->device('Google Pixel XL')
->pushNote('Hello!', 'How are you?')
;
print_r($pushResult);

View File

@ -0,0 +1,34 @@
#!/usr/bin/env php
<?php
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Debug\Debug;
use Sikofitt\Pushbullet\Console\Application;
use Symfony\Component\Console\Output\ConsoleOutput;
set_time_limit(0);
/**
* @var Composer\Autoload\ClassLoader $loader
*/
$loader = require __DIR__ . '/../vendor/autoload.php';
$input = new ArgvInput();
$output = new ConsoleOutput();
$env = $input->getParameterOption(['--env', '-e'],
getenv('PHP_ENV') ?: 'dev');
$debug = getenv('PHP_DEBUG') !== '0' && !$input->hasParameterOption([
'--no-debug',
'',
]) && $env !== 'prod';
if ($debug) {
Debug::enable();
}
$application = new Application();
$application->add(new \Symfony\Component\Console\Command\HelpCommand());
$application->add(new \Symfony\Component\Console\Command\ListCommand());
$application->run($input, $output);

0
cache/.gitkeep vendored Normal file
View File

View File

@ -9,10 +9,47 @@
},
"require": {
"php": ">=7.1",
"hassankhan/config": "^0.9",
"incenteev/composer-parameter-handler": "2.1.*",
"ivkos/pushbullet": "^3.1",
"symfony/console": "^3.2",
"symfony/event-dispatcher": "^3.2",
"monolog/monolog": "^1.23",
"symfony/config": "^3.2",
"josegonzalez/dotenv": "^3.1"
"symfony/console": "^3.2",
"symfony/dependency-injection": "^3.3",
"symfony/event-dispatcher": "^3.2",
"symfony/yaml": "^3.3",
"tedivm/stash": "^0.14.2"
},
"autoload-dev": {
"psr-4": {
"Sikofitt\\Tests\\Pushbullet\\": "tests/"
}
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.5",
"phpunit/phpunit": "~5",
"symfony/var-dumper": "^3.3"
},
"extra": {
"incenteev-parameters": {
"file": "config/config.yaml",
"parameter-key": "pushbullet"
}
},
"config": {
"sort-packages": true,
"platform": {
"php": "7.1"
},
"bin-dir": "bin",
"optimize-autoloader": true
},
"scripts": {
"default": [
"Incenteev\\ParameterHandler\\ScriptHandler::buildParameters"
],
"post-install-cmd": ["@default"],
"post-update-cmd": ["@default"]
}
}

5
config/config.yaml.dist Normal file
View File

@ -0,0 +1,5 @@
pushbullet:
token: pushbullet_token # https://www.pushbullet.com/#settings/account
push_devices: # devices to push to, bin/pushbullet devices
- chrome
- phone

0
log/.gitkeep Normal file
View File

View File

@ -0,0 +1,141 @@
<?php declare(strict_types=1);
/*
* Pushbullet Notifier [sikofitt/pushbullet-notifier]
* Copyright (C) 2017 http://blog.rewiv.com R. Eric Wheeler <sikofitt@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Sikofitt\Pushbullet\Console;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\SyslogHandler;
use Monolog\Logger;
use Psr\Container\ContainerInterface;
use Sikofitt\Pushbullet\Console\Command\PushbulletDevicesCommand;
use Sikofitt\Pushbullet\Console\Command\PushbulletNotifierCommand;
use Sikofitt\Pushbullet\DependencyInjection\Container;
use Sikofitt\Pushbullet\DependencyInjection\PushBulletExtension;
use Symfony\Component\Console\Application as SymfonyApplication;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
class Application extends SymfonyApplication
{
protected const APP_VERSION = '0.0.1';
protected const APP_NAME = 'Pushbullet Notifier';
/**
* @var \Symfony\Component\DependencyInjection\ContainerInterface
*/
private $container;
/**
* @param array $parameters Parameters to set at runtime.
*
* @throws \LogicException
*/
public function __construct(array $parameters = [])
{
$this->buildContainer($parameters);
$this->add(new PushbulletNotifierCommand($this->container));
$this->add(new PushbulletDevicesCommand($this->container));
parent::__construct(self::APP_NAME, self::APP_VERSION);
}
/**
* @throws \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @return null|string
*/
public function getRootDir(): ?string
{
try {
return $this->container->getParameter('app.root');
} catch (InvalidArgumentException $i) {
return null;
}
}
/**
* @param string $rootDir
*/
public function setRootDir(string $rootDir): void
{
$this->container->setParameter('app.root', $rootDir);
}
/**
* Runs the current application.
*
* @param InputInterface $input An Input instance
* @param OutputInterface $output An Output instance
*
* @throws \Exception When running fails. Bypass this when {@link setCatchExceptions()}.
* @return int 0 if everything went fine, or an error code
*
*/
public function run(
InputInterface $input = null,
OutputInterface $output = null
): int {
return parent::run(
$input,
$output
); // TODO: Change the autogenerated stub
}
/**
* @return \Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface
*/
public function getParameterBag(): ParameterBagInterface
{
return $this->container->getParameterBag();
}
/**
* @param \Psr\Container\ContainerInterface $container
*
* @return $this
*/
public function setContainer(ContainerInterface $container): Application
{
$this->container = $container;
return $this;
}
private function buildContainer(array $parameters): void
{
$extension = new PushBulletExtension();
$parameterBag = new ParameterBag($parameters);
$this->container = new Container($parameterBag);
$this->container->registerExtension($extension);
$this->container->loadFromExtension($extension->getAlias());
$this->container->setParameter('app.root', dirname(__DIR__, 4));
$logFile = sprintf('%s/log/pushbullet.log', $this->container->getParameter('app.root'));
$handlers[] = new StreamHandler($logFile);
$handlers[] = new SyslogHandler('pushbullet');
$logger = new Logger('pushbullet', $handlers);
$this->container->set('logger', $logger);
$this->container->compile();
}
}

View File

@ -0,0 +1,351 @@
<?php declare(strict_types=1);
/*
* Pushbullet Notifier [sikofitt/pushbullet-notifier]
* Copyright (C) 2017 http://blog.rewiv.com R. Eric Wheeler <sikofitt@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Sikofitt\Pushbullet\Console\Command;
use Pushbullet\Exceptions\NotFoundException;
use Pushbullet\Pushbullet;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Helper\TableCell;
use Symfony\Component\Console\Helper\TableSeparator;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Command to list available targets from a Pushbullet account.
*/
class PushbulletDevicesCommand extends Command
{
/** @var array */
private $table;
/** @var SymfonyStyle */
private $io;
/** @var \Pushbullet\Pushbullet */
private $pushbullet;
/** @var string */
private $type;
/** @var ContainerInterface */
private $container;
/**
* PushbulletDevicesCommand constructor.
*
* @param ContainerInterface $container
*
* @throws RuntimeException
* @throws LogicException
* @throws InvalidArgumentException
* @throws \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
*/
public function __construct(ContainerInterface $container)
{
$this->table = [];
$this->container = $container;
$token = $container->getParameter('pushbullet.token');
try {
$this->pushbullet = new Pushbullet($token);
} catch (\Exception $e) {
throw new RuntimeException($e->getMessage(), $e->getCode(), $e);
}
parent::__construct('targets');
}
/**
* Configures the current command.
*
* @throws \Symfony\Component\Console\Exception\InvalidArgumentException
*/
public function configure(): void
{
$this->setName('targets')
->setDescription('Gets a list of available pushbullet targets.')
->setHelp($this->getHelpText())
->addArgument(
'target',
InputArgument::OPTIONAL,
"Which types you want to display.\n[all, devices, contacts, channels]",
'all'
);
}
/**
* Interacts with the user.
*
* This method is executed before the InputDefinition is validated.
* This means that this is the only place where the command can
* interactively ask for values of missing required arguments.
*
* @param InputInterface $input An InputInterface instance
* @param OutputInterface $output An OutputInterface instance
*
* @throws \Symfony\Component\Console\Exception\InvalidArgumentException
*/
public function interact(InputInterface $input, OutputInterface $output): void
{
$this->io = new SymfonyStyle($input, $output);
$this->type = strtolower($input->getArgument('target'));
$availableTypes = ['all', 'devices', 'channels', 'contacts'];
if (false === array_key_exists($this->type, array_flip($availableTypes))) {
throw new InvalidArgumentException('display must be one of [' . implode(', ', $availableTypes) . ']');
}
}
/**
* Executes the current command.
*
* This method is not abstract because you can use this class
* as a concrete class. In this case, instead of defining the
* execute() method, you set the code to execute by passing
* a Closure to the setCode() method.
*
* @param InputInterface $input An InputInterface instance
* @param OutputInterface $output An OutputInterface instance
*
* @throws \Symfony\Component\Console\Exception\InvalidArgumentException
* @throws \Symfony\Component\Console\Exception\RuntimeException
* @throws LogicException When this abstract method is not implemented
* @throws \Pushbullet\Exceptions\NotFoundException
* @throws \Pushbullet\Exceptions\InvalidTokenException
* @throws \Pushbullet\Exceptions\ConnectionException
*
* @return null|int null or 0 if everything went fine, or an error code
*
* @see setCode()
*/
public function execute(InputInterface $input, OutputInterface $output): ?int
{
$this->io->note('You can push by iden or Nick name');
$heading = ['Nick name', 'Make', 'Model', 'iden'];
switch ($this->type) {
case 'devices':
$this->io->text(' <fg=white;options=bold>Devices</>');
$this->addDevicesSection();
break;
case 'channels':
$heading = ['Name', 'Description', 'iden'];
$this->io->text(' <fg=white;options=bold>Channels</>');
$this->addChannelsSection();
break;
case 'contacts':
$heading = ['Name', 'Email', 'iden'];
$this->io->text(' <fg=white;options=bold>Contacts</>');
$this->addContactsSection();
break;
default:
// devices
$this->addDevicesHeading();
$this->addDevicesSection();
// channels
$this->addChannelsHeading();
$this->addChannelsSection();
// contacts
$this->addContactsHeading();
$this->addContactsSection();
break;
}
if (true !== empty($this->table)) {
$logger = $this->container->get('logger');
$logger->debug('Creating table');
$this->io->table($heading, $this->table);
return 0;
}
$this->io->error('There were no devices found.');
return 255;
}
/**
* @return string
* Help text for this command.
*/
private function getHelpText(): string
{
return 'This command displays your available devices, contacts, and channels.' . PHP_EOL .
'By default this will display all of your targets.' . PHP_EOL .
'You can list specific ones by using the argument target.' . PHP_EOL .
'[{path}/bin/pushbullet targets contacts], for example will only display your contact targets.' . PHP_EOL;
}
/**
* Sets the devices listing header.
*/
private function addDevicesHeading(): void
{
$this->io->text(' <fg=white;options=bold>Devices</>');
}
/**
* Sets the channels listing header.
*/
private function addChannelsHeading(): void
{
$tableSeparator = new TableSeparator();
$tableCell = new TableCell();
$this->table[] = $tableSeparator;
$this->table[] = [
new TableCell('<fg=white;options=bold>Channels</>'),
$tableCell,
$tableCell,
$tableCell
];
$this->table[] = new TableSeparator();
$this->table[] = [
new TableCell('<fg=green>Name</>'),
new TableCell('<fg=green>Description</>'),
new TableCell(),
new TableCell('<fg=green>Iden</>')
];
$this->table[] = new TableSeparator();
}
/**
* Sets the contacts listing header.
*/
private function addContactsHeading(): void
{
$this->table[] = new TableSeparator();
$this->table[] = [
new TableCell('<fg=white;options=bold>Contacts</>'),
new TableCell(),
new TableCell(),
new TableCell()
];
$this->table[] = new TableSeparator();
$this->table[] = [
new TableCell('<fg=green>Name</>'),
new TableCell('<fg=green>Email</>'),
new TableCell(),
new TableCell('<fg=green>Iden</>')
];
$this->table[] = new TableSeparator();
}
/**
* Adds the devices section of the table.
*
* @throws \Pushbullet\Exceptions\ConnectionException
* @throws \Pushbullet\Exceptions\InvalidTokenException
*/
private function addDevicesSection(): void
{
try {
$pushbulletDevices = $this->pushbullet->getDevices();
} catch (\Exception $e) {
$this->io->error($e->getMessage());
return;
}
foreach ($pushbulletDevices as $device) {
$this->table[] = [
$device->nickname,
$device->manufacturer,
$device->model,
$device->iden
];
}
}
/**
* Adds the contacts section of the table.
*
* @throws \Pushbullet\Exceptions\ConnectionException
* @throws \Pushbullet\Exceptions\InvalidTokenException
*/
private function addContactsSection(): void
{
try {
$contacts = $this->pushbullet->getContacts();
} catch (\Exception $e) {
$this->io->error($e->getMessage());
return;
}
foreach ($contacts as $contact) {
if ('all' === $this->type) {
$this->table[] = [
$contact->name,
$contact->email,
new TableCell(),
$contact->iden
];
} else {
$this->table[] = [
$contact->name,
$contact->email,
$contact->iden,
];
}
}
}
/**
* Adds the channels section of the table.
*
* @throws \Pushbullet\Exceptions\ConnectionException
* @throws \Pushbullet\Exceptions\InvalidTokenException
* @throws \Pushbullet\Exceptions\NotFoundException
*/
private function addChannelsSection(): void
{
try {
$channels = $this->pushbullet->getMyChannels();
} catch (NotFoundException $n) {
$this->io->error('Could not find any channels.');
return;
} catch (\Exception $e) {
return;
}
foreach ($channels as $channel) {
if ('all' === $this->type) {
$this->table[] = [
$channel->name,
$channel->description,
new TableCell(),
$channel->iden
];
} else {
$this->table[] = [
$channel->name,
$channel->description,
$channel->iden
];
}
}
}
}

View File

@ -0,0 +1,195 @@
<?php declare(strict_types=1);
/*
* Pushbullet Notifier [sikofitt/pushbullet-notifier]
* Copyright (C) 2017 http://blog.rewiv.com R. Eric Wheeler <sikofitt@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Sikofitt\Pushbullet\Console\Command;
use Pushbullet\Push;
use Pushbullet\Pushbullet;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Command to send notifications through Pushbullet.
*/
class PushbulletNotifierCommand extends Command
{
/** @var \Pushbullet\Pushbullet */
private $pushbullet;
/** @var string */
private $typeFunction;
/**
* Constructor.
*
* @param $container ContainerInterface
*
* @throws LogicException When the command name is empty
* @throws \Pushbullet\Exceptions\PushbulletException
* @throws \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
*/
public function __construct(ContainerInterface $container)
{
$token = $container->getParameter('pushbullet.token');
$this->pushbullet = new Pushbullet($token);
parent::__construct();
}
/**
* Configures the current command.
*
* @throws \Symfony\Component\Console\Exception\InvalidArgumentException
*/
public function configure(): void
{
$this->setName('notify')
->setDescription('Notifies using Pushbullet.')
->addArgument(
'name',
InputArgument::IS_ARRAY,
'The name or ident of the device to push to.'
)
->addOption(
'device',
'd',
InputOption::VALUE_NONE,
'Push to a device'
)
->addOption(
'channel',
'c',
InputOption::VALUE_NONE,
'Push to a channel'
)
->addOption(
'contact',
't',
InputOption::VALUE_NONE,
'Push to a contact'
)
->addOption(
'title',
null,
InputOption::VALUE_OPTIONAL,
'The Title of your note.',
'Note from ' . getenv('USER')
)
->addOption(
'message',
'm',
InputOption::VALUE_REQUIRED,
'Your message. You should quote this value.'
)
;
}
/**
* Interacts with the user.
*
* This method is executed before the InputDefinition is validated.
* This means that this is the only place where the command can
* interactively ask for values of missing required arguments.
*
* @param InputInterface $input An InputInterface instance
* @param OutputInterface $output An OutputInterface instance
*
* @throws \Symfony\Component\Console\Exception\InvalidArgumentException
*/
public function interact(InputInterface $input, OutputInterface $output): void
{
if (null === $input->getOption('message')) {
throw new InvalidArgumentException('Message MUST be set.');
}
if (null === $input->getArgument('name') || true === empty($input->getArgument('name'))) {
throw new InvalidArgumentException('Name must be set');
}
$device = $input->getOption('device');
$channel = $input->getOption('channel');
$contact = $input->getOption('contact');
if (
($device && $channel && $contact) ||
($device && $channel) ||
($device && $contact) ||
($channel && $contact)
) {
throw new InvalidArgumentException('Can only set one target type.');
}
if ($device) {
$this->typeFunction = 'device';
} elseif ($channel) {
$this->typeFunction = 'channel';
} elseif ($contact) {
$this->typeFunction = 'contact';
} else {
throw new InvalidArgumentException('Need to set at least one type');
}
}
/**
* Executes the current command.
*
* This method is not abstract because you can use this class
* as a concrete class. In this case, instead of defining the
* execute() method, you set the code to execute by passing
* a Closure to the setCode() method.
*
* @param InputInterface $input An InputInterface instance
* @param OutputInterface $output An OutputInterface instance
*
* @throws LogicException When this abstract method is not implemented
* @throws \Pushbullet\Exceptions\NotPushableException
* @throws \Pushbullet\Exceptions\ConnectionException
* @throws \Symfony\Component\Console\Exception\InvalidArgumentException
* @return null|int null or 0 if everything went fine, or an error code
*
* @see setCode()
*/
public function execute(InputInterface $input, OutputInterface $output): ?int
{
$io = new SymfonyStyle($input, $output);
$iden = $input->getArgument('name');
$iden = implode(' ', $iden);
/** @var \Pushbullet\Device|\Pushbullet\Contact|\Pushbullet\Channel $type */
$type = $this->pushbullet->{$this->typeFunction}($iden);
$title = $input->getOption('title');
$message = $input->getOption('message');
$result = $type->pushNote($title, $message);
if ($result instanceof Push) {
$io->success('Your note has been pushed!');
return 0;
}
return 255;
}
}

View File

@ -0,0 +1,58 @@
<?php declare(strict_types=1);
/*
* Pushbullet Notifier [sikofitt/pushbullet-notifier]
* Copyright (C) 2017 http://blog.rewiv.com R. Eric Wheeler <sikofitt@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Sikofitt\Pushbullet\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
class Configuration implements ConfigurationInterface
{
/**
* Generates the configuration tree builder.
*
* @throws \RuntimeException
* @return \Symfony\Component\Config\Definition\Builder\TreeBuilder The
* tree builder
*/
public function getConfigTreeBuilder(): ?TreeBuilder
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('pushbullet');
$rootNode
->children()
->scalarNode('token')
->isRequired()
->cannotBeEmpty()
->end()
->arrayNode('push_devices')
->cannotBeEmpty()
->requiresAtLeastOneElement()
->beforeNormalization()
->castToArray()
->end()
->scalarPrototype()
->end()
->end()
->end();
return $treeBuilder;
}
}

View File

@ -0,0 +1,44 @@
<?php declare(strict_types=1);
/*
* Pushbullet Notifier [sikofitt/pushbullet-notifier]
* Copyright (C) 2017 http://blog.rewiv.com R. Eric Wheeler <sikofitt@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Sikofitt\Pushbullet\DependencyInjection;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use Psr\Container\ContainerInterface;
use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
/**
* ContainerBuilder is a DI container that provides an API to easily describe services.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Container extends ContainerBuilder implements ContainerInterface
{
/**
* @param ParameterBagInterface $parameterBag A ParameterBagInterface instance
*/
public function __construct(ParameterBagInterface $parameterBag = null)
{
parent::__construct($parameterBag);
}
}

View File

@ -0,0 +1,89 @@
<?php declare(strict_types=1);
/*
* Pushbullet Notifier [sikofitt/pushbullet-notifier]
* Copyright (C) 2017 http://blog.rewiv.com R. Eric Wheeler <sikofitt@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Sikofitt\Pushbullet\DependencyInjection;
use \Symfony\Component\Yaml\Yaml;
use Symfony\Component\Config\Definition\Processor;
use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;
use Symfony\Component\Yaml\Exception\ParseException;
class PushBulletExtension extends Extension
{
/**
* Loads a specific configuration.
*
* @param array $configs An array of configuration values
* @param ContainerBuilder $container A ContainerBuilder instance
*
* @throws \InvalidArgumentException When provided tag is not defined in
* this extension
*/
public function load(array $configs, ContainerBuilder $container): void
{
$locator = new FileLocator([$container->getParameter('app.root').'/config']);
try {
$config = $locator->locate('config.yaml');
} catch (FileLocatorFileNotFoundException $f) {
print $f->getMessage();
exit;
}
try {
$configs = Yaml::parse(file_get_contents($config));
} catch (ParseException $p) {
print sprintf('%sUnable to parse %s at line %d (stopped at "%s") in %s%s', PHP_EOL, $config, $p->getParsedLine(), $p->getSnippet(), PHP_EOL, PHP_EOL);
exit;
} catch (\Exception $e) {
print PHP_EOL . $e->getMessage() . PHP_EOL . PHP_EOL;
exit;
}
$configuration = new Configuration();
$processor = new Processor();
$config = $processor->processConfiguration($configuration, $configs);
$object = new \stdClass();
$object->class = new \ArrayObject();
$object->arguments = [
['array']
];
$container->set('pushbullet.app', $object);
$container->setParameter('pushbullet.token', $config['token']);
$container->setParameter('pushbullet.push_devices', $config['push_devices']);
}
/**
* Returns the recommended alias to use in XML.
*
* This alias is also the mandatory prefix to use when using YAML.
*
* @return string The alias
*/
public function getAlias()
{
return 'pushbullet';
}
}

0
tests/.gitkeep Normal file
View File