summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/AbstractApplication.php650
-rw-r--r--source/Application/Cli.php30
-rw-r--r--source/Command/AbstractCommand.php53
-rw-r--r--source/Command/Backup.php107
-rw-r--r--source/Command/Channel.php127
-rw-r--r--source/Command/Channel/AbstractCommand.php37
-rw-r--r--source/Command/Channel/Add.php66
-rw-r--r--source/Command/Channel/CommandInterface.php21
-rw-r--r--source/Command/Channel/Delete.php87
-rw-r--r--source/Command/Channel/Edit.php102
-rw-r--r--source/Command/Channel/List.php54
-rw-r--r--source/Command/CommandInterface.php26
-rw-r--r--source/Command/Install.php96
-rw-r--r--source/Command/Restore.php152
-rw-r--r--source/Command/Upgrade.php227
-rw-r--r--source/Command/User.php144
-rw-r--r--source/Command/User/AbstractCommand.php63
-rw-r--r--source/Command/User/Add.php124
-rw-r--r--source/Command/User/CommandInterface.php31
-rw-r--r--source/Command/User/Delete.php105
-rw-r--r--source/Command/User/Edit.php161
-rw-r--r--source/Command/User/List.php58
-rw-r--r--source/Command/VerifyInstallation.php69
-rw-r--r--source/Command/VerifyInstallation/AbstractCommand.php50
-rw-r--r--source/Command/VerifyInstallation/LocalFiles.php70
-rw-r--r--source/Command/VerifyInstallation/Version.php40
-rw-r--r--source/Configuration/Path.php220
-rw-r--r--source/File.php122
-rw-r--r--source/Filesystem.php203
-rw-r--r--source/Input.php204
-rw-r--r--source/InputDependentInterface.php21
-rw-r--r--source/Output.php57
-rw-r--r--source/OutputDependentInterface.php21
-rw-r--r--source/String.php38
34 files changed, 3636 insertions, 0 deletions
diff --git a/source/AbstractApplication.php b/source/AbstractApplication.php
new file mode 100644
index 0000000..5966447
--- /dev/null
+++ b/source/AbstractApplication.php
@@ -0,0 +1,650 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-17
+ */
+
+/**
+ * Class AbstractApplication
+ * This class is doing a lot. See it as class that is the
+ * - Application
+ * - Factory
+ * - ServiceLocator
+ */
+abstract class AbstractApplication
+{
+ /**
+ * @var array
+ */
+ private $arguments = array();
+
+ /**
+ * @var array
+ */
+ private $chatConfiguration = array();
+
+ /**
+ * @var array
+ */
+ private $channels = array();
+
+ /**
+ * @var array
+ */
+ private $instancePool;
+
+ /**
+ * @var array
+ */
+ private $roles = array();
+
+ /**
+ * @var array
+ */
+ private $users = array();
+
+ //begin of command
+ /**
+ * @return Command_Backup
+ */
+ public function getBackupCommand()
+ {
+ if ($this->isNotInInstancePool('command_backup')) {
+ $command = new Command_Backup();
+ $command->setFilesystem($this->getFilesystem());
+ $command->setInput($this->getInput());
+ $command->setPathConfiguration($this->getPathConfiguration());
+ $command->setOutput($this->getOutput());
+ $this->setToInstancePool('command_backup', $command);
+ }
+
+ return $this->getFromInstancePool('command_backup');
+ }
+
+ /**
+ * @return Command_Channel
+ */
+ public function getChannelCommand()
+ {
+ if ($this->isNotInInstancePool('channel_command')) {
+ $command = new Command_Channel();
+ $command->setApplication($this);
+ $command->setFilesystem($this->getFilesystem());
+ $command->setInput($this->getInput());
+ $command->setOutput($this->getOutput());
+ $this->setToInstancePool(
+ 'channel_command',
+ $command
+ );
+ }
+
+ return $this->getFromInstancePool('channel_command');
+ }
+
+ /**
+ * @return Command_Channel_Add
+ */
+ public function getChannelAddCommand()
+ {
+ if ($this->isNotInInstancePool('channel_add_command')) {
+ $command = new Command_Channel_Add();
+ $command->setChannelFile($this->getChannelFile());
+ $command->setChannels($this->getChannels());
+ $command->setInput($this->getInput());
+ $command->setOutput($this->getOutput());
+ $this->setToInstancePool(
+ 'channel_add_command',
+ $command
+ );
+ }
+
+ return $this->getFromInstancePool('channel_add_command');
+ }
+
+ /**
+ * @return Command_Channel_Delete
+ */
+ public function getChannelDeleteCommand()
+ {
+ if ($this->isNotInInstancePool('channel_delete_command')) {
+ $command = new Command_Channel_Delete();
+ $command->setChannelFile($this->getChannelFile());
+ $command->setChannels($this->getChannels());
+ $command->setInput($this->getInput());
+ $command->setOutput($this->getOutput());
+ $this->setToInstancePool(
+ 'channel_delete_command',
+ $command
+ );
+ }
+
+ return $this->getFromInstancePool('channel_delete_command');
+ }
+
+ /**
+ * @return Command_Channel_Edit
+ */
+ public function getChannelEditCommand()
+ {
+ if ($this->isNotInInstancePool('channel_edit_command')) {
+ $command = new Command_Channel_Edit();
+ $command->setChannelFile($this->getChannelFile());
+ $command->setChannels($this->getChannels());
+ $command->setInput($this->getInput());
+ $command->setOutput($this->getOutput());
+ $this->setToInstancePool(
+ 'channel_edit_command',
+ $command
+ );
+ }
+
+ return $this->getFromInstancePool('channel_edit_command');
+ }
+
+ /**
+ * @return Command_Channel_List
+ */
+ public function getChannelListCommand()
+ {
+ if ($this->isNotInInstancePool('channel_list_command')) {
+ $command = new Command_Channel_List();
+ $command->setChannelFile($this->getChannelFile());
+ $command->setChannels($this->getChannels());
+ $command->setInput($this->getInput());
+ $command->setOutput($this->getOutput());
+ $this->setToInstancePool(
+ 'channel_list_command',
+ $command
+ );
+ }
+
+ return $this->getFromInstancePool('channel_list_command');
+ }
+
+ /**
+ * @return Command_Install
+ */
+ public function getInstallCommand()
+ {
+ if ($this->isNotInInstancePool('install_command')) {
+ $command = new Command_Install();
+ $command->setFilesystem($this->getFilesystem());
+ $command->setInput($this->getInput());
+ $command->setPathConfiguration($this->getPathConfiguration());
+ $command->setOutput($this->getOutput());
+ $this->setToInstancePool(
+ 'install_command',
+ $command
+ );
+ }
+
+ return $this->getFromInstancePool('install_command');
+ }
+
+ /**
+ * @return Command_Restore
+ */
+ public function getRestoreCommand()
+ {
+ if ($this->isNotInInstancePool('restore_command')) {
+ $command = new Command_Restore();
+ $command->setFilesystem($this->getFilesystem());
+ $command->setInput($this->getInput());
+ $command->setPathConfiguration($this->getPathConfiguration());
+ $command->setOutput($this->getOutput());
+ $this->setToInstancePool(
+ 'restore_command',
+ $command
+ );
+ }
+
+ return $this->getFromInstancePool('restore_command');
+ }
+
+ /**
+ * @return Command_Upgrade
+ */
+ public function getUpgradeCommand()
+ {
+ if ($this->isNotInInstancePool('upgrade_command')) {
+ $command = new Command_Upgrade();
+ $command->setApplication($this);
+ $command->setChangeLog($this->getFile($this->getPathConfiguration()->getChangeLogFilePath()));
+ $command->setFilesystem($this->getFilesystem());
+ $command->setInput($this->getInput());
+ $command->setPathConfiguration($this->getPathConfiguration());
+ $command->setOutput($this->getOutput());
+ $this->setToInstancePool(
+ 'upgrade_command',
+ $command
+ );
+ }
+
+ return $this->getFromInstancePool('upgrade_command');
+ }
+
+ /**
+ * @return Command_User
+ */
+ public function getUserCommand()
+ {
+ if ($this->isNotInInstancePool('user_command')) {
+ $command = new Command_User();
+ $command->setApplication($this);
+ $command->setFilesystem($this->getFilesystem());
+ $command->setInput($this->getInput());
+ $command->setPathConfiguration($this->getPathConfiguration());
+ $command->setOutput($this->getOutput());
+ $this->setToInstancePool(
+ 'user_command',
+ $command
+ );
+ }
+
+ return $this->getFromInstancePool('user_command');
+ }
+
+ /**
+ * @return Command_User_Add
+ */
+ public function getUserAddCommand()
+ {
+ if ($this->isNotInInstancePool('user_add_command')) {
+ $command = new Command_User_Add();
+ $command->setChannels($this->getChannels());
+ $command->setOutput($this->getOutput());
+ $command->setRoles($this->getRoles());
+ $command->setUserFile($this->getUserFile());
+ $command->setUsers($this->getUsers());
+ $this->setToInstancePool(
+ 'user_add_command',
+ $command
+ );
+ }
+
+ return $this->getFromInstancePool('user_add_command');
+ }
+
+ /**
+ * @return Command_User_Edit
+ */
+ public function getUserEditCommand()
+ {
+ if ($this->isNotInInstancePool('user_edit_command')) {
+ $command = new Command_User_Edit();
+ $command->setChannels($this->getChannels());
+ $command->setInput($this->getInput());
+ $command->setOutput($this->getOutput());
+ $command->setRoles($this->getRoles());
+ $command->setUserFile($this->getUserFile());
+ $command->setUsers($this->getUsers());
+ $this->setToInstancePool(
+ 'user_edit_command',
+ $command
+ );
+ }
+
+ return $this->getFromInstancePool('user_edit_command');
+ }
+
+ /**
+ * @return Command_User_Delete
+ */
+ public function getUserDeleteCommand()
+ {
+ if ($this->isNotInInstancePool('user_delete_command')) {
+ $command = new Command_User_Delete();
+ $command->setChannels($this->getChannels());
+ $command->setInput($this->getInput());
+ $command->setOutput($this->getOutput());
+ $command->setRoles($this->getRoles());
+ $command->setUserFile($this->getUserFile());
+ $command->setUsers($this->getUsers());
+ $this->setToInstancePool(
+ 'user_delete_command',
+ $command
+ );
+ }
+
+ return $this->getFromInstancePool('user_delete_command');
+ }
+
+ /**
+ * @return Command_User_List
+ */
+ public function getUserListCommand()
+ {
+ if ($this->isNotInInstancePool('user_list_command')) {
+ $command = new Command_User_List();
+ $command->setChannels($this->getChannels());
+ $command->setInput($this->getInput());
+ $command->setOutput($this->getOutput());
+ $command->setRoles($this->getRoles());
+ $command->setUserFile($this->getUserFile());
+ $command->setUsers($this->getUsers());
+ $this->setToInstancePool(
+ 'user_list_command',
+ $command
+ );
+ }
+
+ return $this->getFromInstancePool('user_list_command');
+ }
+
+ /**
+ * @return Command_VerifyInstallation
+ */
+ public function getVerifyInstallationCommand()
+ {
+ if ($this->isNotInInstancePool('validate_installation_command')) {
+ $command = new Command_VerifyInstallation();
+ $command->setApplication($this);
+ $command->setInput($this->getInput());
+ $command->setOutput($this->getOutput());
+ $this->setToInstancePool(
+ 'validate_installation_command',
+ $command
+ );
+ }
+
+ return $this->getFromInstancePool('validate_installation_command');
+ }
+
+ /**
+ * @return Command_VerifyInstallation_LocalFiles
+ */
+ public function getVerifyInstallationLocalFilesCommand()
+ {
+ if ($this->isNotInInstancePool('validate_installation_local_files_command')) {
+ $command = new Command_VerifyInstallation_LocalFiles();
+ $command->setApplication($this);
+ $command->setFilesystem($this->getFilesystem());
+ $command->setInput($this->getInput());
+ $command->setPathConfiguration($this->getPathConfiguration());
+ $command->setOutput($this->getOutput());
+ $this->setToInstancePool(
+ 'validate_installation_local_files_command',
+ $command
+ );
+ }
+
+ return $this->getFromInstancePool('validate_installation_local_files_command');
+ }
+
+ /**
+ * @return Command_VerifyInstallation_Version
+ */
+ public function getVerifyInstallationVersionCommand()
+ {
+ if ($this->isNotInInstancePool('validate_installation_version_command')) {
+ $command = new Command_VerifyInstallation_Version();
+ $command->setApplication($this);
+ $command->setFilesystem($this->getFilesystem());
+ $command->setInput($this->getInput());
+ $command->setPathConfiguration($this->getPathConfiguration());
+ $command->setOutput($this->getOutput());
+ $this->setToInstancePool(
+ 'validate_installation_version_command',
+ $command
+ );
+ }
+
+ return $this->getFromInstancePool('validate_installation_version_command');
+ }
+ //end of command
+
+ //begin of file
+ /**
+ * @return File
+ */
+ public function getChannelFile()
+ {
+ if ($this->isNotInInstancePool('channel_file')) {
+ $this->setToInstancePool(
+ 'channel_file',
+ $this->getFile(
+ $this->getPathConfiguration()->getChatChannelsFilePath()
+ )
+ );
+ }
+
+ return $this->getFromInstancePool('channel_file');
+ }
+
+ /**
+ * @return File
+ */
+ public function getUserFile()
+ {
+ if ($this->isNotInInstancePool('user_file')) {
+ $this->setToInstancePool(
+ 'user_file',
+ $this->getFile(
+ $this->getPathConfiguration()->getChatUsersFilePath()
+ )
+ );
+ }
+
+ return $this->getFromInstancePool('user_file');
+ }
+ //end of file
+
+ /**
+ * @return array
+ */
+ public function getChannels()
+ {
+ if (empty($this->channels)) {
+ $this->setPropertyFromFile(
+ 'channels',
+ 'channels',
+ $this->getPathConfiguration()->getChatChannelsFilePath()
+ );
+ }
+
+ return $this->channels;
+ }
+
+ /**
+ * @return array
+ */
+ public function getChatConfiguration()
+ {
+ if (empty($this->chatConfiguration)) {
+ $this->setPropertyFromFile(
+ 'chatConfiguration',
+ 'config',
+ $this->getPathConfiguration()->getChatConfigurationFilePath()
+ );
+ }
+
+ return $this->chatConfiguration;
+ }
+
+ /**
+ * @return string
+ */
+ public function getCurrentVersion()
+ {
+ return require $this->getPathConfiguration()->getChatVersionFilePath();
+ }
+
+ /**
+ * @return string
+ */
+ public function getExampleVersion()
+ {
+ return require $this->getPathConfiguration()->getExampleVersionFilePath();
+ }
+
+ /**
+ * @param null|string $path
+ * @return File
+ */
+ public function getFile($path = null)
+ {
+ return new File($path);
+ }
+
+ /**
+ * @return Filesystem
+ */
+ public function getFilesystem()
+ {
+ if ($this->isNotInInstancePool('filesystem')) {
+ $filesystem = new Filesystem();
+ $this->setToInstancePool('filesystem', $filesystem);
+ }
+
+ return $this->getFromInstancePool('filesystem');
+ }
+
+ /**
+ * @return Input
+ */
+ public function getInput()
+ {
+ if ($this->isNotInInstancePool('input')) {
+ $this->setToInstancePool(
+ 'input',
+ new Input($this->getString(), $this->arguments)
+ );
+ }
+
+ return $this->getFromInstancePool('input');
+ }
+
+ /**
+ * @return Output
+ */
+ public function getOutput()
+ {
+ if ($this->isNotInInstancePool('output')) {
+ $this->setToInstancePool(
+ 'output',
+ new Output()
+ );
+ }
+
+ return $this->getFromInstancePool('output');
+ }
+
+ /**
+ * @return Configuration_Path
+ */
+ public function getPathConfiguration()
+ {
+ if ($this->isNotInInstancePool('configuration_path')) {
+ $configuration = new Configuration_Path('..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR);
+ $this->setToInstancePool('configuration_path', $configuration);
+ }
+
+ return $this->getFromInstancePool('configuration_path');
+ }
+
+ /**
+ * @return array
+ */
+ public function getRoles()
+ {
+ $this->getChatConfiguration();
+ if (empty($this->roles)) {
+ if (defined('AJAX_CHAT_GUEST')) {
+ $this->roles = array(
+ AJAX_CHAT_GUEST => 'AJAX_CHAT_GUEST',
+ AJAX_CHAT_USER => 'AJAX_CHAT_USER',
+ AJAX_CHAT_MODERATOR => 'AJAX_CHAT_MODERATOR',
+ AJAX_CHAT_ADMIN => 'AJAX_CHAT_ADMIN',
+ AJAX_CHAT_CHATBOT => 'AJAX_CHAT_CHATBOT',
+ AJAX_CHAT_CUSTOM => 'AJAX_CHAT_CUSTOM',
+ AJAX_CHAT_BANNED => 'AJAX_CHAT_BANNED'
+ );
+ }
+ }
+
+ return $this->roles;
+ }
+
+ /**
+ * @return String
+ */
+ public function getString()
+ {
+ if ($this->isNotInInstancePool('string')) {
+ $this->setToInstancePool('string', new String());
+ }
+
+ return $this->getFromInstancePool('string');
+ }
+
+ /**
+ * @return array
+ */
+ public function getUsers()
+ {
+ //@todo - fix this damn call, if we remove this the needed constants are not defined
+ $this->getChatConfiguration();
+ if (empty($this->users)) {
+ $this->setPropertyFromFile(
+ 'users',
+ 'users',
+ $this->getPathConfiguration()->getChatUsersFilePath()
+ );
+ }
+
+ return $this->users;
+ }
+
+ /**
+ * @param array $arguments
+ */
+ public function setArguments(array $arguments)
+ {
+ $this->arguments = $arguments;
+ }
+
+ /**
+ * @param string $key
+ * @return mixed
+ */
+ private function getFromInstancePool($key)
+ {
+ return $this->instancePool[$key];
+ }
+
+ /**
+ * @param string $key
+ * @return bool
+ */
+ private function isNotInInstancePool($key)
+ {
+ return (!(isset($this->instancePool[$key])));
+ }
+
+ /**
+ * @param string $propertyName
+ * @param string $fileValueName
+ * @param string $filePath
+ * @throws Exception
+ */
+ private function setPropertyFromFile($propertyName, $fileValueName, $filePath)
+ {
+ if (!is_file($filePath)) {
+ throw new Exception(
+ 'provided file path is not valid: ' . $filePath
+ );
+ }
+
+ require $filePath;
+ $this->$propertyName = $$fileValueName;
+ }
+
+ /**
+ * @param string $key
+ * @param mixed $value
+ */
+ private function setToInstancePool($key, $value)
+ {
+ $this->instancePool[$key] = $value;
+ }
+} \ No newline at end of file
diff --git a/source/Application/Cli.php b/source/Application/Cli.php
new file mode 100644
index 0000000..7c4ec19
--- /dev/null
+++ b/source/Application/Cli.php
@@ -0,0 +1,30 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-17
+ */
+
+/**
+ * Class Application_Cli
+ */
+class Application_Cli extends AbstractApplication
+{
+ /**
+ * @throws Exception
+ */
+ public function __construct()
+ {
+ global $argv;
+
+ $isNotCalledFromCommandLineInterface = (PHP_SAPI !== 'cli');
+
+ if ($isNotCalledFromCommandLineInterface) {
+ throw new Exception(
+ 'command line script only '
+ );
+ }
+ $arguments = $argv;
+ array_shift($arguments);
+ $this->setArguments($arguments);
+ }
+} \ No newline at end of file
diff --git a/source/Command/AbstractCommand.php b/source/Command/AbstractCommand.php
new file mode 100644
index 0000000..55b91eb
--- /dev/null
+++ b/source/Command/AbstractCommand.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-13
+ */
+
+/**
+ * Class Command_AbstractCommand
+ */
+abstract class Command_AbstractCommand implements Command_CommandInterface
+{
+ /**
+ * @var Input
+ */
+ protected $input;
+
+ /**
+ * @var Output
+ */
+ protected $output;
+
+ /**
+ * @return Input
+ */
+ public function getInput()
+ {
+ return $this->input;
+ }
+
+ /**
+ * @param Input $input
+ */
+ public function setInput(Input $input)
+ {
+ $this->input = $input;
+ }
+
+ /**
+ * @return null|Output
+ */
+ public function getOutput()
+ {
+ return $this->output;
+ }
+
+ /**
+ * @param Output $output
+ */
+ public function setOutput(Output $output)
+ {
+ $this->output = $output;
+ }
+} \ No newline at end of file
diff --git a/source/Command/Backup.php b/source/Command/Backup.php
new file mode 100644
index 0000000..14b74c6
--- /dev/null
+++ b/source/Command/Backup.php
@@ -0,0 +1,107 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-16
+ */
+
+/**
+ * Class Command_Backup
+ */
+class Command_Backup extends Command_AbstractCommand
+{
+ /**
+ * @var Configuration_Path
+ */
+ private $pathConfiguration;
+
+ /**
+ * @var Filesystem
+ */
+ private $filesystem;
+
+ /**
+ * @param Configuration_Path $configuration
+ */
+ public function setPathConfiguration(Configuration_Path $configuration)
+ {
+ $this->pathConfiguration = $configuration;
+ }
+
+ /**
+ * @param Filesystem $filesystem
+ */
+ public function setFilesystem(Filesystem $filesystem)
+ {
+ $this->filesystem = $filesystem;
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function execute()
+ {
+ if (!$this->filesystem->isDirectory($this->pathConfiguration->getBackupPath())) {
+ $this->filesystem->createDirectory($this->pathConfiguration->getBackupPath());
+ }
+
+ $identifierToPaths = array(
+ 'channels' => array(
+ 'backup' => $this->pathConfiguration->getBackupChannelsFilePath(),
+ 'chat' => $this->pathConfiguration->getChatChannelsFilePath()
+ ),
+ 'application' => array(
+ 'backup' => $this->pathConfiguration->getBackupConfigurationFilePath(),
+ 'chat' => $this->pathConfiguration->getChatConfigurationFilePath()
+ ),
+ 'users' => array(
+ 'backup' => $this->pathConfiguration->getBackupUsersFilePath(),
+ 'chat' => $this->pathConfiguration->getChatUsersFilePath()
+ ),
+ 'version' => array(
+ 'backup' => $this->pathConfiguration->getBackupVersionFilePath(),
+ 'chat' => $this->pathConfiguration->getChatVersionFilePath()
+ ),
+ );
+
+ foreach ($identifierToPaths as $identifier => $paths) {
+ if ($this->filesystem->isFile($paths['backup'])) {
+ $this->output->addLine($identifier . ' backup file available, will delete it ...');
+ $this->filesystem->deleteFile($paths['backup']);
+ }
+ }
+
+ foreach ($identifierToPaths as $identifier => $paths) {
+ echo 'creating backup of ' . $identifier . ' ...' . PHP_EOL;
+ $this->filesystem->copy(
+ $paths['chat'],
+ $paths['backup']
+ );
+ }
+ }
+
+ /**
+ * @return array
+ */
+ public function getUsage()
+ {
+ return array();
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function verify()
+ {
+ if (is_null($this->pathConfiguration)) {
+ throw new Exception(
+ 'application is mandatory'
+ );
+ }
+
+ if (is_null($this->filesystem)) {
+ throw new Exception(
+ 'filesystem is mandatory'
+ );
+ }
+ }
+} \ No newline at end of file
diff --git a/source/Command/Channel.php b/source/Command/Channel.php
new file mode 100644
index 0000000..aa5c235
--- /dev/null
+++ b/source/Command/Channel.php
@@ -0,0 +1,127 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-16
+ */
+
+class Command_Channel extends Command_AbstractCommand
+{
+ /**
+ * @var AbstractApplication
+ */
+ private $application;
+
+ /**
+ * @var string
+ */
+ private $command;
+
+ /**
+ * @var array
+ */
+ private $commands = array(
+ 'add',
+ 'edit',
+ 'delete',
+ 'list'
+ );
+
+ /**
+ * @var Filesystem
+ */
+ private $filesystem;
+
+ /**
+ * @param AbstractApplication $application
+ */
+ public function setApplication(AbstractApplication $application)
+ {
+ $this->application = $application;
+ }
+
+ /**
+ * @param Filesystem $filesystem
+ */
+ public function setFilesystem(Filesystem $filesystem)
+ {
+ $this->filesystem = $filesystem;
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function execute()
+ {
+ switch ($this->command) {
+ case 'add':
+ $command = $this->application->getChannelAddCommand();
+ break;
+ case 'edit':
+ $command = $this->application->getChannelEditCommand();
+ break;
+ case 'delete':
+ $command = $this->application->getChannelDeleteCommand();
+ break;
+ case 'list':
+ $command = $this->application->getChannelListCommand();
+ break;
+ default:
+ throw new Exception(
+ 'unsupported command "' . $this->command . '"'
+ );
+ }
+
+ $command->setInput($this->input);
+ $command->setOutput($this->output);
+
+ try {
+ $command->verify();
+ } catch (Exception $exception) {
+ throw new Exception(
+ '--' . $this->command . ' ' . implode("\n", $command->getUsage()) . PHP_EOL .
+ PHP_EOL .
+ $exception->getMessage()
+ );
+ }
+ $command->execute();
+ }
+
+ /**
+ * @return array
+ */
+ public function getUsage()
+ {
+ return array(
+ '[--' . implode('|--', $this->commands) . ']'
+ );
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function verify()
+ {
+ $this->command = null;
+
+ if ($this->input->getNumberOfArguments() < 1) {
+ throw new Exception(
+ 'invalid number of arguments provided'
+ );
+ }
+
+ foreach ($this->commands as $command) {
+ if ($this->input->hasLongOption($command)) {
+ $this->command = $command;
+ break;
+ }
+ }
+
+ if (is_null($this->command)) {
+ throw new Exception(
+ 'invalid command provided'
+ );
+ }
+
+ $this->input->removeLongOption($this->command);
+ }
+} \ No newline at end of file
diff --git a/source/Command/Channel/AbstractCommand.php b/source/Command/Channel/AbstractCommand.php
new file mode 100644
index 0000000..42b6836
--- /dev/null
+++ b/source/Command/Channel/AbstractCommand.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-14
+ */
+
+/**
+ * Class Command_Channel_AbstractCommand
+ */
+abstract class Command_Channel_AbstractCommand extends Command_AbstractCommand implements Command_Channel_CommandInterface
+{
+ /**
+ * @var File
+ */
+ protected $file;
+
+ /**
+ * @var array
+ */
+ protected $channels;
+
+ /**
+ * @param array $channels
+ */
+ public function setChannels(array $channels)
+ {
+ $this->channels = $channels;
+ }
+
+ /**
+ * @param File $file
+ */
+ public function setChannelFile(File $file)
+ {
+ $this->file = $file;
+ }
+} \ No newline at end of file
diff --git a/source/Command/Channel/Add.php b/source/Command/Channel/Add.php
new file mode 100644
index 0000000..751970c
--- /dev/null
+++ b/source/Command/Channel/Add.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-14
+ */
+
+/**
+ * Class Command_Channel_Add
+ */
+class Command_Channel_Add extends Command_Channel_AbstractCommand
+{
+ /**
+ * @var string
+ */
+ private $inputName;
+
+ /**
+ * @throws Exception
+ */
+ public function execute()
+ {
+ end($this->channels);
+ $nextKey = (key($this->channels) + 1);
+ reset($this->channels);
+
+ $content = $this->file->read();
+
+ $content[] = '// added - ' . date('Y-m-d H:i:s');
+ $content[] = '$channels[' . $nextKey . '] = \'' . $this->inputName . '\';';
+
+ $this->file->write($content);
+ }
+
+ /**
+ * @return array
+ */
+ public function getUsage()
+ {
+ return array(
+ 'name="<name>"',
+ ' available channels: ' . implode(',', array_keys($this->channels)),
+ );
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function verify()
+ {
+ if ($this->input->getNumberOfArguments() !== 1) {
+ throw new Exception(
+ 'invalid number of arguments provided'
+ );
+ }
+
+ $name = $this->input->getParameterValue('name');
+
+ if (is_null($name)) {
+ throw new Exception(
+ 'invalid name "' . $name . '" provided'
+ );
+ }
+
+ $this->inputName = $name;
+ }
+}
diff --git a/source/Command/Channel/CommandInterface.php b/source/Command/Channel/CommandInterface.php
new file mode 100644
index 0000000..72af707
--- /dev/null
+++ b/source/Command/Channel/CommandInterface.php
@@ -0,0 +1,21 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-14
+ */
+
+/**
+ * Interface Command_Channel_CommandInterface
+ */
+interface Command_Channel_CommandInterface extends Command_CommandInterface
+{
+ /**
+ * @param array $channels
+ */
+ public function setChannels(array $channels);
+
+ /**
+ * @param File $file
+ */
+ public function setChannelFile(File $file);
+} \ No newline at end of file
diff --git a/source/Command/Channel/Delete.php b/source/Command/Channel/Delete.php
new file mode 100644
index 0000000..af7a791
--- /dev/null
+++ b/source/Command/Channel/Delete.php
@@ -0,0 +1,87 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-14
+ */
+
+/**
+ * Class Command_Channel_Delete
+ */
+class Command_Channel_Delete extends Command_Channel_AbstractCommand
+{
+ /**
+ * @var int
+ */
+ private $inputId;
+
+ /**
+ * @throws Exception
+ */
+ public function execute()
+ {
+ reset($this->channels);
+
+ $lines = $this->file->read();
+ $content = array();
+
+ foreach ($lines as $line) {
+ if ($line == '// Sample channel list:') {
+ $content[] = $line;
+ break;
+ } else {
+ $content[] = $line;
+ }
+ }
+
+ if (empty($this->channels)) {
+ throw new Exception(
+ 'nothing to delete'
+ );
+ } else {
+ unset($this->channels[$this->inputId]);
+ $ids = array_values($this->channels);
+
+ if (!empty($ids)) {
+ foreach ($ids as $id => $name) {
+ $content[] = '$channels[' . $id . '] = \'' . $name . '\';';
+ }
+ }
+
+ $this->file->write($content);
+ }
+ }
+
+ /**
+ * @return array
+ */
+ public function getUsage()
+ {
+ return array(
+ 'channel_id=<channel id>',
+ ' available channels: ' . implode(',', array_keys($this->channels))
+ );
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function verify()
+ {
+ if ($this->input->getNumberOfArguments() !== 1) {
+ throw new Exception(
+ 'invalid number of arguments provided'
+ );
+ }
+
+ $validIds = array_keys($this->channels);
+ $inputId = $this->input->getParameterValue('channel_id');
+
+ if (!isset($validIds[$inputId])) {
+ throw new Exception(
+ 'invalid name "' . $inputId . '" provided'
+ );
+ }
+
+ $this->inputId = $inputId;
+ }
+}
diff --git a/source/Command/Channel/Edit.php b/source/Command/Channel/Edit.php
new file mode 100644
index 0000000..fc852b6
--- /dev/null
+++ b/source/Command/Channel/Edit.php
@@ -0,0 +1,102 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-14
+ */
+
+/**
+ * Class Command_Channel_Edit
+ */
+class Command_Channel_Edit extends Command_Channel_AbstractCommand
+{
+ /**
+ * @var string
+ */
+ private $inputName;
+
+ /**
+ * @var int
+ */
+ private $inputId;
+
+ /**
+ * @throws Exception
+ */
+ public function execute()
+ {
+ reset($this->channels);
+
+ $lines = $this->file->read();
+ $content = array();
+ $contentAfterCurrentChannel = array();
+ $string = new String();
+
+ $foundCurrentChannelLine = false;
+ $linePrefixToSearchFor = '$channels[' . $this->inputId . ']';
+
+ foreach ($lines as $line) {
+ if ($string->startsWith($line, $linePrefixToSearchFor)) {
+ $foundCurrentChannelLine = true;
+ } else {
+ if ($foundCurrentChannelLine) {
+ $contentAfterCurrentChannel[] = $line;
+ } else {
+ $content[] = $line;
+ }
+ }
+ }
+
+ $content[] = '$channels[' . $this->inputId . '] = \'' . $this->inputName . '\';';
+
+ foreach ($contentAfterCurrentChannel as $line) {
+ $content[] = $line;
+ }
+
+ $this->file->write($content);
+ }
+
+ /**
+ * @return array
+ */
+ public function getUsage()
+ {
+ return array(
+ 'id=<id> name="<name>"',
+ ' available channels: ' . implode(',', array_keys($this->channels))
+ );
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function verify()
+ {
+ if ($this->input->getNumberOfArguments() !== 2) {
+ throw new Exception(
+ 'invalid number of arguments provided'
+ );
+ }
+
+ $name = $this->input->getParameterValue('name');
+ $id = $this->input->getParameterValue('id');
+
+ if (is_null($name)) {
+ throw new Exception(
+ 'no name provided'
+ );
+ }
+
+ if (is_null($id)) {
+ throw new Exception(
+ 'no id provided'
+ );
+ } else if (!isset($this->channels[$id])) {
+ throw new Exception(
+ 'invalid id provided'
+ );
+ }
+
+ $this->inputName = $name;
+ $this->inputId = $id;
+ }
+} \ No newline at end of file
diff --git a/source/Command/Channel/List.php b/source/Command/Channel/List.php
new file mode 100644
index 0000000..caaa445
--- /dev/null
+++ b/source/Command/Channel/List.php
@@ -0,0 +1,54 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-14
+ */
+
+/**
+ * Class Command_Channel_List
+ */
+class Command_Channel_List extends Command_Channel_AbstractCommand
+{
+ /**
+ * @throws Exception
+ */
+ public function execute()
+ {
+ $numberOfChannels = count($this->channels);
+
+ $this->output->addLine('number of channels: ' . $numberOfChannels);
+
+ if ($numberOfChannels > 0) {
+ $this->output->addLine();
+ $this->output->addLine('id | name ');
+ $this->output->addLine('--------');
+
+ foreach ($this->channels as $id => $name) {
+ $this->output->addLine(
+ implode(
+ ' | ',
+ array(
+ $id,
+ $name
+ )
+ )
+ );
+ }
+ }
+ }
+
+ /**
+ * @return array
+ */
+ public function getUsage()
+ {
+ return array();
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function verify()
+ {
+ }
+}
diff --git a/source/Command/CommandInterface.php b/source/Command/CommandInterface.php
new file mode 100644
index 0000000..afd9908
--- /dev/null
+++ b/source/Command/CommandInterface.php
@@ -0,0 +1,26 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-13
+ */
+
+/**
+ * Interface Command_CommandInterface
+ */
+interface Command_CommandInterface extends InputDependentInterface, OutputDependentInterface
+{
+ /**
+ * @throws Exception
+ */
+ public function execute();
+
+ /**
+ * @return array
+ */
+ public function getUsage();
+
+ /**
+ * @throws Exception
+ */
+ public function verify();
+} \ No newline at end of file
diff --git a/source/Command/Install.php b/source/Command/Install.php
new file mode 100644
index 0000000..936ae69
--- /dev/null
+++ b/source/Command/Install.php
@@ -0,0 +1,96 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-17
+ */
+
+/**
+ * Class Command_Install
+ */
+class Command_Install extends Command_AbstractCommand
+{
+ /**
+ * @var Configuration_Path
+ */
+ private $pathConfiguration;
+
+ /**
+ * @var Filesystem
+ */
+ private $filesystem;
+
+ /**
+ * @param Configuration_Path $configuration
+ */
+ public function setPathConfiguration(Configuration_Path $configuration)
+ {
+ $this->pathConfiguration = $configuration;
+ }
+
+ /**
+ * @param Filesystem $filesystem
+ */
+ public function setFilesystem(Filesystem $filesystem)
+ {
+ $this->filesystem = $filesystem;
+ }
+
+ /**
+ * @throws Exception
+ * @todo implement setup of database (check if connection is available, split it up in multiple steps (Command_Install_Files, Command_Install_Database)
+ */
+ public function execute()
+ {
+ $identifierToPaths = array(
+ 'channels' => array(
+ 'example' => $this->pathConfiguration->getExampleChannelsFilePath(),
+ 'chat' => $this->pathConfiguration->getChatChannelsFilePath()
+ ),
+ 'pathConfiguration' => array(
+ 'example' => $this->pathConfiguration->getExampleConfigurationFilePath(),
+ 'chat' => $this->pathConfiguration->getChatConfigurationFilePath()
+ ),
+ 'users' => array(
+ 'example' => $this->pathConfiguration->getExampleUsersFilePath(),
+ 'chat' => $this->pathConfiguration->getChatUsersFilePath()
+ ),
+ 'version' => array(
+ 'example' => $this->pathConfiguration->getExampleVersionFilePath(),
+ 'chat' => $this->pathConfiguration->getChatVersionFilePath()
+ ),
+ );
+
+ foreach ($identifierToPaths as $identifier => $paths) {
+ if (!$this->filesystem->isFile($paths['chat'])) {
+ $directoryPath = dirname($paths['chat']);
+
+ if (!$this->filesystem->isDirectory($directoryPath)) {
+ $this->output->addLine('no directory available at "' . $directoryPath . '", will create one ...');
+ $this->filesystem->createDirectory($directoryPath);
+ }
+ $this->output->addLine('no ' . $identifier . ' file available, will create one ...');
+ $this->filesystem->copy(
+ $paths['example'],
+ $paths['chat']
+ );
+ } else {
+ $this->output->addLine($identifier . ' file available, nothing to do ...');
+ }
+ }
+ }
+
+ /**
+ * @return array
+ */
+ public function getUsage()
+ {
+ return array();
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function verify()
+ {
+ }
+} \ No newline at end of file
diff --git a/source/Command/Restore.php b/source/Command/Restore.php
new file mode 100644
index 0000000..60c78a7
--- /dev/null
+++ b/source/Command/Restore.php
@@ -0,0 +1,152 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-17
+ */
+
+/**
+ * Class Command_Restore
+ */
+class Command_Restore extends Command_AbstractCommand
+{
+ /**
+ * @var string
+ */
+ private $command;
+
+ /**
+ * @var array
+ */
+ private $commands = array(
+ 'all',
+ 'channels',
+ 'application',
+ 'users',
+ 'version'
+ );
+
+ /**
+ * @var Filesystem
+ */
+ private $filesystem;
+
+ /**
+ * @var Configuration_Path
+ */
+ private $pathConfiguration;
+
+ /**
+ * @param Configuration_Path $configuration
+ */
+ public function setPathConfiguration(Configuration_Path $configuration)
+ {
+ $this->pathConfiguration = $configuration;
+ }
+
+ /**
+ * @param Filesystem $filesystem
+ */
+ public function setFilesystem(Filesystem $filesystem)
+ {
+ $this->filesystem = $filesystem;
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function execute()
+ {
+ $identifiers = array();
+
+ switch ($this->command) {
+ case 'all':
+ $identifiers = array(
+ 'channels',
+ 'pathConfiguration',
+ 'users',
+ 'version'
+ );
+ break;
+ case 'channels':
+ $identifiers[] = 'channels';
+ break;
+ case 'pathConfiguration':
+ $identifiers[] = 'pathConfiguration';
+ break;
+ case 'users':
+ $identifiers[] = 'users';
+ break;
+ case 'version':
+ $identifiers[] = 'version';
+ break;
+ }
+
+ $identifierToPaths = array(
+ 'channels' => array(
+ 'backup' => $this->pathConfiguration->getBackupChannelsFilePath(),
+ 'chat' => $this->pathConfiguration->getChatChannelsFilePath()
+ ),
+ 'pathConfiguration' => array(
+ 'backup' => $this->pathConfiguration->getBackupConfigurationFilePath(),
+ 'chat' => $this->pathConfiguration->getChatConfigurationFilePath()
+ ),
+ 'users' => array(
+ 'backup' => $this->pathConfiguration->getBackupUsersFilePath(),
+ 'chat' => $this->pathConfiguration->getChatUsersFilePath()
+ ),
+ 'version' => array(
+ 'backup' => $this->pathConfiguration->getBackupVersionFilePath(),
+ 'chat' => $this->pathConfiguration->getChatVersionFilePath()
+ ),
+ );
+
+ foreach ($identifiers as $identifier) {
+ if ($this->filesystem->isFile($identifierToPaths[$identifier]['backup'])) {
+ $this->output->addLine($identifier . ' backup file available, will restore it ...');
+ $this->filesystem->copy(
+ $identifierToPaths[$identifier]['backup'],
+ $identifierToPaths[$identifier]['chat']
+ );
+ } else {
+ $this->output->addLine('no ' . $identifier .' backup file available ...');
+ }
+ }
+ }
+
+ /**
+ * @return array
+ */
+ public function getUsage()
+ {
+ return array(
+ '[--' . implode('|--', $this->commands) . ']'
+ );
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function verify()
+ {
+ if ($this->input->getNumberOfArguments() !== 1) {
+ throw new Exception(
+ 'invalid number of arguments provided'
+ );
+ }
+
+ foreach ($this->commands as $command) {
+ if ($this->input->hasLongOption($command)) {
+ $this->command = $command;
+ break;
+ }
+ }
+
+ if (is_null($this->command)) {
+ throw new Exception(
+ 'invalid command provided'
+ );
+ }
+
+ $this->command = $command;
+ }
+} \ No newline at end of file
diff --git a/source/Command/Upgrade.php b/source/Command/Upgrade.php
new file mode 100644
index 0000000..16ac2e6
--- /dev/null
+++ b/source/Command/Upgrade.php
@@ -0,0 +1,227 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-17
+ */
+
+/**
+ * Class Command_Upgrade
+ */
+class Command_Upgrade extends Command_AbstractCommand
+{
+ /**
+ * @var AbstractApplication
+ */
+ private $application;
+
+ /**
+ * @var File
+ */
+ private $changeLog;
+
+ /**
+ * @var Filesystem
+ */
+ private $filesystem;
+
+ /**
+ * @var Configuration_Path
+ */
+ private $pathConfiguration;
+
+ /**
+ * @param AbstractApplication $application
+ */
+ public function setApplication(AbstractApplication $application)
+ {
+ $this->application = $application;
+ }
+
+ /**
+ * @param File $file
+ */
+ public function setChangeLog(File $file)
+ {
+ $this->changeLog = $file;
+ }
+
+ /**
+ * @param Configuration_Path $configuration
+ */
+ public function setPathConfiguration(Configuration_Path $configuration)
+ {
+ $this->pathConfiguration = $configuration;
+ }
+
+ /**
+ * @param Filesystem $filesystem
+ */
+ public function setFilesystem(Filesystem $filesystem)
+ {
+ $this->filesystem = $filesystem;
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function execute()
+ {
+ //__process
+ $currentVersion = $this->application->getCurrentVersion();
+ $finalVersion = $this->application->getExampleVersion();
+ $releases = $this->fetchReleasesToProcess($currentVersion, $finalVersion);
+
+ if (empty($releases)) {
+ $this->output->addLine('nothing to do ...');
+ } else {
+ $pathToIndexPhp = $this->pathConfiguration->getChatPath() . DIRECTORY_SEPARATOR . 'index.php';
+ $pathToBackupOfIndexPhp = $pathToIndexPhp . '.backup';
+
+ $this->backup();
+ $this->executePreUpdateTasks($pathToIndexPhp, $pathToBackupOfIndexPhp);
+ $this->upgrade($releases);
+ $this->executePostUpdateTasks($pathToIndexPhp, $pathToBackupOfIndexPhp);
+
+ $this->output->addLine('upgraded from "' . $currentVersion . '" to "' . $finalVersion . '"');
+ }
+ }
+
+ /**
+ * @return array
+ */
+ public function getUsage()
+ {
+ return array();
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function verify()
+ {
+ }
+
+ /**
+ * @throws Exception
+ */
+ private function backup()
+ {
+ $command = $this->application->getBackupCommand();
+
+ $this->input->setArguments(array('--all'));
+
+ $command->setInput($this->input);
+ $command->setOutput($this->output);
+ $command->verify();
+ $command->execute();
+ }
+
+ /**
+ * @param string $pathToIndexPhp
+ * @param string $pathToBackupOfIndexPhp
+ * @throws Exception
+ */
+ private function executePreUpdateTasks($pathToIndexPhp, $pathToBackupOfIndexPhp)
+ {
+ $this->filesystem->move($pathToIndexPhp, $pathToBackupOfIndexPhp);
+ $file = $this->filesystem->createFile($pathToIndexPhp);
+ $file->write(array(
+ '<?php',
+ 'echo \'updating system, back soon\';'
+ ));
+ }
+
+ /**
+ * @param string $pathToIndexPhp
+ * @param string $pathToBackupOfIndexPhp
+ * @throws Exception
+ */
+ private function executePostUpdateTasks($pathToIndexPhp, $pathToBackupOfIndexPhp)
+ {
+ $this->filesystem->move($pathToBackupOfIndexPhp, $pathToIndexPhp);
+ $this->filesystem->copy(
+ $this->pathConfiguration->getExampleVersionFilePath(),
+ $this->pathConfiguration->getChatVersionFilePath()
+ );
+ }
+
+ private function upgrade(array $releases)
+ {
+ foreach ($releases as $release) {
+ $path = $this->pathConfiguration->getReleasePath() . DIRECTORY_SEPARATOR . $release;
+ $files = $this->fetchUpdatesFilesFromRelease($path);
+ foreach ($files as $file) {
+ $this->executeUpdateFile($file);
+ $this->changeLog->append(
+ '[' . date('Y-m-d H:i:s', time()) . '] ' .
+ $file
+ );
+ }
+ }
+ }
+
+ /**
+ * @param string $currentVersion
+ * @param string $finalVersion
+ * @return array
+ * @throws Exception
+ */
+ private function fetchReleasesToProcess($currentVersion, $finalVersion)
+ {
+ if (!is_dir($this->pathConfiguration->getReleasePath())) {
+ throw new Exception(
+ 'no directory found:' . PHP_EOL .
+ $this->pathConfiguration->getReleasePath()
+ );
+ }
+
+ $releases = $this->filesystem->getDirectories(
+ $this->pathConfiguration->getReleasePath(),
+ array('upcoming'),
+ false
+ );
+ $releasesToProcess = array();
+ foreach ($releases as $release) {
+ $isNewer = version_compare($release, $currentVersion, '>');
+ if ($isNewer) {
+ $releasesToProcess[] = $release;
+ }
+ }
+ natsort($releasesToProcess);
+
+ return $releasesToProcess;
+ }
+
+ /**
+ * @param string $path
+ * @return array
+ * @throws Exception
+ */
+ private function fetchUpdatesFilesFromRelease($path)
+ {
+ if (!is_dir($path)) {
+ throw new Exception(
+ 'provided release path is not a directory: ' . PHP_EOL . $path
+ );
+ }
+
+ $files = $this->filesystem->getFiles($path);
+
+ return $files;
+ }
+
+ /**
+ * @param string $file
+ * @throws Exception
+ */
+ private function executeUpdateFile($file)
+ {
+ if (!is_file($file)) {
+ throw new Exception(
+ 'provided path "' . $file . '" is not a file'
+ );
+ }
+
+ require $file;
+ }
+} \ No newline at end of file
diff --git a/source/Command/User.php b/source/Command/User.php
new file mode 100644
index 0000000..616eb85
--- /dev/null
+++ b/source/Command/User.php
@@ -0,0 +1,144 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-17
+ */
+
+/**
+ * Class Command_User
+ */
+class Command_User extends Command_AbstractCommand
+{
+ /**
+ * @var AbstractApplication
+ */
+ private $application;
+
+ /**
+ * @var string
+ */
+ private $command;
+
+ /**
+ * @var array
+ */
+ private $commands = array(
+ 'add',
+ 'edit',
+ 'delete',
+ 'list'
+ );
+
+ /**
+ * @var Filesystem
+ */
+ private $filesystem;
+
+ /**
+ * @var Configuration_Path
+ */
+ private $pathConfiguration;
+
+ /**
+ * @param AbstractApplication $application
+ */
+ public function setApplication(AbstractApplication $application)
+ {
+ $this->application = $application;
+ }
+
+ /**
+ * @param Configuration_Path $configuration
+ */
+ public function setPathConfiguration(Configuration_Path $configuration)
+ {
+ $this->pathConfiguration = $configuration;
+ }
+
+ /**
+ * @param \Filesystem $filesystem
+ */
+ public function setFilesystem(Filesystem $filesystem)
+ {
+ $this->filesystem = $filesystem;
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function execute()
+ {
+ switch ($this->command) {
+ case 'add':
+ $command = $this->application->getUserAddCommand();
+ break;
+ case 'edit':
+ $command = $this->application->getUserEditCommand();
+ break;
+ case 'delete':
+ $command = $this->application->getUserDeleteCommand();
+ break;
+ case 'list':
+ $command = $this->application->getUserListCommand();
+ break;
+ default:
+ throw new Exception(
+ 'unsupported command "' . $this->command . '"'
+ );
+ }
+
+ $command->setInput($this->input);
+ $command->setOutput($this->output);
+
+ try {
+ $command->verify();
+ } catch (Exception $exception) {
+ throw new Exception(
+ '--' . $this->command . ' ' . implode("\n", $command->getUsage()) . PHP_EOL .
+ PHP_EOL .
+ $exception->getMessage()
+ );
+ }
+ $command->execute();
+ }
+
+ /**
+ * @return array
+ */
+ public function getUsage()
+ {
+ return array(
+ '[--' . implode('|--', $this->commands) . ']'
+ );
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function verify()
+ {
+ $this->command = null;
+
+ if ($this->input->getNumberOfArguments() < 1) {
+ throw new Exception(
+ 'invalid number of arguments provided'
+ );
+ }
+
+
+ foreach ($this->commands as $command) {
+ if ($this->input->hasLongOption($command)) {
+ $this->command = $command;
+ break;
+ }
+ }
+
+ if (is_null($this->command)) {
+ throw new Exception(
+ 'invalid command provided'
+ );
+ }
+
+ $this->input->removeLongOption($this->command);
+ }
+} \ No newline at end of file
diff --git a/source/Command/User/AbstractCommand.php b/source/Command/User/AbstractCommand.php
new file mode 100644
index 0000000..00512c2
--- /dev/null
+++ b/source/Command/User/AbstractCommand.php
@@ -0,0 +1,63 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-14
+ */
+
+/**
+ * Class Command_User_AbstractCommand
+ */
+abstract class Command_User_AbstractCommand extends Command_AbstractCommand implements Command_User_CommandInterface
+{
+ /**
+ * @var array
+ */
+ protected $channels;
+
+ /**
+ * @var array
+ */
+ protected $roles;
+
+ /**
+ * @var File
+ */
+ protected $file;
+
+ /**
+ * @var array
+ */
+ protected $users;
+
+ /**
+ * @param array $channels
+ */
+ public function setChannels(array $channels)
+ {
+ $this->channels = $channels;
+ }
+
+ /**
+ * @param array $roles
+ */
+ public function setRoles(array $roles)
+ {
+ $this->roles = $roles;
+ }
+
+ /**
+ * @param \File $userFile
+ */
+ public function setUserFile(File $userFile)
+ {
+ $this->file = $userFile;
+ }
+
+ /**
+ * @param array $users
+ */
+ public function setUsers(array $users)
+ {
+ $this->users = $users;
+ }
+} \ No newline at end of file
diff --git a/source/Command/User/Add.php b/source/Command/User/Add.php
new file mode 100644
index 0000000..088feef
--- /dev/null
+++ b/source/Command/User/Add.php
@@ -0,0 +1,124 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-12
+ */
+
+/**
+ * Class Command_User_Add
+ */
+class Command_User_Add extends Command_User_AbstractCommand
+{
+ /**
+ * @var array
+ */
+ private $inputChannels;
+
+ /**
+ * @var string
+ */
+ private $inputName;
+
+ /**
+ * @var string
+ */
+ private $inputPassword;
+
+ /**
+ * @var string
+ */
+ private $inputRole;
+
+ /**
+ * @throws Exception
+ */
+ public function execute()
+ {
+ end($this->users);
+ $nextKey = (key($this->users) + 1);
+ reset($this->users);
+
+ $content = $this->file->read();
+
+ $content[] = '// added - ' . date('Y-m-d H:i:s');
+ $content[] = '$users[' . $nextKey . '] = array();';
+ $content[] = '$users[' . $nextKey . '][\'userRole\'] = ' . $this->roles[$this->inputRole] . ';';
+ $content[] = '$users[' . $nextKey . '][\'userName\'] = \'' . $this->inputName . '\';';
+ $content[] = '$users[' . $nextKey . '][\'password\'] = \'' . $this->inputPassword . '\';';
+ $content[] = '$users[' . $nextKey . '][\'channels\'] = array(' . implode(',', $this->inputChannels) . ');';
+
+ $this->file->write($content);
+ }
+
+ /**
+ * @return array
+ */
+ public function getUsage()
+ {
+ return array(
+ 'name="<name>" password="<password>" role=<id> channels="<id>[,<id>[...]]"',
+ ' available channels: ' . implode(',', array_keys($this->channels)),
+ ' available roles: ' . implode(',', array_keys($this->roles))
+ );
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function verify()
+ {
+ if ($this->input->getNumberOfArguments() !== 4) {
+ throw new Exception(
+ 'invalid number of arguments provided'
+ );
+ }
+
+ $channels = explode(',', $this->input->getParameterValue('channels', ''));
+ $name = $this->input->getParameterValue('name');
+ $password = $this->input->getParameterValue('password');
+ $role = $this->input->getParameterValue('role');
+
+ if (is_null($name)) {
+ throw new Exception(
+ 'no name "' . $name . '" provided'
+ );
+ }
+
+ if (is_null($role)) {
+ throw new Exception(
+ 'no role "' . $role . '" provided'
+ );
+ } else {
+ if (!isset($this->roles[$role])) {
+ throw new Exception(
+ 'invalid role "' . $role . '" provided'
+ );
+ }
+ }
+
+ if (is_null($password)) {
+ throw new Exception(
+ 'no password "' . $password . '" provided'
+ );
+ }
+
+ if (empty($channels)) {
+ throw new Exception(
+ 'no channels provided'
+ );
+ }
+
+ foreach ($channels as $channel) {
+ if (!isset($this->channels[$channel])) {
+ throw new Exception(
+ 'invalid channel "' . $channel . '" provided'
+ );
+ }
+ }
+
+ $this->inputChannels = $channels;
+ $this->inputName = $name;
+ $this->inputPassword = $password;
+ $this->inputRole = $role;
+ }
+}
diff --git a/source/Command/User/CommandInterface.php b/source/Command/User/CommandInterface.php
new file mode 100644
index 0000000..b8aa332
--- /dev/null
+++ b/source/Command/User/CommandInterface.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-14
+ */
+
+/**
+ * Interface Command_User_CommandInterface
+ */
+interface Command_User_CommandInterface extends Command_CommandInterface
+{
+ /**
+ * @param array $channels
+ */
+ public function setChannels(array $channels);
+
+ /**
+ * @param array $roles
+ */
+ public function setRoles(array $roles);
+
+ /**
+ * @param \File $userFile
+ */
+ public function setUserFile(File $userFile);
+
+ /**
+ * @param array $users
+ */
+ public function setUsers(array $users);
+} \ No newline at end of file
diff --git a/source/Command/User/Delete.php b/source/Command/User/Delete.php
new file mode 100644
index 0000000..aeed24a
--- /dev/null
+++ b/source/Command/User/Delete.php
@@ -0,0 +1,105 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-12
+ */
+
+/**
+ * Class Command_User_Delete
+ */
+class Command_User_Delete extends Command_User_AbstractCommand
+{
+ /**
+ * @var int
+ */
+ private $inputId;
+
+ /**
+ * @throws Exception
+ */
+ public function execute()
+ {
+ reset($this->users);
+
+ $lines = $this->file->read();
+ $content = array();
+
+ foreach ($lines as $line) {
+ if ($line == '$users[0][\'channels\'] = array(0);') {
+ $content[] = $line;
+ $content[] = '';
+ break;
+ } else {
+ $content[] = $line;
+ }
+ }
+
+ unset($this->users[0]);
+
+ if (empty($this->users)) {
+ throw new Exception(
+ 'nothing to delete'
+ );
+ } else {
+ unset($this->users[$this->inputId]);
+ $idToUser = array_values($this->users);
+
+ if (!empty($idToUser)) {
+ foreach ($idToUser as $id => $user) {
+ ++$id; //we have to increase by one since we have to prevent overwriting the "0" user
+ $content[] = '// updated - ' . date('Y-m-d H:i:s');
+ $content[] = '$users[' . $id . '] = array();';
+ $content[] = '$users[' . $id . '][\'userRole\'] = ' . $this->roles[$user['userRole']] . ';';
+ $content[] = '$users[' . $id . '][\'userName\'] = \'' . $user['userName'] . '\';';
+ $content[] = '$users[' . $id . '][\'password\'] = \'' . $user['password'] . '\';';
+ $content[] = '$users[' . $id . '][\'channels\'] = array(' . implode(',', $user['channels']) . ');';
+ }
+ }
+
+ $this->file->write($content);
+ }
+ }
+
+ /**
+ * @return array
+ */
+ public function getUsage()
+ {
+ $users = $this->users;
+ unset($users[0]);
+
+ return array(
+ 'userid=<id>',
+ ' available users: ' . implode(',', array_keys($users))
+ );
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function verify()
+ {
+ if ($this->input->getNumberOfArguments() !== 1) {
+ throw new Exception(
+ 'invalid number of arguments provided'
+ );
+ }
+
+ $validIds = array_keys($this->users);
+ $userId = $this->input->getParameterValue('user_id');
+
+ if (!isset($validIds[$userId])) {
+ throw new Exception(
+ 'invalid id "' . $userId . '" provided'
+ );
+ }
+
+ if ($userId === 0) {
+ throw new Exception(
+ 'you are not allowed to delete id "' . $userId . '"'
+ );
+ }
+
+ $this->inputId = $userId;
+ }
+}
diff --git a/source/Command/User/Edit.php b/source/Command/User/Edit.php
new file mode 100644
index 0000000..72467ee
--- /dev/null
+++ b/source/Command/User/Edit.php
@@ -0,0 +1,161 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-13
+ */
+
+/**
+ * Class Command_User_Edit
+ */
+class Command_User_Edit extends Command_User_AbstractCommand
+{
+ /**
+ * @var array
+ */
+ private $inputChannels;
+
+ /**
+ * @var string
+ */
+ private $inputName;
+
+ /**
+ * @var string
+ */
+ private $inputPassword;
+
+ /**
+ * @var string
+ */
+ private $inputRole;
+
+ /**
+ * @var int
+ */
+ private $inputId;
+
+ /**
+ * @throws Exception
+ */
+ public function execute()
+ {
+ reset($this->users);
+
+ $lines = $this->file->read();
+ $content = array();
+ $contentAfterCurrentUser = array();
+ $string = new String();
+
+ $foundCurrentUserContent = false;
+ $linePrefixToSearchFor = '$users[' . $this->inputId . '][';
+
+ foreach ($lines as $line) {
+ if ($string->startsWith($line, $linePrefixToSearchFor)) {
+ $foundCurrentUserContent = true;
+ } else {
+ if ($foundCurrentUserContent) {
+ $contentAfterCurrentUser[] = $line;
+ } else {
+ $content[] = $line;
+ }
+ }
+ }
+
+ $content[] = '$users[' . $this->inputId . '][\'userRole\'] = ' . $this->roles[$this->inputRole] . ';';
+ $content[] = '$users[' . $this->inputId . '][\'userName\'] = \'' . $this->inputName . '\';';
+ $content[] = '$users[' . $this->inputId . '][\'password\'] = \'' . $this->inputPassword . '\';';
+ $content[] = '$users[' . $this->inputId . '][\'channels\'] = array(' . implode(',', $this->inputChannels) . ');';
+
+ foreach ($contentAfterCurrentUser as $line) {
+ $content[] = $line;
+ }
+
+ $this->file->write($content);
+ }
+
+ /**
+ * @return array
+ */
+ public function getUsage()
+ {
+ return array(
+ 'user_id=<id> name="<name>" password="<password>" role=<id> channels="<id>[,<id>[...]]"',
+ ' available channels: ' . implode(',', array_keys($this->channels)),
+ ' available roles: ' . implode(',', array_keys($this->roles)),
+ ' available users: ' . implode(',', array_keys($this->users))
+ );
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function verify()
+ {
+ if ($this->input->getNumberOfArguments() !== 5) {
+ throw new Exception(
+ 'invalid number of arguments provided'
+ );
+ }
+
+ $channels = explode(',', $this->input->getParameterValue('channels', ''));
+ $name = $this->input->getParameterValue('name');
+ $password = $this->input->getParameterValue('password');
+ $role = $this->input->getParameterValue('role');
+ $userId = $this->input->getParameterValue('user_id');
+ $validIds = array_keys($this->users);
+
+ if (is_null($name)) {
+ throw new Exception(
+ 'no name provided'
+ );
+ }
+
+ if (is_null($role)) {
+ throw new Exception(
+ 'no role provided'
+ );
+ } else {
+ if (!isset($this->roles[$role])) {
+ throw new Exception(
+ 'invalid role "' . $role . '" provided'
+ );
+ }
+ }
+
+ if (is_null($password)) {
+ throw new Exception(
+ 'no password provided'
+ );
+ }
+
+ if (empty($channels)) {
+ throw new Exception(
+ 'no channels provided'
+ );
+ }
+
+ foreach ($channels as $channel) {
+ if (!isset($this->channels[$channel])) {
+ throw new Exception(
+ 'invalid channel "' . $channel . '" provided'
+ );
+ }
+ }
+
+ if (($userId === 0)) {
+ throw new Exception(
+ 'no id provided'
+ );
+ } else if (!isset($validIds[$userId])) {
+ throw new Exception(
+ 'invalid id provided'
+ );
+ }
+
+ $this->inputChannels = $channels;
+ $this->inputName = $name;
+ $this->inputPassword = $password;
+ $this->inputRole = $role;
+ $this->inputId = $userId;
+ }
+} \ No newline at end of file
diff --git a/source/Command/User/List.php b/source/Command/User/List.php
new file mode 100644
index 0000000..130e842
--- /dev/null
+++ b/source/Command/User/List.php
@@ -0,0 +1,58 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-12
+ */
+
+/**
+ * Class Command_User_List
+ */
+class Command_User_List extends Command_User_AbstractCommand
+{
+ /**
+ * @throws Exception
+ */
+ public function execute()
+ {
+ unset($this->users[0]);
+ //remove initial user since we are not allowed to remove this user
+ $numberOfUsers = count($this->users);
+
+ $this->output->addLine('number of users: ' . $numberOfUsers);
+
+ if ($numberOfUsers > 0) {
+ $this->output->addLine();
+ $this->output->addLine('id | name | role | channels');
+ $this->output->addLine('----------------');
+
+ foreach ($this->users as $id => $user) {
+ $this->output->addLine(
+ implode(
+ ' | ',
+ array(
+ $id,
+ $user['userName'],
+ $user['userRole'],
+ implode(',', $user['channels'])
+ )
+ )
+ );
+ }
+ }
+ }
+
+ /**
+ * @return array
+ */
+ public function getUsage()
+ {
+ return array();
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function verify()
+ {
+ }
+}
diff --git a/source/Command/VerifyInstallation.php b/source/Command/VerifyInstallation.php
new file mode 100644
index 0000000..0abd881
--- /dev/null
+++ b/source/Command/VerifyInstallation.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-17
+ */
+
+/**
+ * Class Command_VerifyInstallation
+ */
+class Command_VerifyInstallation extends Command_AbstractCommand
+{
+ /**
+ * @var AbstractApplication
+ */
+ protected $application;
+
+ /**
+ * @param AbstractApplication $application
+ */
+ public function setApplication(AbstractApplication $application)
+ {
+ $this->application = $application;
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function execute()
+ {
+ $this->verifyLocalFiles($this->application, $this->input, $this->output);
+ $this->verifyVersion($this->application, $this->input, $this->output);
+ //@todo fetch current version from url
+ }
+
+ /**
+ * @param AbstractApplication $application
+ */
+ private function verifyLocalFiles(AbstractApplication $application)
+ {
+ $command = $application->getVerifyInstallationLocalFilesCommand();
+ $command->verify();
+ $command->execute();
+ }
+
+ /**
+ * @param AbstractApplication $application
+ */
+ private function verifyVersion(AbstractApplication $application)
+ {
+ $command = $application->getVerifyInstallationVersionCommand();
+ $command->verify();
+ $command->execute();
+ }
+
+ /**
+ * @return array
+ */
+ public function getUsage()
+ {
+ return array();
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function verify()
+ {
+ }
+} \ No newline at end of file
diff --git a/source/Command/VerifyInstallation/AbstractCommand.php b/source/Command/VerifyInstallation/AbstractCommand.php
new file mode 100644
index 0000000..d64a680
--- /dev/null
+++ b/source/Command/VerifyInstallation/AbstractCommand.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-21
+ */
+
+/**
+ * Class Command_VerifyInstallation_AbstractCommand
+ */
+abstract class Command_VerifyInstallation_AbstractCommand extends Command_AbstractCommand
+{
+ /**
+ * @var AbstractApplication
+ */
+ protected $application;
+
+ /**
+ * @var Filesystem
+ */
+ protected $filesystem;
+
+ /**
+ * @var Configuration_Path
+ */
+ protected $pathConfiguration;
+
+ /**
+ * @param AbstractApplication $application
+ */
+ public function setApplication(AbstractApplication $application)
+ {
+ $this->application = $application;
+ }
+
+ /**
+ * @param Filesystem $filesystem
+ */
+ public function setFilesystem(Filesystem $filesystem)
+ {
+ $this->filesystem = $filesystem;
+ }
+
+ /**
+ * @param Configuration_Path $configuration
+ */
+ public function setPathConfiguration(Configuration_Path $configuration)
+ {
+ $this->pathConfiguration = $configuration;
+ }
+} \ No newline at end of file
diff --git a/source/Command/VerifyInstallation/LocalFiles.php b/source/Command/VerifyInstallation/LocalFiles.php
new file mode 100644
index 0000000..dafd44a
--- /dev/null
+++ b/source/Command/VerifyInstallation/LocalFiles.php
@@ -0,0 +1,70 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-21
+ */
+
+/**
+ * Class Command_VerifyInstallation_LocalFiles
+ */
+class Command_VerifyInstallation_LocalFiles extends Command_VerifyInstallation_AbstractCommand
+{
+ /**
+ * @throws Exception
+ */
+ public function execute()
+ {
+ $pathToLibDirectory = $this->pathConfiguration->getChatPath() . DIRECTORY_SEPARATOR . 'lib';
+
+ if (!$this->filesystem->isDirectory($pathToLibDirectory)) {
+ throw new Exception(
+ 'directory "lib" is missing, installation needed'
+ );
+ }
+
+ $pathToDataDirectory = $pathToLibDirectory . DIRECTORY_SEPARATOR . 'data';
+
+ if (!$this->filesystem->isDirectory($pathToDataDirectory)) {
+ throw new Exception(
+ 'directory "data" is missing, installation needed'
+ );
+ }
+
+ $identifierToPublicPath = array(
+ 'channels' => $this->pathConfiguration->getChatChannelsFilePath(),
+ 'pathConfiguration' => $this->pathConfiguration->getChatConfigurationFilePath(),
+ 'users' => $this->pathConfiguration->getChatUsersFilePath(),
+ 'version' => $this->pathConfiguration->getChatVersionFilePath()
+ );
+
+ foreach ($identifierToPublicPath as $identifier => $path) {
+ if (!$this->filesystem->isFile($path)) {
+ throw new Exception(
+ 'file "' . $identifier . '" is missing, installation needed'
+ );
+ }
+ }
+
+ $pathToInstallPhp = $this->pathConfiguration->getChatPath() . DIRECTORY_SEPARATOR . 'install.php';
+
+ if ($this->filesystem->isFile($pathToInstallPhp)) {
+ throw new Exception(
+ 'file "' . $pathToInstallPhp . '" still available'
+ );
+ }
+ }
+
+ /**
+ * @return array
+ */
+ public function getUsage()
+ {
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function verify()
+ {
+ }
+} \ No newline at end of file
diff --git a/source/Command/VerifyInstallation/Version.php b/source/Command/VerifyInstallation/Version.php
new file mode 100644
index 0000000..a2f592b
--- /dev/null
+++ b/source/Command/VerifyInstallation/Version.php
@@ -0,0 +1,40 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-21
+ */
+
+/**
+ * Class Command_VerifyInstallation_Version
+ */
+class Command_VerifyInstallation_Version extends Command_VerifyInstallation_AbstractCommand
+{
+ /**
+ * @throws Exception
+ */
+ public function execute()
+ {
+ $exampleVersion = $this->application->getExampleVersion();
+ $currentVersion = $this->application->getCurrentVersion();
+
+ if ($exampleVersion !== $currentVersion) {
+ throw new Exception(
+ 'current version "' . $currentVersion . '" and code version "' . $exampleVersion . '" differs, update needed'
+ );
+ }
+ }
+
+ /**
+ * @return array
+ */
+ public function getUsage()
+ {
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function verify()
+ {
+ }
+} \ No newline at end of file
diff --git a/source/Configuration/Path.php b/source/Configuration/Path.php
new file mode 100644
index 0000000..06917f5
--- /dev/null
+++ b/source/Configuration/Path.php
@@ -0,0 +1,220 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-17
+ */
+
+/**
+ * Class Configuration_Path
+ */
+class Configuration_Path
+{
+ /**
+ * @var string
+ */
+ private $pathToRootDirectory;
+
+ /**
+ * @param string $relativePathToRootDirectory - relative path from Configuration_Path file
+ * @throws Exception
+ */
+ public function __construct($relativePathToRootDirectory)
+ {
+ $this->pathToRootDirectory = realpath(__DIR__ . DIRECTORY_SEPARATOR . $relativePathToRootDirectory);
+
+ if (!is_dir($relativePathToRootDirectory)) {
+ throw new Exception(
+ 'provided root path is not a directory: ' . PHP_EOL .
+ '"' . $this->pathToRootDirectory . '"'
+ );
+ }
+ }
+
+ //begin of path
+ /**
+ * @return string
+ */
+ public function getBackupPath()
+ {
+ return $this->pathToRootDirectory . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'backup';
+ }
+
+ /**
+ * @return string
+ */
+ public function getBackupChannelsFilePath()
+ {
+ return $this->getBackupPath() . DIRECTORY_SEPARATOR . $this->getChannelsFileName();
+ }
+
+ /**
+ * @return string
+ */
+ public function getBackupConfigurationFilePath()
+ {
+ return $this->getBackupPath() . DIRECTORY_SEPARATOR . $this->getConfigurationFileName();
+ }
+
+ /**
+ * @return string
+ */
+ public function getBackupUsersFilePath()
+ {
+ return $this->getBackupPath() . DIRECTORY_SEPARATOR . $this->getUsersFileName();
+ }
+
+ /**
+ * @return string
+ */
+ public function getBackupVersionFilePath()
+ {
+ return $this->getBackupPath() . DIRECTORY_SEPARATOR . $this->getVersionFileName();
+ }
+
+ /**
+ * @return string
+ */
+ public function getExamplePath()
+ {
+ return $this->pathToRootDirectory . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'example';
+ }
+
+ /**
+ * @return string
+ */
+ public function getExampleChannelsFilePath()
+ {
+ return $this->getExamplePath() . DIRECTORY_SEPARATOR . $this->getChannelsFileName();
+ }
+
+ /**
+ * @return string
+ */
+ public function getExampleConfigurationFilePath()
+ {
+ return $this->getChatPath() . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . $this->getConfigurationFileName() . '.example';
+ }
+
+ /**
+ * @return string
+ */
+ public function getExampleUsersFilePath()
+ {
+ return $this->getExamplePath() . DIRECTORY_SEPARATOR . $this->getUsersFileName();
+ }
+
+ /**
+ * @return string
+ */
+ public function getExampleVersionFilePath()
+ {
+ return $this->getExamplePath() . DIRECTORY_SEPARATOR . $this->getVersionFileName();
+ }
+
+ /**
+ * @return string
+ */
+ public function getChatPath()
+ {
+ return $this->pathToRootDirectory . DIRECTORY_SEPARATOR . 'chat';
+ }
+
+ /**
+ * @return string
+ */
+ public function getChatChannelsFilePath()
+ {
+ return $this->getChatPath() . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . $this->getChannelsFileName();
+ }
+
+ /**
+ * @return string
+ */
+ public function getChatClassesFilePath()
+ {
+ return $this->getChatPath() . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . $this->getClassesFileName();
+ }
+
+ /**
+ * @return string
+ */
+ public function getChatConfigurationFilePath()
+ {
+ return $this->getChatPath() . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . $this->getConfigurationFileName();
+ }
+
+ /**
+ * @return string
+ */
+ public function getChatUsersFilePath()
+ {
+ return $this->getChatPath() . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . $this->getUsersFileName();
+ }
+
+ /**
+ * @return string
+ */
+ public function getChatVersionFilePath()
+ {
+ return $this->getChatPath() . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . $this->getVersionFileName();
+ }
+
+ /**
+ * @return string
+ */
+ public function getReleasePath()
+ {
+ return $this->pathToRootDirectory . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'release';
+ }
+
+ /**
+ * @return string
+ */
+ public function getChangeLogFilePath()
+ {
+ return $this->pathToRootDirectory . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'change.log';
+ }
+ //end of path
+
+ //begin of file name
+ /**
+ * @return string
+ */
+ public function getChannelsFileName()
+ {
+ return 'channels.php';
+ }
+
+ /**
+ * @return string
+ */
+ public function getClassesFileName()
+ {
+ return 'classes.php';
+ }
+
+ /**
+ * @return string
+ */
+ public function getConfigurationFileName()
+ {
+ return 'config.php';
+ }
+
+ /**
+ * @return string
+ */
+ public function getUsersFileName()
+ {
+ return 'users.php';
+ }
+
+ /**
+ * @return string
+ */
+ public function getVersionFileName()
+ {
+ return 'version.php';
+ }
+ //end of file name
+} \ No newline at end of file
diff --git a/source/File.php b/source/File.php
new file mode 100644
index 0000000..076592c
--- /dev/null
+++ b/source/File.php
@@ -0,0 +1,122 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-13
+ */
+
+/**
+ * Class File
+ */
+class File
+{
+ /**
+ * @var string
+ */
+ private $path;
+
+ /**
+ * @param null|string $path
+ */
+ public function __construct($path = null)
+ {
+ if (!is_null($path)) {
+ $this->setPath($path);
+ }
+ }
+
+ /**
+ * @param string|array $content
+ * @throws Exception
+ */
+ public function append($content)
+ {
+ if (is_array($content)) {
+ $content = implode(PHP_EOL, $content);
+ } else {
+ $content .= PHP_EOL;
+ }
+
+ $numberOfBytes = file_put_contents($this->getPath(), $content, FILE_APPEND);
+
+ if ($numberOfBytes === false) {
+ throw new Exception(
+ 'can not append content to file "' . $this->getPath() . '"'
+ );
+ }
+ }
+
+ /**
+ * @param string $path
+ * @throws Exception
+ */
+ public function copy($path)
+ {
+ $couldBeCopied = copy($this->getPath(), $path);
+
+ if ($couldBeCopied === false) {
+ throw new Exception(
+ 'could not copy file from path "' . $this->getPath() . '" to "' . $path . '"'
+ );
+ }
+ }
+
+ /**
+ * @return bool
+ * @throws Exception
+ */
+ public function exists()
+ {
+ return (is_file($this->getPath()));
+ }
+
+ /**
+ * @return string
+ * @throws Exception
+ */
+ public function getPath()
+ {
+ if (is_null($this->path)) {
+ throw new Exception(
+ 'no path set'
+ );
+ }
+
+ return $this->path;
+ }
+
+ /**
+ * @return array
+ * @throws Exception
+ */
+ public function read()
+ {
+ return explode("\n", file_get_contents($this->getPath()));
+ }
+
+ /**
+ * @param string $path
+ */
+ public function setPath($path)
+ {
+ $this->path = (string) $path;
+ }
+
+ /**
+ * @param string|array $content
+ * @throws Exception
+ */
+ public function write($content)
+ {
+ if (is_array($content)) {
+ $content = implode("\n", $content);
+ }
+
+ $numberOfBytes = file_put_contents($this->getPath(), $content);
+
+ if ($numberOfBytes === false) {
+ throw new Exception(
+ 'can not append content to file "' . $this->getPath() . '"'
+ );
+ }
+ }
+} \ No newline at end of file
diff --git a/source/Filesystem.php b/source/Filesystem.php
new file mode 100644
index 0000000..2847d25
--- /dev/null
+++ b/source/Filesystem.php
@@ -0,0 +1,203 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-15
+ */
+
+/**
+ * Class Filesystem
+ */
+class Filesystem
+{
+ /**
+ * @param string $source
+ * @param string $target
+ * @throws Exception
+ */
+ public function copy($source, $target)
+ {
+ if (copy($source, $target) === false) {
+ throw new Exception(
+ 'can not copy "' . $source . '" to "' . $target . '"'
+ );
+ }
+ }
+
+ /**
+ * @param string $path
+ * @param int $mode
+ * @param bool $recursive
+ * @throws Exception
+ */
+ public function createDirectory($path, $mode = 0777, $recursive = false)
+ {
+ if (mkdir($path, $mode, $recursive) === false) {
+ throw new Exception(
+ 'can not create directory "' . $path . '"'
+ );
+ }
+ }
+
+ /**
+ * @param string $path
+ * @return File
+ * @throws Exception
+ */
+ public function createFile($path)
+ {
+ if (touch($path) === false) {
+ throw new Exception(
+ 'can not create file "' . $path . '"'
+ );
+ }
+
+ return $this->getFile($path);
+ }
+
+ /**
+ * @param string $path
+ * @throws Exception
+ */
+ public function deleteDirectory($path)
+ {
+ if (rmdir($path) === false) {
+ throw new Exception(
+ 'can not delete directory "' . $path . '"'
+ );
+ }
+ }
+
+ /**
+ * @param string $path
+ * @throws Exception
+ */
+ public function deleteFile($path)
+ {
+ if (unlink($path) === false) {
+ throw new Exception(
+ 'can not unlink "' . $path . '"'
+ );
+ }
+ }
+
+ /**
+ * This method is not bulletproof, it simple checks if $path is a directory
+ * @param string $path
+ * @return File
+ * @throws Exception
+ */
+ public function getFile($path)
+ {
+ if ($this->isDirectory($path)) {
+ throw new Exception(
+ 'provided path "' . $path . '" is a directory'
+ );
+ }
+
+ $file = new File();
+ $file->setPath($path);
+
+ return $file;
+ }
+
+ /**
+ * taken from: https://github.com/stevleibelt/examples/blob/master/php/filesystem/listFilesInDirectory.php
+ * @param string $path
+ * @param array $blackList
+ * @param bool $addPathToName
+ * @return array
+ */
+ public function getDirectories($path, array $blackList = array(), $addPathToName = true)
+ {
+ $blackList = array_merge(
+ $blackList,
+ array(
+ '.',
+ '..'
+ )
+ );
+ $directories = array();
+
+ if (is_dir($path)) {
+ if ($directoryHandle = opendir($path)) {
+ while (false !== ($directory = readdir($directoryHandle))) {
+ if (is_dir($path . DIRECTORY_SEPARATOR . $directory)) {
+ if (!in_array($directory, $blackList)) {
+ if ($addPathToName) {
+ $directories[] = $path . DIRECTORY_SEPARATOR . $directory;
+ } else {
+ $directories[] = $directory;
+ }
+ }
+ }
+ }
+ closedir($directoryHandle);
+ }
+ }
+
+ return $directories;
+ }
+
+ /**
+ * taken from: https://github.com/stevleibelt/examples/blob/master/php/filesystem/listFilesInDirectory.php
+ * @param string $path
+ * @param array $blackList
+ * @param bool $addPathToName
+ * @return array
+ */
+ public function getFiles($path, array $blackList = array(), $addPathToName = true)
+ {
+ $files = array();
+
+ if (is_dir($path)) {
+ if ($directoryHandle = opendir($path)) {
+ while (false !== ($file = readdir($directoryHandle))) {
+ if (is_file($path . DIRECTORY_SEPARATOR . $file)) {
+ if (!in_array($file, $blackList)) {
+ if ($addPathToName) {
+ $files[] = $path . DIRECTORY_SEPARATOR . $file;
+ } else {
+ $files[] = $file;
+ }
+ }
+ }
+ }
+ closedir($directoryHandle);
+ }
+ }
+
+ return $files;
+ }
+
+ /**
+ * @param string $path
+ * @return bool
+ */
+ public function isDirectory($path)
+ {
+ return is_dir($path);
+ }
+
+ /**
+ * @param string $path
+ * @return bool
+ */
+ public function isFile($path)
+ {
+ return is_file($path);
+ }
+
+ /**
+ * @param string $source
+ * @param string $target
+ * @throws Exception
+ */
+ public function move($source, $target)
+ {
+ if (rename($source, $target) === false) {
+ throw new Exception(
+ 'can not move "' . $source . '" to "' . $target . '"'
+ );
+ }
+ }
+} \ No newline at end of file
diff --git a/source/Input.php b/source/Input.php
new file mode 100644
index 0000000..dd4911a
--- /dev/null
+++ b/source/Input.php
@@ -0,0 +1,204 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-20
+ */
+
+/**
+ * Class Input
+ */
+class Input
+{
+ /**
+ * @var array
+ */
+ private $arguments;
+
+ /**
+ * @var array
+ */
+ private $longOptions;
+
+ /**
+ * @var int
+ */
+ private $numberOfArguments;
+
+ /**
+ * @var array
+ */
+ private $parameters;
+
+ /**
+ * @var array
+ */
+ private $shortOptions;
+
+ /**
+ * @var String
+ */
+ private $string;
+
+ /**
+ * @param String $string
+ * @param array $arguments
+ */
+ public function __construct(String $string, array $arguments = array())
+ {
+ $this->longOptions = array();
+ $this->parameters = array();
+ $this->shortOptions = array();
+ $this->string = $string;
+
+ $this->setArguments($arguments);
+ }
+
+ /**
+ * @return array
+ */
+ public function getArguments()
+ {
+ return $this->arguments;
+ }
+
+ /**
+ * @return int
+ */
+ public function getNumberOfArguments()
+ {
+ return $this->numberOfArguments;
+ }
+
+ /**
+ * @param string $name
+ * @param null $default
+ * @return null
+ */
+ public function getParameterValue($name, $default = null)
+ {
+ if ($this->hasParameter($name)) {
+ $value = $this->parameters[$name];
+ } else {
+ $value = $default;
+ }
+
+ return $value;
+ }
+
+ /**
+ * @param string $name
+ * @return bool
+ */
+ public function hasParameter($name)
+ {
+ return (isset($this->parameters[$name]));
+ }
+
+ /**
+ * @param string $name
+ */
+ public function removeParameters($name)
+ {
+ if ($this->hasParameter($name)) {
+ unset($this->parameters[$name]);
+ $this->update();
+ }
+ }
+
+ /**
+ * @param $name
+ * @return bool
+ */
+ public function hasLongOption($name)
+ {
+ return (isset($this->longOptions[$name]));
+ }
+
+ /**
+ * @param $longOrShortName
+ * @return bool
+ */
+ public function hasOption($longOrShortName)
+ {
+ $hasOption = $this->hasLongOption($longOrShortName);
+
+ if (!$hasOption) {
+ $hasOption = $this->hasShortOption($longOrShortName);
+ }
+
+ return $hasOption;
+ }
+
+ /**
+ * @param $name
+ * @return bool
+ */
+ public function hasShortOption($name)
+ {
+ return (isset($this->shortOptions[$name]));
+ }
+
+ /**
+ * @param string $name
+ */
+ public function removeLongOption($name)
+ {
+ if ($this->hasLongOption($name)) {
+ unset($this->longOptions[$name]);
+ $this->update();
+ }
+ }
+
+ /**
+ * @param string $longOrShortName
+ */
+ public function removeOption($longOrShortName)
+ {
+ if ($this->hasLongOption($longOrShortName)) {
+ unset($this->longOptions[$longOrShortName]);
+ $this->update();
+ } else if ($this->hasShortOption($longOrShortName)) {
+ unset($this->shortOptions[$longOrShortName]);
+ $this->update();
+ }
+ }
+
+ /**
+ * @param string $name
+ */
+ public function removeShortOption($name)
+ {
+ if ($this->hasShortOption($name)) {
+ unset($this->shortOptions[$name]);
+ $this->update();
+ }
+ }
+
+ /**
+ * @param array $arguments
+ */
+ public function setArguments(array $arguments)
+ {
+ foreach ($arguments as $argument) {
+ if ($this->string->startsWith($argument, '--')) {
+ $this->longOptions[$this->string->cut($argument, 2)] = true;
+ } else if ($this->string->startsWith($argument, '-')) {
+ $this->shortOptions[$this->string->cut($argument, 1)] = true;
+ } else {
+ $parts = explode('=', $argument);
+ if (count($parts) > 1) {
+ $name = array_shift($parts);
+ $this->parameters[$name] = implode('=', $parts);
+ }
+ }
+ }
+
+ $this->update();
+ }
+
+ private function update()
+ {
+ $this->arguments = array_merge($this->parameters, $this->shortOptions, $this->longOptions);
+ $this->numberOfArguments = count($this->arguments);
+ }
+} \ No newline at end of file
diff --git a/source/InputDependentInterface.php b/source/InputDependentInterface.php
new file mode 100644
index 0000000..0d65b0b
--- /dev/null
+++ b/source/InputDependentInterface.php
@@ -0,0 +1,21 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-20
+ */
+
+/**
+ * Interface InputDependentInterface
+ */
+interface InputDependentInterface
+{
+ /**
+ * @return Input
+ */
+ public function getInput();
+
+ /**
+ * @param Input $input
+ */
+ public function setInput(Input $input);
+} \ No newline at end of file
diff --git a/source/Output.php b/source/Output.php
new file mode 100644
index 0000000..f05383a
--- /dev/null
+++ b/source/Output.php
@@ -0,0 +1,57 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-19
+ */
+
+/**
+ * Class Output
+ */
+class Output
+{
+ /**
+ * @var array
+ */
+ private $content;
+
+ /**
+ * @var string
+ */
+ private $indention;
+
+ public function __construct()
+ {
+ $this->content = array();
+ $this->indention = ' ';
+ }
+
+ public function __clone()
+ {
+ $this->content = array();
+ }
+
+ /**
+ * @param string $line
+ * @param int $numberOfIndention
+ */
+ public function addLine($line = '', $numberOfIndention = 0)
+ {
+ $this->content[] = (str_repeat($this->indention, $numberOfIndention)) . $line;
+ }
+
+ /**
+ * @param string $indention
+ */
+ public function setIndention($indention)
+ {
+ $this->indention = (string) $indention;
+ }
+
+ /**
+ * @return array
+ */
+ public function toArray()
+ {
+ return $this->content;
+ }
+} \ No newline at end of file
diff --git a/source/OutputDependentInterface.php b/source/OutputDependentInterface.php
new file mode 100644
index 0000000..29d4fe3
--- /dev/null
+++ b/source/OutputDependentInterface.php
@@ -0,0 +1,21 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-19
+ */
+
+/**
+ * Interface OutputDependentInterface
+ */
+interface OutputDependentInterface
+{
+ /**
+ * @return null|Output
+ */
+ public function getOutput();
+
+ /**
+ * @param Output $output
+ */
+ public function setOutput(Output $output);
+} \ No newline at end of file
diff --git a/source/String.php b/source/String.php
new file mode 100644
index 0000000..64cc541
--- /dev/null
+++ b/source/String.php
@@ -0,0 +1,38 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-13
+ */
+
+/**
+ * Class String
+ */
+class String
+{
+ /**
+ * @param string $string
+ * @param string $prefix
+ * @return bool
+ */
+ public function startsWith($string, $prefix)
+ {
+ return (strncmp($string, $prefix, strlen($prefix)) === 0);
+ }
+
+ /**
+ * @param string $string
+ * @param int $start
+ * @param null|int $length
+ * @return string
+ */
+ public function cut($string, $start = 0, $length = 0)
+ {
+ if (($length === 0)) {
+ $part = substr($string, $start);
+ } else {
+ $part = substr($string, $start, $length);
+ }
+
+ return $part;
+ }
+} \ No newline at end of file