summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore7
-rw-r--r--autoLoader.php42
-rw-r--r--bin/backup.php34
-rw-r--r--bin/channel.php34
-rw-r--r--bin/install.php48
-rw-r--r--bin/restore.php34
-rw-r--r--bin/upgrade.php34
-rw-r--r--bin/user.php34
-rw-r--r--bin/verify_installation.php29
-rw-r--r--chat/index.php2
-rw-r--r--data/change.log0
-rw-r--r--data/example/channels.php15
-rw-r--r--data/example/users.php40
-rw-r--r--data/example/version.php7
-rw-r--r--data/release/README.md6
-rw-r--r--data/release/upcoming/yymmdd_hhiiss_developer_short-description.php.example9
-rw-r--r--readme.md10
-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
51 files changed, 4017 insertions, 4 deletions
diff --git a/.gitignore b/.gitignore
index 0e424e9..3b9d685 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,7 @@
/chat/lib/config.php
-/nbproject/* \ No newline at end of file
+/chat/lib/data/channels.php
+/chat/lib/data/users.php
+/chat/lib/data/version.php
+/data/backup/*
+/nbproject/*
+.idea
diff --git a/autoLoader.php b/autoLoader.php
new file mode 100644
index 0000000..a7b54d5
--- /dev/null
+++ b/autoLoader.php
@@ -0,0 +1,42 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-13
+ */
+
+if (function_exists('spl_autoload_register')) {
+ //own autoloader - since support is from php 5 up, no namespaces are available so back to pear style
+ function classLoader($className) {
+ $classNameAsPath = str_replace('_', DIRECTORY_SEPARATOR, $className);
+
+ //keep the most important file path on top
+ $directories = array(
+ __DIR__ . DIRECTORY_SEPARATOR . 'chat' . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'class',
+ __DIR__ . DIRECTORY_SEPARATOR . 'source'
+ );
+ $isLoaded = false;
+ $filePath = '';
+
+ foreach ($directories as $directory) {
+ $filePath = $directory . DIRECTORY_SEPARATOR . $classNameAsPath . '.php';
+
+ if (is_file($filePath)) {
+ require_once $filePath;
+ $isLoaded = true;
+ break;
+ }
+ }
+
+ if (!$isLoaded) {
+ throw new Exception(
+ 'can not load class "' . $className . '"' . PHP_EOL .
+ 'last try with path "' . $filePath . '"'
+ );
+ }
+ }
+ spl_autoload_register('classLoader');
+} else {
+ throw new Exception(
+ 'spl_autoload_register function is missing but needed'
+ );
+}
diff --git a/bin/backup.php b/bin/backup.php
new file mode 100644
index 0000000..8a85a72
--- /dev/null
+++ b/bin/backup.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-14
+ */
+
+try {
+ require_once __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'autoLoader.php';
+
+ $application = new Application_Cli();
+
+ $verifyInstallation = $application->getVerifyInstallationCommand();
+ $verifyInstallation->verify();
+ $verifyInstallation->execute();
+
+ $command = $application->getBackupCommand();
+ try {
+ $command->verify();
+ } catch (Exception $exception) {
+ throw new Exception(implode("\n", $command->getUsage()));
+ }
+ $command->execute();
+
+ $command->getOutput()->addLine('done');
+
+ foreach ($command->getOutput()->toArray() as $line) {
+ echo $line . PHP_EOL;
+ }
+} catch (Exception $exception) {
+ echo 'error occurred' . PHP_EOL;
+ echo '----------------' . PHP_EOL;
+ echo 'Usage:' . PHP_EOL . basename(__FILE__) . ' ' . $exception->getMessage() . PHP_EOL;
+ exit(1);
+} \ No newline at end of file
diff --git a/bin/channel.php b/bin/channel.php
new file mode 100644
index 0000000..b51b753
--- /dev/null
+++ b/bin/channel.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-14
+ */
+
+try {
+ require_once __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'autoLoader.php';
+
+ $application = new Application_Cli();
+
+ $verifyInstallation = $application->getVerifyInstallationCommand();
+ $verifyInstallation->verify();
+ $verifyInstallation->execute();
+
+ $command = $application->getChannelCommand();
+ try {
+ $command->verify();
+ } catch (Exception $exception) {
+ throw new Exception(implode("\n", $command->getUsage()));
+ }
+ $command->execute();
+
+ $command->getOutput()->addLine('done');
+
+ foreach ($command->getOutput()->toArray() as $line) {
+ echo $line . PHP_EOL;
+ }
+} catch (Exception $exception) {
+ echo 'error occurred' . PHP_EOL;
+ echo '----------------' . PHP_EOL;
+ echo 'Usage:' . PHP_EOL . basename(__FILE__) . ' ' . $exception->getMessage() . PHP_EOL;
+ exit(1);
+} \ No newline at end of file
diff --git a/bin/install.php b/bin/install.php
new file mode 100644
index 0000000..a312b63
--- /dev/null
+++ b/bin/install.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-14
+ */
+
+try {
+ require_once __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'autoLoader.php';
+
+ $application = new Application_Cli();
+ $isInstalled = true;
+
+ try {
+ $verifyInstallation = $application->getVerifyInstallationCommand();
+ $verifyInstallation->verify();
+ $verifyInstallation->execute();
+ } catch (Exception $exception) {
+ $isInstalled = false;
+ }
+
+ if ($isInstalled) {
+ throw new Exception(
+ 'already installed'
+ );
+ }
+
+ $command = $application->getInstallCommand();
+ try {
+ $command->verify();
+ } catch (Exception $exception) {
+ throw new Exception(implode("\n", $command->getUsage()));
+ }
+ $command->execute();
+
+ $command->getOutput()->addLine();
+ $command->getOutput()->addLine('please execute install.php and remove the file afterwards');
+ $command->getOutput()->addLine();
+ $command->getOutput()->addLine('done');
+
+ foreach ($command->getOutput()->toArray() as $line) {
+ echo $line . PHP_EOL;
+ }
+} catch (Exception $exception) {
+ echo 'error occurred' . PHP_EOL;
+ echo '----------------' . PHP_EOL;
+ echo 'Usage:' . PHP_EOL . basename(__FILE__) . ' ' . $exception->getMessage() . PHP_EOL;
+ exit(1);
+} \ No newline at end of file
diff --git a/bin/restore.php b/bin/restore.php
new file mode 100644
index 0000000..28b5032
--- /dev/null
+++ b/bin/restore.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-14
+ */
+
+try {
+ require_once __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'autoLoader.php';
+
+ $application = new Application_Cli();
+
+ $verifyInstallation = $application->getVerifyInstallationCommand();
+ $verifyInstallation->verify();
+ $verifyInstallation->execute();
+
+ $command = $application->getRestoreCommand();
+ try {
+ $command->verify();
+ } catch (Exception $exception) {
+ throw new Exception(implode("\n", $command->getUsage()));
+ }
+ $command->execute();
+
+ $command->getOutput()->addLine('done');
+
+ foreach ($command->getOutput()->toArray() as $line) {
+ echo $line . PHP_EOL;
+ }
+} catch (Exception $exception) {
+ echo 'error occurred' . PHP_EOL;
+ echo '----------------' . PHP_EOL;
+ echo 'Usage:' . PHP_EOL . basename(__FILE__) . ' ' . $exception->getMessage() . PHP_EOL;
+ exit(1);
+} \ No newline at end of file
diff --git a/bin/upgrade.php b/bin/upgrade.php
new file mode 100644
index 0000000..a6a4a57
--- /dev/null
+++ b/bin/upgrade.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-14
+ */
+
+try {
+ require_once __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'autoLoader.php';
+
+ $application = new Application_Cli();
+
+ $verifyInstallation = $application->getVerifyInstallationLocalFilesCommand();
+ $verifyInstallation->verify();
+ $verifyInstallation->execute();
+
+ $command = $application->getUpgradeCommand();
+ try {
+ $command->verify();
+ } catch (Exception $exception) {
+ throw new Exception(implode("\n", $command->getUsage()));
+ }
+ $command->execute();
+
+ $command->getOutput()->addLine('done');
+
+ foreach ($command->getOutput()->toArray() as $line) {
+ echo $line . PHP_EOL;
+ }
+} catch (Exception $exception) {
+ echo 'error occurred' . PHP_EOL;
+ echo '----------------' . PHP_EOL;
+ echo 'Usage:' . PHP_EOL . basename(__FILE__) . ' ' . $exception->getMessage() . PHP_EOL;
+ exit(1);
+}
diff --git a/bin/user.php b/bin/user.php
new file mode 100644
index 0000000..5e1b78a
--- /dev/null
+++ b/bin/user.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-12
+ */
+
+try {
+ require_once __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'autoLoader.php';
+
+ $application = new Application_Cli();
+
+ $verifyInstallation = $application->getVerifyInstallationCommand();
+ $verifyInstallation->verify();
+ $verifyInstallation->execute();
+
+ $command = $application->getUserCommand();
+ try {
+ $command->verify();
+ } catch (Exception $exception) {
+ throw new Exception(implode("\n", $command->getUsage()));
+ }
+ $command->execute();
+
+ $command->getOutput()->addLine('done');
+
+ foreach ($command->getOutput()->toArray() as $line) {
+ echo $line . PHP_EOL;
+ }
+} catch (Exception $exception) {
+ echo 'error occurred' . PHP_EOL;
+ echo '----------------' . PHP_EOL;
+ echo 'Usage:' . PHP_EOL . basename(__FILE__) . ' ' . $exception->getMessage() . PHP_EOL;
+ exit(1);
+} \ No newline at end of file
diff --git a/bin/verify_installation.php b/bin/verify_installation.php
new file mode 100644
index 0000000..d724169
--- /dev/null
+++ b/bin/verify_installation.php
@@ -0,0 +1,29 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-17
+ */
+
+try {
+ require_once __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'autoLoader.php';
+
+ $application = new Application_Cli();
+ $command = $application->getVerifyInstallationCommand();
+ try {
+ $command->verify();
+ } catch (Exception $exception) {
+ throw new Exception(implode("\n", $command->getUsage()));
+ }
+ $command->execute();
+
+ $command->getOutput()->addLine('installation is valid');
+
+ foreach ($command->getOutput()->toArray() as $line) {
+ echo $line . PHP_EOL;
+ }
+} catch (Exception $exception) {
+ echo 'error occurred' . PHP_EOL;
+ echo '----------------' . PHP_EOL;
+ echo 'Usage:' . PHP_EOL . basename(__FILE__) . ' ' . $exception->getMessage() . PHP_EOL;
+ exit(1);
+} \ No newline at end of file
diff --git a/chat/index.php b/chat/index.php
index d411a86..5546318 100644
--- a/chat/index.php
+++ b/chat/index.php
@@ -21,4 +21,4 @@ require(AJAX_CHAT_PATH.'lib/custom.php');
require(AJAX_CHAT_PATH.'lib/classes.php');
// Initialize the chat:
-$ajaxChat = new CustomAJAXChat();
+$ajaxChat = new CustomAJAXChat(); \ No newline at end of file
diff --git a/data/change.log b/data/change.log
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/data/change.log
diff --git a/data/example/channels.php b/data/example/channels.php
new file mode 100644
index 0000000..13a6b6a
--- /dev/null
+++ b/data/example/channels.php
@@ -0,0 +1,15 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// List containing the custom channels:
+$channels = array();
+
+// Sample channel list:
+$channels[0] = 'Public';
+$channels[1] = 'Private';
diff --git a/data/example/users.php b/data/example/users.php
new file mode 100644
index 0000000..564f36c
--- /dev/null
+++ b/data/example/users.php
@@ -0,0 +1,40 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// List containing the registered chat users:
+$users = array();
+/*
+ // Sample admin user:
+ $users[1] = array();
+ $users[1]['userRole'] = AJAX_CHAT_ADMIN;
+ $users[1]['userName'] = 'admin';
+ $users[1]['password'] = 'admin';
+ $users[1]['channels'] = array(0,1);
+
+ // Sample moderator user:
+ $users[2] = array();
+ $users[2]['userRole'] = AJAX_CHAT_MODERATOR;
+ $users[2]['userName'] = 'moderator';
+ $users[2]['password'] = 'moderator';
+ $users[2]['channels'] = array(0,1);
+
+ // Sample registered user:
+ $users[3] = array();
+ $users[3]['userRole'] = AJAX_CHAT_USER;
+ $users[3]['userName'] = 'user';
+ $users[3]['password'] = 'user';
+ $users[3]['channels'] = array(0,1);
+*/
+
+// Default guest user (don't delete this one):
+$users[0] = array();
+$users[0]['userRole'] = AJAX_CHAT_GUEST;
+$users[0]['userName'] = null;
+$users[0]['password'] = null;
+$users[0]['channels'] = array(0);
diff --git a/data/example/version.php b/data/example/version.php
new file mode 100644
index 0000000..e71f22b
--- /dev/null
+++ b/data/example/version.php
@@ -0,0 +1,7 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-14
+ */
+
+return '0.8.7'; \ No newline at end of file
diff --git a/data/release/README.md b/data/release/README.md
new file mode 100644
index 0000000..a47b973
--- /dev/null
+++ b/data/release/README.md
@@ -0,0 +1,6 @@
+# Release Directory Content
+
+The main idea is to group "upgrade todos" per version directories.
+
+The files inside each directory have to include independent steps.
+"The sky is the limit" (but don't break the sky). As seen in the example file, you have access to the application and therefor access to everything you probably need.
diff --git a/data/release/upcoming/yymmdd_hhiiss_developer_short-description.php.example b/data/release/upcoming/yymmdd_hhiiss_developer_short-description.php.example
new file mode 100644
index 0000000..bd2b81b
--- /dev/null
+++ b/data/release/upcoming/yymmdd_hhiiss_developer_short-description.php.example
@@ -0,0 +1,9 @@
+<?php
+/**
+ * @author stev leibelt <artodeto@bazzline.net>
+ * @since 2014-08-20
+ */
+
+/** @var AbstractApplication $application */
+$application = $this->application;
+$this->output->addLine(__FILE__);
diff --git a/readme.md b/readme.md
index 931d8b8..7818cfe 100644
--- a/readme.md
+++ b/readme.md
@@ -63,8 +63,14 @@ Features
- Well commented Source Code
- Developed with Security as integral part - built to prevent Code injections, SQL injections, Cross-site scripting (XSS), Session stealing and other attacks
- Tested successfully with Microsoft Internet Explorer, Mozilla Firefox, Opera and Safari - built to work with all modern browsers :)
-
-
+- Command Line Utilities to:
+ - backup system
+ - install system
+ - restore system
+ - update system (this is done by introducing a "version" file)
+ - add, edit, delete and list existing channels
+ - add, edit, delete and list existing users
+ - verify existing installation
Help
----
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