Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
67e34e52b8 | ||
|
dc96556b5a | ||
|
31822ab7e7 | ||
|
50e9a4c621 | ||
|
0710ef474f | ||
|
50748f2fb5 | ||
|
0755b84fdd | ||
|
39feb2edb9 | ||
|
a09bc5aff1 | ||
|
d3dd08081b | ||
|
427f830e42 | ||
|
f23375ffce | ||
|
6a11a9dcce |
13
README.md
13
README.md
@ -9,10 +9,17 @@ composer require aerex/baikal-storage-plugin
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
Create the `config.yaml` to your webserver. Make sure the file is *writable* by your webserver (e.g Apache, Nginx). For more details on the configuration details see the wiki page.
|
You can use the CLI to help you generate a config file or use the example configuration provided in the project. Make sure the file is *writable* by your webserver (e.g Apache, Nginx).
|
||||||
|
|
||||||
|
### Use the CLI
|
||||||
|
Run the command `./vendor/bin/baikalstorage` and follow the instructions
|
||||||
|
|
||||||
|
### Manual
|
||||||
|
Copy the `example-config.yaml` file and rename it to `config.yaml`.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
- Add the plugin to `Core/Frameworks/Baikal/Core/Server.php`
|
- Add the plugin to the end of the `Server.php` file located under `Core/Frameworks/Baikal/Core/Server.php`. For example
|
||||||
|
|
||||||
```
|
```
|
||||||
$this->server->addPlugin(new \Aerex\BaikalStorage\Plugin(<absolute/path/of/config/file>))
|
$this->server->addPlugin(new \Aerex\BaikalStorage\Plugin(<absolute/path/of/config.yaml)
|
||||||
```
|
```
|
||||||
|
@ -12,22 +12,22 @@
|
|||||||
"repositories": [
|
"repositories": [
|
||||||
{
|
{
|
||||||
"type": "vcs",
|
"type": "vcs",
|
||||||
"url": "https://git.aerex.me/Aerex/baikal-storage-plugin"
|
"url": "https://github.com/Aerex/baikal-storage-plugin"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"bin": [
|
"bin": [
|
||||||
"bin/console"
|
"bin/baikalstorage"
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.5",
|
"php" : "^7.2 || ^8.0",
|
||||||
"sabre/dav" : "~4.1.0",
|
"sabre/dav" : "~4.3.0",
|
||||||
"sabre/vobject": "^4.0",
|
"sabre/vobject": "^4.2.1",
|
||||||
"nesbot/carbon": "^2.0.0",
|
"nesbot/carbon": "^2.0.0",
|
||||||
"laminas/laminas-validator": "^2.13",
|
"laminas/laminas-validator": "^2.13",
|
||||||
"laminas/laminas-stdlib": "^3.2",
|
"laminas/laminas-stdlib": "^3.2",
|
||||||
"psr/container": "^1.0",
|
"psr/container": "^1.0",
|
||||||
"symfony/config": "3.4",
|
"symfony/config": "3.4|^4.0|^5.0",
|
||||||
"symfony/process": "^3.4",
|
"symfony/process": "^3.4|^4.0|^5.0",
|
||||||
"monolog/monolog": "^2.0",
|
"monolog/monolog": "^2.0",
|
||||||
"symfony/yaml": "~3.0|~4.0",
|
"symfony/yaml": "~3.0|~4.0",
|
||||||
"symfony/console": "^3.4|^4.0|^5.0"
|
"symfony/console": "^3.4|^4.0|^5.0"
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
|
||||||
namespace Aerex\BaikalStorage\Commands;
|
namespace Aerex\BaikalStorage\Commands;
|
||||||
|
|
||||||
use Symfony\Component\Console\Command\Command;
|
use Symfony\Component\Console\Command\Command;
|
||||||
@ -12,8 +11,6 @@ use Symfony\Component\Console\Question\ChoiceQuestion;
|
|||||||
use Monolog\Logger as Monolog;
|
use Monolog\Logger as Monolog;
|
||||||
use Aerex\BaikalStorage\Configs\ConfigBuilder;
|
use Aerex\BaikalStorage\Configs\ConfigBuilder;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class CreateConfigFileCommand extends Command {
|
class CreateConfigFileCommand extends Command {
|
||||||
protected $io;
|
protected $io;
|
||||||
|
|
||||||
@ -25,7 +22,12 @@ class CreateConfigFileCommand extends Command {
|
|||||||
|
|
||||||
public function addtaskwarriorConfig() {
|
public function addtaskwarriorConfig() {
|
||||||
$configs = [];
|
$configs = [];
|
||||||
$filePath = $this->io->askQuestion(new Question('Where is the location for the taskrc file?'));
|
$taskrcQuestion = new Question('Where is the location for the taskrc file?');
|
||||||
|
$self = $this;
|
||||||
|
$taskrcQuestion->setAutocompleterCallback(function(string $input) use ($self) {
|
||||||
|
return $self->autocompleteFilePathCallback($input);
|
||||||
|
});
|
||||||
|
$filePath = $this->io->askQuestion($taskrcQuestion);
|
||||||
$taskrcFilePath = $filePath . '/.taskrc';
|
$taskrcFilePath = $filePath . '/.taskrc';
|
||||||
if (!file_exists($taskrcFilePath)) {
|
if (!file_exists($taskrcFilePath)) {
|
||||||
throw new \RuntimeException("The taskrc file at $taskrcFilePath does not exist");
|
throw new \RuntimeException("The taskrc file at $taskrcFilePath does not exist");
|
||||||
@ -48,22 +50,49 @@ class CreateConfigFileCommand extends Command {
|
|||||||
->setDescription('Create baikal storage plugin configuration file');
|
->setDescription('Create baikal storage plugin configuration file');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function autocompleteFilePathCallback(string $input): array {
|
||||||
|
// Strip any characters from the last slash to the end of the string
|
||||||
|
// to keep only the last directory and generate suggestions for it
|
||||||
|
$inputPath = preg_replace('%(/|^)[^/]*$%', '$1', $input);
|
||||||
|
$inputPath = '' === $inputPath ? '.': $inputPath;
|
||||||
|
|
||||||
|
$foundFilesAndDirs = scandir($inputPath) ?: [];
|
||||||
|
|
||||||
|
// Excluded restricted directories
|
||||||
|
$restrictedDirs = ['dev', 'bin', 'boot', 'etc', 'input', 'lib',
|
||||||
|
'lib64', 'mnt', 'proc', 'run', 'sbin', 'sys', 'srv', 'usr', 'var'];
|
||||||
|
$foundSafeFileAndDirs = array_diff($foundFilesAndDirs, $restrictedDirs);
|
||||||
|
|
||||||
|
return array_map(function($dirOrFile) use ($inputPath) {
|
||||||
|
return $inputPath.$dirOrFile;
|
||||||
|
}, $foundSafeFileAndDirs);
|
||||||
|
}
|
||||||
|
|
||||||
protected function execute(InputInterface $input, OutputInterface $output) {
|
protected function execute(InputInterface $input, OutputInterface $output) {
|
||||||
$this->io = new SymfonyStyle($input, $output);
|
$this->io = new SymfonyStyle($input, $output);
|
||||||
|
|
||||||
$this->io->title('Baikal Storage Plugin Configuration Creation');
|
$this->io->title('Baikal Storage Plugin Configuration Creation');
|
||||||
|
|
||||||
$filePath = $this->io->askQuestion(new Question('Where to create `config.yaml` configuration file?'));
|
// TODO: move create config file code block to function
|
||||||
$this->fullFilePath = $this->verifyFileCanBeCreated($filePath, CreateConfigFileCommand::$CONFIG_FILE_NAME);
|
$question = new Question('Where to create `config.yaml` configuration file?');
|
||||||
|
$self = $this;
|
||||||
|
$question->setAutocompleterCallback(function(string $input) use ($self) {
|
||||||
|
return $self->autocompleteFilePathCallback($input);
|
||||||
|
});
|
||||||
|
$filePath = $this->io->askQuestion($question);
|
||||||
|
|
||||||
$this
|
try {
|
||||||
->setupGeneralConfigs()
|
$this->fullFilePath = $this->verifyAndCreateFile($filePath, CreateConfigFileCommand::$CONFIG_FILE_NAME);
|
||||||
->setupStorages()
|
$this->setupGeneralConfigs()
|
||||||
->saveConfigs();
|
->setupStorages()
|
||||||
|
->saveConfigs();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
// or return this if some error happened during the execution
|
$this->output->writeln("`config.yaml file created at $filePath");
|
||||||
// (it's equivalent to returning int(1))
|
|
||||||
// return Command::FAILURE;
|
return Command::SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getStorageNames() {
|
protected function getStorageNames() {
|
||||||
@ -78,7 +107,7 @@ class CreateConfigFileCommand extends Command {
|
|||||||
return $storages;
|
return $storages;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function verifyFileCanBeCreated($filePath, $fileName) {
|
protected function verifyAndCreateFile($filePath, $fileName) {
|
||||||
if (empty($filePath)) {
|
if (empty($filePath)) {
|
||||||
throw new \RuntimeException('Configuration file path cannot be empty');
|
throw new \RuntimeException('Configuration file path cannot be empty');
|
||||||
}
|
}
|
||||||
@ -104,8 +133,15 @@ class CreateConfigFileCommand extends Command {
|
|||||||
$this->configs['general'] = [];
|
$this->configs['general'] = [];
|
||||||
if ($this->io->confirm('Enable logging?')) {
|
if ($this->io->confirm('Enable logging?')) {
|
||||||
$this->configs['general']['logger'] = [];
|
$this->configs['general']['logger'] = [];
|
||||||
$logFilePath = $this->io->askQuestion(new Question('Where to create log file?'));
|
|
||||||
$this->configs['general']['logger']['file'] = $this->verifyFileCanBeCreated($logFilePath, CreateConfigFileCommand::$LOGGER_FILE_NAME);
|
$logFileQuestion = new Question('Where to create log file?');
|
||||||
|
$self = $this;
|
||||||
|
$logFileQuestion->setAutocompleterCallback(function(string $input) use ($self) {
|
||||||
|
return $self->autocompleteFilePathCallback($input);
|
||||||
|
});
|
||||||
|
$logFilePath = $this->io->askQuestion($logFileQuestion);
|
||||||
|
|
||||||
|
$this->configs['general']['logger']['file'] = $this->verifyAndCreateFile($logFilePath, CreateConfigFileCommand::$LOGGER_FILE_NAME);
|
||||||
|
|
||||||
$logLevelChoiceQuestion = new ChoiceQuestion('Log level (defaults to ERROR)', array_keys(Monolog::getLevels()), 4);
|
$logLevelChoiceQuestion = new ChoiceQuestion('Log level (defaults to ERROR)', array_keys(Monolog::getLevels()), 4);
|
||||||
$logLevelChoiceQuestion->setErrorMessage('Log level %s is invalid');
|
$logLevelChoiceQuestion->setErrorMessage('Log level %s is invalid');
|
||||||
@ -134,5 +170,4 @@ class CreateConfigFileCommand extends Command {
|
|||||||
$configBuilder = new ConfigBuilder($this->fullFilePath);
|
$configBuilder = new ConfigBuilder($this->fullFilePath);
|
||||||
$configBuilder->saveConfigs($this->configs);
|
$configBuilder->saveConfigs($this->configs);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,9 +21,9 @@ class ConfigBuilder implements ConfigurationInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getConfigTreeBuilder() {
|
public function getConfigTreeBuilder() {
|
||||||
$treeBuilder = new TreeBuilder();
|
$treeBuilder = new TreeBuilder('configs', 'array');
|
||||||
$rootNode = $treeBuilder->root('configs');
|
$rootNode = $treeBuilder->getRootNode();
|
||||||
$ref = $rootNode->children()
|
$ref = $rootNode->children()
|
||||||
->arrayNode('general')
|
->arrayNode('general')
|
||||||
->children()
|
->children()
|
||||||
->arrayNode('logger')
|
->arrayNode('logger')
|
||||||
|
@ -26,8 +26,7 @@ class Console extends AbstractConsole {
|
|||||||
if (isset($input)) {
|
if (isset($input)) {
|
||||||
$input = $this->convertToString($input);
|
$input = $this->convertToString($input);
|
||||||
}
|
}
|
||||||
$process = new Process(implode(' ', $stdin), null, $envs, $input);
|
$process = new Process($stdin, null, $envs, $input);
|
||||||
$process->inheritEnvironmentVariables();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$process->mustRun();
|
$process->mustRun();
|
||||||
|
@ -47,11 +47,12 @@ class Plugin extends ServerPlugin {
|
|||||||
function __construct($configFile){
|
function __construct($configFile){
|
||||||
$this->rawConfigs = $this->buildConfigurations($configFile);
|
$this->rawConfigs = $this->buildConfigurations($configFile);
|
||||||
$this->storageManager = new StorageManager($this->rawConfigs);
|
$this->storageManager = new StorageManager($this->rawConfigs);
|
||||||
|
$this->logger = new Logger($this->rawConfigs, 'BaikalStorage');
|
||||||
$this->initializeStorages($this->rawConfigs);
|
$this->initializeStorages($this->rawConfigs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getDisplayName($path) {
|
private function getDisplayName($path) {
|
||||||
// Remove filepath (e.g Remove xxxx.ics from calendars/collection_name/xxxx.ics)
|
// Remove filepath
|
||||||
$urlParts = explode('/', $path);
|
$urlParts = explode('/', $path);
|
||||||
$calendarUrl = implode('/', array_slice($urlParts, 0, sizeof($urlParts)-1));
|
$calendarUrl = implode('/', array_slice($urlParts, 0, sizeof($urlParts)-1));
|
||||||
|
|
||||||
@ -307,4 +308,3 @@ class Plugin extends ServerPlugin {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,10 @@ class StorageManager {
|
|||||||
$this->configs = $configs;
|
$this->configs = $configs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getStorages() {
|
||||||
|
return $this->storages;
|
||||||
|
}
|
||||||
|
|
||||||
public function fromStorageSource(Calendar $calendar) {
|
public function fromStorageSource(Calendar $calendar) {
|
||||||
if (!isset($this->configs)) {
|
if (!isset($this->configs)) {
|
||||||
throw new \Exception('StorageManager was not initialize or configs are not defined');
|
throw new \Exception('StorageManager was not initialize or configs are not defined');
|
||||||
@ -34,9 +38,6 @@ class StorageManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStorages() {
|
|
||||||
return $this->storages;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getConfigs() {
|
public function getConfigs() {
|
||||||
return $this->configs;
|
return $this->configs;
|
||||||
@ -72,4 +73,3 @@ class StorageManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,4 +11,3 @@ interface IStorage {
|
|||||||
public function getConfigBrowser();
|
public function getConfigBrowser();
|
||||||
public function updateConfigs($postData);
|
public function updateConfigs($postData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,6 +179,7 @@ class Taskwarrior implements IStorage {
|
|||||||
if (!isset($c->VTODO)){
|
if (!isset($c->VTODO)){
|
||||||
throw new \Exception('Calendar event does not contain VTODO');
|
throw new \Exception('Calendar event does not contain VTODO');
|
||||||
}
|
}
|
||||||
|
$this->logger->info(sprintf('Executing on calendar %s', $displayname));
|
||||||
$this->logger->info(json_encode($c->jsonSerialize()));
|
$this->logger->info(json_encode($c->jsonSerialize()));
|
||||||
$this->refresh();
|
$this->refresh();
|
||||||
$task = $this->vObjectToTask($c->VTODO, $displayname);
|
$task = $this->vObjectToTask($c->VTODO, $displayname);
|
||||||
@ -206,6 +207,7 @@ class Taskwarrior implements IStorage {
|
|||||||
}
|
}
|
||||||
$task = $this->tasks[(string)$uid];
|
$task = $this->tasks[(string)$uid];
|
||||||
if (isset($task) && $task['status'] !== 'deleted') {
|
if (isset($task) && $task['status'] !== 'deleted') {
|
||||||
|
$this->logger->info(sprintf('Deleting iCal %s from taskwarrior', $uid));
|
||||||
$uuid = $task['uuid'];
|
$uuid = $task['uuid'];
|
||||||
$this->logger->info(
|
$this->logger->info(
|
||||||
sprintf('Executing TASKRC = %s TASKDATA = %s task delete %s', $this->configs['taskrc'], $this->configs['taskdata'], $uuid)
|
sprintf('Executing TASKRC = %s TASKDATA = %s task delete %s', $this->configs['taskrc'], $this->configs['taskdata'], $uuid)
|
||||||
@ -225,6 +227,5 @@ class Taskwarrior implements IStorage {
|
|||||||
$this->logger->error($e->getTraceAsString());
|
$this->logger->error($e->getTraceAsString());
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user