├── .gitignore ├── .htaccess ├── README.md ├── application ├── controller │ ├── Debug.php │ ├── Doc.php │ ├── Home.php │ └── index.html ├── index.html ├── model │ └── index.html └── view │ ├── 401.php │ ├── 404.php │ ├── docs │ └── index.php │ ├── home │ └── index.php │ └── index.html ├── cli ├── fmvc ├── index.html ├── lib │ ├── Environment.php │ └── Filegen.php └── templates │ ├── controller.txt │ ├── model.txt │ └── view.txt ├── composer.json ├── config ├── config_template.php ├── development.php ├── environment.php ├── index.html └── testing.php ├── core ├── bootstrap.php ├── data │ ├── PdoConn.php │ └── index.html ├── functions │ ├── global_functions.php │ └── index.html ├── helper │ ├── Documentation.php │ ├── Escape.php │ ├── Filter.php │ ├── HtmlHead.php │ ├── Logger.php │ ├── RestApiCaller.php │ └── index.html ├── index.html ├── lib │ ├── Config.php │ ├── Controller.php │ ├── Input.php │ └── index.html └── routes.php ├── data ├── index.html └── sqlite │ ├── index.html │ └── unit_test.db ├── docs ├── command_line.md ├── controllers.md ├── databases.md ├── debugging.md ├── html_head_generator.md ├── index.html ├── input_filtering.md ├── logger.md ├── models.md ├── multiple_environments.md ├── views.md └── windows_authentication.md ├── humans.txt ├── index.php ├── license.txt ├── tests ├── README.md ├── api_test │ ├── delete.php │ ├── get.php │ ├── post-json.php │ ├── post-xml.php │ ├── post.php │ └── put.php ├── cli │ ├── CliEnvironmentTest.php │ └── CliFilegenTest.php ├── core │ ├── ConfigTest.php │ ├── ControllerTest.php │ ├── DocumentationTest.php │ ├── FilterTest.php │ ├── HtmlHeadTest.php │ ├── InputTest.php │ ├── LoggerTest.php │ ├── PdoConnTest.php │ └── RestApiCallerTest.php └── index.html ├── version.txt └── web ├── css ├── .htaccess ├── docs.css └── index.html ├── img ├── .htaccess └── index.html ├── index.php └── scripts ├── .htaccess └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | # PACKAGES # 2 | *.phar 3 | *.lock 4 | *.com 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | 10 | # OS Files # 11 | .DS_Store 12 | .DS_Store? 13 | ._* 14 | .Spotlight-V100 15 | .Trashes 16 | ehthumbs.db 17 | Thumbs.db 18 | .idea/* 19 | 20 | # LOGS / DATABASES # 21 | *.sqlite 22 | *.log 23 | error_log/* 24 | temp/* 25 | 26 | # APP SPECIFIC # 27 | web/scripts/jquery/* 28 | libraries/* 29 | cgi-bin/* 30 | build.xml 31 | tests/temp/* 32 | tests/coverage/* 33 | web.config 34 | php.ini -------------------------------------------------------------------------------- /.htaccess: -------------------------------------------------------------------------------- 1 | RewriteEngine On 2 | RewriteCond %{REQUEST_FILENAME} !-f 3 | RewriteCond %{REQUEST_FILENAME} !-d 4 | RewriteRule ^(.*)$ index.php [QSA,L] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #Flight MVC 2 | 3 | ## Description 4 | This is my take on a simple extension to implement a more 'classic' MVC pattern that runs on top of the Flight micro-framework. Flight is a great, lightweight framework for PHP. I happen to find it a little easier to work in a more traditional MVC type of structure. This extension of Flight establishes that structure and also adds in a few features like: 5 | 6 | * a PDO wrapper 7 | * a Router to read the controller, command, and 2 parameters 8 | * multiple environments and config files 9 | * a debugger function 10 | * a logger 11 | * an HTML head section builder 12 | * a input filter class (static methods) 13 | 14 | ##Installation 15 | Clone or download this repository and then run Composer's update feature to install dependencies (like Flight!). You can modify the `composer.json` files section on `require-dev` to get rid of or add development libraries like Phing, Codesniffer, phpUnit, etc. 16 | 17 | ## Unit testing 18 | All of the classes in this mod are unit tested with phpUnit, you will find the tests in the /tests directory 19 | 20 | ## Documentation 21 | Documentation for Flight is at: [http://flightphp.com] 22 | 23 | All extension documentation is in the Docs folder. You can also view the documentation using the `doc` controller (e.g. `http://example.com/doc`) 24 | 25 | ## Contributing 26 | Fork this repository and send a pull request. Please stick to issues on the issue tracker or to-do's in the individual files as my intent is to keep this repo as lightweight as possible, and I do not intend to make it a full featured extension of the Flight framework. If you have an idea for a feature, submit it to the issue tracker and let's talk it out before you start coding. I have some ideas too, but some may end up as different extensions rather than features in this extension of Flight. Remember, it is a 'micro-framework' after all. 27 | 28 | ###Conventions 29 | This extension follows PSR-1, PSR-2, and PSR-4 conventions for autoloading, structure, and style. All contributions should follow these conventions. I recommend checking with Codesniffer to be sure. 30 | 31 | ##Thanks/Credits 32 | * Mike Cao: developer of the Flight micro-framework [http://flightphp.com] 33 | * Emanuil Rusev: for the Parsedown Library that runs the doc viewer [http://erusev.com] 34 | -------------------------------------------------------------------------------- /application/controller/Debug.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright 2013 9 | * @license /license.txt 10 | */ 11 | namespace fmvc\application\controller; 12 | 13 | class Debug extends \fmvc\core\lib\Controller 14 | { 15 | public function __construct($deps, $params) 16 | { 17 | parent::__construct($deps, $params); 18 | } 19 | 20 | /** 21 | * Not used, show 404 error 22 | */ 23 | public function index() 24 | { 25 | 26 | \Flight::render('404', array()); 27 | } 28 | 29 | /** 30 | * Show PHP Info, but not in production environment 31 | * DELETE THIS METHOD IF YOU DON'T NEED IT 32 | */ 33 | public function info() 34 | { 35 | echo \Flight::config()->item('environment'); 36 | if (\Flight::config()->item('environment') !== 'production') { 37 | echo phpinfo(); 38 | } else { 39 | echo 'DISABLED'; 40 | } 41 | } 42 | 43 | /** 44 | * Debug dump of the Controller Object (not in production) 45 | * DELETE THIS METHOD IF YOU DON'T NEED IT 46 | */ 47 | public function this() 48 | { 49 | echo "Current Environment: " . \Flight::config()->item('environment') . "
"; 50 | if (\Flight::config()->item('environment') !== 'production') { 51 | echo "

Debug of the current controller object

"; 52 | debug($this); 53 | } else { 54 | echo 'DISABLED'; 55 | } 56 | } 57 | 58 | /** 59 | * Debug dump of the Config Object (not in production) 60 | * DELETE THIS METHOD IF YOU DON'T NEED IT 61 | */ 62 | public function config() 63 | { 64 | echo "Current Environment: " . \Flight::config()->item('environment') . "
"; 65 | if (\Flight::config()->item('environment') !== 'production') { 66 | echo "

Debug of the current configuration object

"; 67 | debug(\Flight::config()->item()); 68 | } else { 69 | echo 'DISABLED'; 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /application/controller/Doc.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright 2014 11 | * @license /license.txt 12 | */ 13 | namespace fmvc\application\controller; 14 | 15 | class Doc extends \fmvc\core\lib\Controller 16 | { 17 | 18 | public function __construct($deps, $params) 19 | { 20 | parent::__construct($deps, $params); 21 | 22 | $this->parser = new \Parsedown(); 23 | $this->doc = new \fmvc\core\helper\Documentation(); 24 | $this->head->style(array('docs')); 25 | $this->head->title('FlightMVC Documentation Viewer'); 26 | } 27 | 28 | public function index() 29 | { 30 | $data = array(); 31 | 32 | $data['html_head'] = $this->head->head(); 33 | $data['filelist'] = $this->doc->getDocumentationFileNames(); 34 | 35 | 36 | if (isset($this->param[0])) { 37 | $data['text'] = $this->doc->parseDocumentationFile($this->param[0].'.md', $this->parser); 38 | } else { 39 | $markdown = file_get_contents('./README.md'); 40 | $data['text'] = $this->parser->text($markdown); 41 | } 42 | 43 | \Flight::render('docs/index', $data); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /application/controller/Home.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright 2014 9 | * @license /license.txt 10 | */ 11 | namespace fmvc\application\controller; 12 | 13 | class Home extends \fmvc\core\lib\Controller 14 | { 15 | /** 16 | * Constructor: Dependencies are picked up from routes.php The default 17 | * Dependencies sent to the controller are Config and Input, which are then 18 | * passed through to the parent constructor 19 | * @param array $deps dependencies 20 | * @param array $params parameters passed via the uri 21 | */ 22 | public function __construct($deps, $params) 23 | { 24 | parent::__construct($deps, $params); 25 | } 26 | 27 | /** 28 | * Main Menu, Home Page 29 | */ 30 | public function index() 31 | { 32 | 33 | \Flight::render('home/index', array('html_head' => $this->head->head())); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /application/controller/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Directory Browsing Prohibited

8 | 9 | -------------------------------------------------------------------------------- /application/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Directory Browsing Prohibited

8 | 9 | -------------------------------------------------------------------------------- /application/model/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Directory Browsing Prohibited

8 | 9 | -------------------------------------------------------------------------------- /application/view/401.php: -------------------------------------------------------------------------------- 1 | 9 | * @copyright 2014 10 | * @license /license.txt 11 | */ 12 | ?> 13 |
14 |

401: User Not Authorized

15 |
16 | -------------------------------------------------------------------------------- /application/view/404.php: -------------------------------------------------------------------------------- 1 | 9 | * @copyright 2014 10 | * @license /license.txt 11 | */ 12 | ?> 13 |
14 |

404: File Not Found

15 |
16 | -------------------------------------------------------------------------------- /application/view/docs/index.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright 2013 11 | * @license /license.txt 12 | */ 13 | ?> 14 | 15 | 16 | 17 | 18 | 19 |
20 |
21 |

Documentation Viewer for the Flight-MVC Extension

22 |
23 |
24 |

Main Menu

25 |
35 | 36 |
37 | 38 |
39 |
40 | 41 | 42 | -------------------------------------------------------------------------------- /application/view/home/index.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright 2014 9 | * @license /license.txt 10 | */ 11 | ?> 12 | 13 | 14 | 15 | 16 |

Welcome to Flight MVC!

17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /application/view/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Directory Browsing Prohibited

8 | 9 | -------------------------------------------------------------------------------- /cli/fmvc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | 13 | * @copyright 2014 14 | * @license /license.txt 15 | */ 16 | 17 | 18 | 19 | //assure running from command line 20 | if (php_sapi_name() !== 'cli') { 21 | die("Error 403: Access Forbidden! \r\n"); 22 | } 23 | 24 | // Get any arguements passed in. 25 | 26 | $args = array(); 27 | $args = $_SERVER['argv']; 28 | 29 | $command = $args[1]; 30 | $param1 = $args[2]; 31 | 32 | 33 | switch ($command) 34 | { 35 | /** 36 | * Command line function for starting/stopping the app 37 | * or also changing the environment (e.g. development, 38 | * testing, etc.) 39 | * 40 | */ 41 | case 'environment': 42 | try { 43 | require_once 'lib/Environment.php'; 44 | $env = new \fmvc\cli\lib\Environment($param1, '../config/environment.php'); 45 | switch ($param1) 46 | { 47 | case 'start': 48 | case 'halt': 49 | $result = $env->toggleHalt(); 50 | break; 51 | 52 | default: 53 | $result= $env->toggleEnvironment(); 54 | break; 55 | } 56 | if ($result === true) { 57 | echo "\r\nSuccess: site is in $param1 mode \r\n"; 58 | } else { 59 | throw new \Exception("ERROR: environment mode not updated! \r\n"); 60 | } 61 | } catch (\Exception $e) { 62 | echo $e->getMessage(); 63 | } 64 | break; 65 | 66 | /** 67 | * Construct a model, view, or controller class file and save it 68 | */ 69 | case 'model': 70 | case 'controller': 71 | case 'view': 72 | try { 73 | require_once 'lib/Filegen.php'; 74 | $mod = new \fmvc\cli\lib\Filegen(); 75 | $applicationPath = "..".DIRECTORY_SEPARATOR."application".DIRECTORY_SEPARATOR.$command.DIRECTORY_SEPARATOR; 76 | $templatePath = ".".DIRECTORY_SEPARATOR."templates".DIRECTORY_SEPARATOR; 77 | $objectName = $param1; 78 | $result = $mod->createObject($command, $objectName, $applicationPath, $templatePath); 79 | if ($result === true) { 80 | echo "New $command created: $objectName\r\n"; 81 | } else { 82 | throw new \Exception('CLI ERROR: File Generation or Creation Error'); 83 | } 84 | } catch (\Exception $e) { 85 | echo $e->getMessage(); 86 | } 87 | 88 | break; 89 | 90 | default: 91 | echo "CLI ERROR: The `$command` command was not found\r\n"; 92 | break; 93 | } 94 | -------------------------------------------------------------------------------- /cli/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Directory Browsing Prohibited

8 | 9 | -------------------------------------------------------------------------------- /cli/lib/Environment.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright 2014 11 | * @license /license.txt 12 | */ 13 | namespace fmvc\cli\lib; 14 | 15 | class Environment 16 | { 17 | public $fileName; 18 | 19 | public $mode; 20 | 21 | public function __construct($mode = null, $filename = null) 22 | { 23 | if (is_null($mode) || is_null($filename)) { 24 | throw new \Exception("Mode and Filename are required. \r\n"); 25 | } else { 26 | $this->mode = $mode; 27 | $this->fileName = $filename; 28 | } 29 | } 30 | 31 | /** 32 | * Changes the mode of the application between 33 | * start and stop depending on the mode given 34 | * @return bool 35 | */ 36 | public function toggleHalt() 37 | { 38 | if ($this->mode === 'halt') { 39 | $string = "mode == 'start') { 41 | $string = "fileName); 46 | $arrFile[0] = $string; 47 | return $this->writeFile(implode($arrFile)); 48 | } 49 | 50 | 51 | /** 52 | * Changes the running environment based on class properties 53 | * @return bool 54 | */ 55 | public function toggleEnvironment() 56 | { 57 | switch ($this->mode) 58 | { 59 | // Turn on the auto-detector 60 | case 'auto': 61 | $string = "define('APP_ENVIRONMENT', null);\r\n"; 62 | break; 63 | 64 | // if it accidentally got here from a start/stop command 65 | case 'start': 66 | case 'halt': 67 | return false; 68 | break; 69 | 70 | // all other cases, set the environment 71 | default: 72 | $string = "define('APP_ENVIRONMENT', '".$this->mode."');\r\n"; 73 | break; 74 | } 75 | $arrFile = file($this->fileName); 76 | $arrFile[24] = $string; 77 | return $this->writeFile(implode($arrFile)); 78 | } 79 | 80 | 81 | /** 82 | * Writes changes out to the environment file 83 | * @param $content 84 | * @return bool 85 | */ 86 | public function writeFile($content) 87 | { 88 | $handle = fopen($this->fileName, "w"); 89 | $result = fwrite($handle, $content); 90 | if ($result !== strlen($content) || $result === 0) { 91 | return false; 92 | } else { 93 | return true; 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /cli/lib/Filegen.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright 2013 11 | * @license /license.txt 12 | */ 13 | namespace fmvc\cli\lib; 14 | 15 | class Filegen 16 | { 17 | /** 18 | * Generates a model, controller, or view from a text file in the 19 | * /cli/templates directory. 20 | * 21 | * @param string $objectType the type of object (model, view, controller) 22 | * @param string $fileName name of the object to be created, will be exploded if it has a `/` 23 | * @param string $path the location where the object will be created 24 | * @param string $templatePath location of templates for objects 25 | * @return bool 26 | * @throws \Exception 27 | * 28 | */ 29 | public function createObject($objectType, $fileName, $path, $templatePath) 30 | { 31 | //Import the contents of the proper text file 32 | $string = file_get_contents("$templatePath$objectType.txt"); 33 | 34 | // if there is a slash, we need to break this into a subdirectory and file 35 | // and also deal with putting the namespace another level down 36 | if (strpos($fileName, '/') !== false) { 37 | $arrParts = explode('/', $fileName); 38 | $object = ucfirst($arrParts[1]); 39 | $namespace = '\\' . strtolower($arrParts[0]); 40 | $objectFile = ucfirst($arrParts[1]) . '.php'; 41 | $path .= strtolower($arrParts[0]); 42 | 43 | // otherwise blank the namespace addon and prep the file and class names 44 | } else { 45 | $object = ucfirst($fileName); 46 | $namespace = ''; 47 | $objectFile = ucfirst($fileName . '.php'); 48 | } 49 | 50 | // We do not want views to have a capital letter in the file name 51 | if ($objectType == 'view') { 52 | $objectFile = strtolower($objectFile); 53 | } 54 | 55 | // replace the variable placeholders in the template with the object values 56 | $string = str_replace('{MODEL_NAME}', $object, $string); 57 | $string = str_replace('{SUBDIR_NAME}', $namespace, $string); 58 | 59 | //check to make sure it doesn't already exist before committing 60 | if (file_exists($path.$objectFile)) { 61 | throw new \Exception("CLI ERROR: $path$objectFile already exists\r\n"); 62 | } else { 63 | return $this->createFile($path, $objectFile, $string); 64 | } 65 | 66 | } 67 | 68 | /** 69 | * Writes out the object file 70 | * 71 | * @param string $path path to the file 72 | * @param string $name the name of the file with extension 73 | * @param string $contents the contents of the file to be written 74 | * @return bool 75 | * @throws \Exception 76 | */ 77 | public function createFile($path, $name, $contents) 78 | { 79 | if (file_exists($path . DIRECTORY_SEPARATOR) === false) { 80 | mkdir($path . DIRECTORY_SEPARATOR, 0755); 81 | } 82 | 83 | if (! is_writeable($path)) { 84 | throw new \Exception('File Could not be written'); 85 | } else { 86 | file_put_contents($path . DIRECTORY_SEPARATOR .$name, $contents."\r\n"); 87 | return true; 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /cli/templates/controller.txt: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | namespace fmvc\application\controller{SUBDIR_NAME}; 14 | 15 | class {MODEL_NAME} extends \fmvc\core\lib\Controller 16 | { 17 | /** 18 | * Constructor: Dependencies are picked up from routes.php The default 19 | * Dependencies sent to the controller are Config and Input, which are then 20 | * passed through to the parent constructor 21 | * @param array $deps dependencies 22 | * @param array $params parameters passed via the uri 23 | */ 24 | public function __construct($deps, $params) 25 | { 26 | parent::__construct($deps, $params); 27 | 28 | } 29 | 30 | public function index() 31 | { 32 | echo 'Welcome to the {MODEL_NAME} controller'; 33 | } 34 | } -------------------------------------------------------------------------------- /cli/templates/model.txt: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | namespace fmvc\application\model{SUBDIR_NAME}; 16 | 17 | class {MODEL_NAME} 18 | { 19 | public function __construct() 20 | { 21 | 22 | } 23 | } -------------------------------------------------------------------------------- /cli/templates/view.txt: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | 15 | 16 |

Now fill it with content!

17 | 18 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "minimum-stability": "dev", 3 | "name": "flight-base-app", 4 | "version": "0.1.0", 5 | "config": { 6 | "vendor-dir": "libraries" 7 | }, 8 | 9 | "require": { 10 | "mikecao/flight": "dev-master", 11 | "erusev/parsedown": "dev-master" 12 | }, 13 | 14 | "require-dev": { 15 | "phing/phing": "2.*", 16 | "squizlabs/php_codesniffer": "2.*", 17 | "phpunit/phpunit": "5.*", 18 | "sebastian/phpcpd": "3.*", 19 | "phpmd/phpmd" : "dev-master" 20 | }, 21 | 22 | "autoload": { 23 | "psr-4": { 24 | "fmvc\\core\\": "core", 25 | "fmvc\\application\\": "application" 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /config/config_template.php: -------------------------------------------------------------------------------- 1 | 11 | * @copyright 2014 12 | * @license /license.txt 13 | */ 14 | //Turn Sessions On or Off 15 | define('SESSIONS_ENABLED', true); 16 | 17 | // DEFAULT SITE TITLE 18 | $config['default_title'] = "Flight-MVC Default Title"; 19 | 20 | // DATABASE CREDENTIALS 21 | $config['db_default']['driver'] = ''; //mysql, sqlsvr, odbc, sqlite, pgsql 22 | $config['db_default']['db_user'] = ''; 23 | $config['db_default']['db_password'] = ''; 24 | 25 | //sqlsrv & ODBC connections 26 | $config['db_default']['dsn'] = ''; //use for odbc & sqlsrv drivers 27 | 28 | //MYSQL & PGSQL specific settings 29 | $config['db_default']['host'] = ''; //use for mysql/pgsql driver 30 | $config['db_default']['port'] = ''; //use for mysql/pgsql driver 31 | $config['db_default']['db_name'] = ''; //use for mysql/pgsql driver 32 | 33 | //SQLite specific settings 34 | $config['db_default']['db_path'] = './data/sqlite'; // required field 35 | $config['db_default']['db_filename'] = ''; 36 | 37 | 38 | 39 | // DATABASE SETTINGS 40 | $config['db_prefix'] = ""; //this is a prefix for table names in the database 41 | 42 | // PATH FOR ERROR LOG 43 | $config['error_log_path'] = 'error_log/'; 44 | 45 | // USE WINDOWS AUTHENTICATION 46 | $config['use_windows_auth'] = false; 47 | $config['auth_domain'] = 'MYDOMAIN\\'; //use this to strip the domain name from a windows user name 48 | -------------------------------------------------------------------------------- /config/development.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright 2014 9 | * @license /license.txt 10 | */ 11 | //Turn Sessions On or Off 12 | define('SESSIONS_ENABLED', false); 13 | 14 | // DEFAULT SITE TITLE 15 | $config['default_title'] = "Flight-MVC Default Title"; 16 | 17 | // DATABASE DRIVER & CREDENTIALS 18 | $config['db_default']['driver'] = 'sqlite'; // mysql, sqlsrv, sqlite, odbc, pgsql 19 | $config['db_default']['db_user'] = ''; 20 | $config['db_default']['db_password'] = ''; 21 | 22 | //SQLSRV & ODBC connections 23 | $config['db_default']['dsn'] = ''; //use for odbc & sqlsrv drivers 24 | 25 | //MYSQL & PGSQL specific settings 26 | $config['db_default']['host'] = ''; //use for mysql/pgsql driver 27 | $config['db_default']['port'] = ''; //use for mysql/pgsql driver 28 | $config['db_default']['db_name'] = ''; //use for mysql/pgsql driver 29 | 30 | //SQLite specific settings (directory and file must be writeable) 31 | $config['db_default']['db_path'] = './data/sqlite'; // required field 32 | $config['db_default']['db_filename'] = 'unit_test.db'; 33 | 34 | // DATABASE TABLE SETTINGS 35 | $config['db_default']['db_prefix'] = ''; 36 | 37 | // PATH FOR ERROR LOG 38 | $config['error_log_path'] = 'error_log/'; 39 | 40 | // USE WINDOWS AUTHENTICATION 41 | $config['use_windows_auth'] = false; 42 | $config['auth_domain'] = 'MYDOMAIN\\'; //use this to strip the domain name from a windows user name -------------------------------------------------------------------------------- /config/environment.php: -------------------------------------------------------------------------------- 1 | 19 | * @copyright 2013 20 | * @license /license.txt 21 | */ 22 | 23 | // Define the running mode if desired 24 | // If set to null, the auto-detector will take over 25 | define('APP_ENVIRONMENT', null); -------------------------------------------------------------------------------- /config/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Directory Browsing Prohibited

8 | 9 | -------------------------------------------------------------------------------- /config/testing.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright 2013 9 | * @license /license.txt 10 | */ 11 | //Turn Sessions On or Off 12 | define('SESSIONS_ENABLED', true); 13 | 14 | // DEFAULT SITE TITLE 15 | $config['default_title'] = "Flight-MVC Default Title"; 16 | 17 | // DATABASE CREDENTIALS 18 | $config['db_default']['driver'] = ''; //mysql, sqlsvr, odbc, sqlite, pgsql 19 | $config['db_default']['db_user'] = ''; 20 | $config['db_default']['db_password'] = ''; 21 | 22 | //sqlsrv & ODBC connections 23 | $config['db_default']['dsn'] = ''; //use for odbc & sqlsrv drivers 24 | 25 | //MYSQL & PGSQL specific settings 26 | $config['db_default']['host'] = ''; //use for mysql/pgsql driver 27 | $config['db_default']['port'] = ''; //use for mysql/pgsql driver 28 | $config['db_default']['db_name'] = ''; //use for mysql/pgsql driver 29 | 30 | 31 | //SQLite specific settings 32 | $config['db_default']['db_path'] = './data/sqlite'; // required field 33 | $config['db_default']['db_filename'] = ''; 34 | 35 | // DATABASE SETTINGS 36 | $config['db_default']['db_prefix'] = ""; //this is a prefix for table names in the database 37 | 38 | // PATH FOR ERROR LOG 39 | $config['error_log_path'] = 'error_log/'; 40 | 41 | // USE WINDOWS AUTHENTICATION 42 | $config['use_windows_auth'] = true; 43 | $config['auth_domain'] = 'MYDOMAIN\\'; //use this to strip the domain name from a windows user name 44 | -------------------------------------------------------------------------------- /core/bootstrap.php: -------------------------------------------------------------------------------- 1 | 12 | * @copyright 2014 13 | * @license /license.txt 14 | */ 15 | // Initialize a PHP Session 16 | if (SESSIONS_ENABLED === true) { 17 | if (session_status() !== PHP_SESSION_ACTIVE) { 18 | session_start(); 19 | } 20 | } 21 | 22 | // Set up the Views Directory 23 | Flight::set('flight.views.path', 'application/view'); 24 | 25 | // Register the Configuration Dependency 26 | Flight::register('config', 'fmvc\core\lib\Config', array($config)); 27 | 28 | // Put the Running Mode into a Config Variable 29 | Flight::config()->set('environment', setEnvironment(APP_ENVIRONMENT)); 30 | 31 | // Register the Superglobals into an accessible container 32 | Flight::register('input', 'fmvc\core\lib\Input', array()); 33 | 34 | // Register the Logger Dependency 35 | Flight::register('log', 'fmvc\core\helper\Logger', array(array('config' => Flight::config()))); 36 | 37 | // Register the HTML Head Dependency 38 | Flight::register('head', 'fmvc\core\helper\HtmlHead', array(array('config' => Flight::config()))); 39 | 40 | // Establish the default database connection 41 | Flight::register('db', 'fmvc\core\data\PdoConn', array(array('config' => Flight::config()))); 42 | 43 | // Initialize Application Routing 44 | require_once 'routes.php'; 45 | -------------------------------------------------------------------------------- /core/data/PdoConn.php: -------------------------------------------------------------------------------- 1 | 9 | * @copyright 2014 10 | * @license /license.txt 11 | * 12 | */ 13 | namespace fmvc\core\data; 14 | 15 | class PdoConn 16 | { 17 | /** 18 | * PDO Connection Object 19 | * @var \PDO object 20 | */ 21 | public $conn; 22 | 23 | /** 24 | * Configuration parameters (Dependency) 25 | * @var Config object 26 | */ 27 | public $config; 28 | 29 | /** 30 | * Configuration for the specific database 31 | * @var 32 | */ 33 | public $dbConfig; 34 | 35 | 36 | 37 | /** 38 | * Constructor, Initializes Dependencies and calls the initialization 39 | * method to establish the PDO data connection 40 | * 41 | * @param array $arrDep 42 | * @param string $dbname 43 | * @throws \Exception 44 | */ 45 | public function __construct(array $arrDep = array(), $dbname = null) 46 | { 47 | if (empty($arrDep)) { 48 | throw new \Exception('Dependency Failure'); 49 | } else { 50 | foreach ($arrDep as $key => $object) { 51 | $this->$key = $object; 52 | } 53 | } 54 | $this->init($dbname); 55 | } 56 | 57 | /** 58 | * Dynamic method handler for basic CRUD functions 59 | * 60 | * Format for dynamic methods names - 61 | * Create: insertTableName($arrData) 62 | * Retrieve: getTableNameByFieldName($value) 63 | * Retrieve all: allTableName() 64 | * Update: updateTableNameByFieldName($value, $arrUpdate) 65 | * Delete: deleteTableNameByFieldName($value) 66 | * Filter (wildcards): filterTableNameByFieldName($value) 67 | * 68 | * @param $method 69 | * @param $params 70 | * @return mixed 71 | */ 72 | public function __call($method, $params) 73 | { 74 | $action = substr($method, 0, 3); 75 | $retVal = null; 76 | switch ($action) 77 | { 78 | // Handler for SELECT Statements that do wildcards with an asterisk 79 | case 'fil': 80 | $arr = explode('By', substr($method, 6)); 81 | $table = $this->camelCaseToUnderscore($arr[0]); 82 | $field = $this->camelCaseToUnderscore($arr[1]); 83 | $where = $params[0]; 84 | $retVal = $this->filter($table, $field, $where); 85 | break; 86 | 87 | // Handler for SELECT Statements 88 | case 'get': 89 | $arr = explode('By', substr($method, 3)); 90 | $table = $this->camelCaseToUnderscore($arr[0]); 91 | $field = $this->camelCaseToUnderscore($arr[1]); 92 | $where = $params[0]; 93 | $retVal = $this->get($table, $field, $where); 94 | break; 95 | 96 | // Handler for SELECT ALL RECORDS 97 | case 'all': 98 | $table = $this->camelCaseToUnderscore(substr($method, 3)); 99 | $retVal = $this->getAll($table); 100 | break; 101 | 102 | // Handler for INSERT Statements 103 | case 'ins': 104 | $table = $this->camelCaseToUnderscore(substr($method, 6)); 105 | $arrInsert = $params[0]; 106 | $retVal = $this->insert($table, $arrInsert); 107 | break; 108 | 109 | // Handler for UPDATE Statements 110 | case 'upd': 111 | $arr = explode('By', substr($method, 6)); 112 | $table = $this->camelCaseToUnderscore($arr[0]); 113 | $where = array($this->camelCaseToUnderscore($arr[1]) => $params[0]); 114 | $set = $params[1]; 115 | $retVal = $this->update($table, $set, $where); 116 | break; 117 | 118 | // Handler for DELETE Statements 119 | case 'del': 120 | $arr = explode('By', substr($method, 6)); 121 | $table = $this->camelCaseToUnderscore($arr[0]); 122 | $field = $this->camelCaseToUnderscore($arr[1]); 123 | $where = $params[0]; 124 | $retVal = $this->delete($table, array($field => $where)); 125 | break; 126 | } 127 | return $retVal; 128 | } 129 | 130 | /** 131 | * Initialize a connection to the datasource via PDO 132 | * Switches the connection string based upon the driver being used 133 | * 134 | * @param string $dbname Name of the database (without `db_`) as specified in the config file 135 | * @return PdoConn 136 | * @throws \Exception 137 | * 138 | * @TODO: Add support for adding a custom db driver / dsn string that is compatible with PDO? 139 | */ 140 | public function init($dbname = null) 141 | { 142 | $dbname = $this->setDbName($dbname); 143 | 144 | // Load the Connection Configuration 145 | $config = $this->config->item($dbname); 146 | 147 | // Put the Connection Info Into a class property 148 | $this->dbConfig = $config; 149 | 150 | // Build the appropriate connection string 151 | $connStr = $this->createConnectionString($config); 152 | 153 | // Establish a PDO connection or terminate application 154 | try { 155 | $this->conn = new \PDO($connStr, $config['db_user'], $config['db_password']); 156 | return $this; 157 | } catch (\PDOException $e) { 158 | throw new \Exception("data connection error: " . $e->getMessage()); 159 | } 160 | } 161 | 162 | /** 163 | * Executes a prepared statement via PDO to return a recordset 164 | * data returned will be as: $array[0]['field_name'] 165 | * This script will replace an asterisk with a % sign to allow 166 | * for wildcard searches. 167 | * 168 | * @param $table 169 | * @param $field 170 | * @param $where 171 | * @param null $sort 172 | * @throws \PDOException 173 | * @return mixed 174 | */ 175 | public function filter($table, $field, $where, $sort = null) 176 | { 177 | $table = $this->dbConfig['db_prefix'] . $table; 178 | 179 | if (! stristr($where, '*')) { 180 | $where .= '%'; 181 | } else { 182 | $where = str_replace('*', '%', $where); 183 | } 184 | $sql = "select * from $table where $field like '$where'"; 185 | if (! is_null($sort)) { 186 | $sql .= " ORDER BY $sort"; 187 | } 188 | 189 | $stmt = $this->conn->prepare($sql); 190 | if ($stmt === false) { 191 | $err = $this->conn->errorInfo(); 192 | throw new \PDOException('Query Failure ['.$err[2].']'); 193 | } else { 194 | $stmt->execute(); 195 | return $stmt->fetchAll(\PDO::FETCH_ASSOC); 196 | } 197 | } 198 | 199 | /** 200 | * Executes a prepared statement via PDO to return a recordset 201 | * data returned will be as: $array[0]['field_name'] 202 | * 203 | * @param $table 204 | * @param $field 205 | * @param $where 206 | * @return mixed 207 | * @throws \PDOException 208 | */ 209 | public function get($table, $field, $where) 210 | { 211 | $table = $this->dbConfig['db_prefix'] . $table; 212 | 213 | $stmt = $this->conn->prepare("select * from $table where $field = ?"); 214 | $stmt->bindParam(1, $where); 215 | 216 | if ($stmt === false) { 217 | $err = $this->conn->errorInfo(); 218 | throw new \PDOException('Query Failure ['.$err[2].']'); 219 | } else { 220 | $stmt->execute(); 221 | return $stmt->fetchAll(\PDO::FETCH_ASSOC); 222 | } 223 | } 224 | 225 | /** 226 | * Executes a prepared statement via PDO to return a recordset 227 | * data returned will be as: $array[0]['field_name'] 228 | * The where clause for this function uses an in statement 229 | * 230 | * @param $table 231 | * @param $field 232 | * @param $where (string containing the in parameters) 233 | * @return mixed 234 | * @throws \PDOException 235 | */ 236 | public function getIn($table, $field, $where) 237 | { 238 | $table = $this->dbConfig['db_prefix'] . $table; 239 | 240 | $stmt = $this->conn->prepare("select * from $table where $field in ($where)"); 241 | if ($stmt === false) { 242 | $err = $this->conn->errorInfo(); 243 | throw new \PDOException('Query Failure ['.$err[2].']'); 244 | } else { 245 | $stmt->execute(); 246 | return $stmt->fetchAll(\PDO::FETCH_ASSOC); 247 | } 248 | } 249 | 250 | /** 251 | * Executes a prepared statement via PDO to return a recordset 252 | * data returned will be as: $array[0]['field_name'] 253 | * This method accepts any valid sql statement 254 | * 255 | * @param $sql 256 | * @return mixed 257 | * @throws \PDOException 258 | */ 259 | public function doSql($sql) 260 | { 261 | $stmt = $this->conn->prepare($sql); 262 | if ($stmt === false) { 263 | $err = $this->conn->errorInfo(); 264 | throw new \PDOException('Query Failure ['.$err[2].']'); 265 | } else { 266 | $stmt->execute(); 267 | return $stmt->fetchAll(\PDO::FETCH_ASSOC); 268 | } 269 | } 270 | 271 | /** 272 | * Executes a prepared statement via PDO to return a recordset 273 | * data returned will be as: $array[0]['field_name'] 274 | * 275 | * @param string $table table name 276 | * @return array 277 | * @throws \PDOException 278 | */ 279 | public function getAll($table) 280 | { 281 | $table = $this->dbConfig['db_prefix'] . $table; 282 | 283 | $stmt = $this->conn->prepare("select * from $table"); 284 | if ($stmt === false) { 285 | $err = $this->conn->errorInfo(); 286 | throw new \PDOException('Query Failure ['.$err[2].']'); 287 | } else { 288 | $stmt->execute(); 289 | return $stmt->fetchAll(\PDO::FETCH_ASSOC); 290 | } 291 | } 292 | /** 293 | * Executes a prepared statement via PDO to update the 294 | * database 295 | * 296 | * @param string $table name of database table 297 | * @param array $set set parameters (field => value) 298 | * @param array $where where parameter (field => value) 299 | * @return int affected rows 300 | * @throws \PDOException 301 | */ 302 | public function update($table, array $set, array $where) 303 | { 304 | $table = $this->dbConfig['db_prefix'] . $table; 305 | 306 | $i=1; 307 | foreach ($set as $fieldName => $value) { 308 | $arrSet[$i] = "$fieldName = ?"; 309 | $param[$i] = $value; 310 | $i++; 311 | } 312 | $strSet = implode(',', $arrSet); 313 | $whereValue = current($where); 314 | 315 | $stmt = $this->conn->prepare('UPDATE '. $table .' SET ' . $strSet . ' WHERE ' . key($where) . ' = ?'); 316 | 317 | foreach ($param as $paramNo => &$value) { 318 | $stmt->bindParam($paramNo, $value); 319 | } 320 | $p = count($param); 321 | $stmt->bindParam($p+1, $whereValue); 322 | 323 | if ($stmt === false) { 324 | $err = $this->conn->errorInfo(); 325 | throw new \PDOException('Query Failure ['.$err[2].']'); 326 | } else { 327 | $stmt->execute(); 328 | return $stmt->rowCount(); 329 | } 330 | } 331 | 332 | /** 333 | * Executes a prepared statement for PDO to insert a record into the database 334 | * @param string $table 335 | * @param array $arrInsert 336 | * @return int affected rows 337 | * @throws \PDOException 338 | */ 339 | public function insert($table, array $arrInsert) 340 | { 341 | $table = $this->dbConfig['db_prefix'] . $table; 342 | 343 | // Build the Fields and Values part of the insert statement 344 | $i=1; 345 | foreach ($arrInsert as $fieldName => $value) { 346 | $fields[] = $fieldName; 347 | $values[$i] = $value; 348 | $param[$i] = '?'; 349 | $i++; 350 | } 351 | $strFields = implode(',', $fields); 352 | $strValues = implode(',', $param); 353 | 354 | // Prepare the sql statement 355 | $stmt = $this->conn->prepare('INSERT INTO '.$table.' ('.$strFields.') VALUES ('.$strValues.')'); 356 | foreach ($values as $paramNo => &$val) { 357 | $stmt->bindParam($paramNo, $val); 358 | } 359 | 360 | // Execute or throw exception on failure 361 | if ($stmt === false) { 362 | $err = $this->conn->errorInfo(); 363 | throw new \PDOException('Query Failure ['.$err[2].']'); 364 | } else { 365 | $stmt->execute(); 366 | return $this->lastInsertId(); 367 | } 368 | } 369 | 370 | 371 | /** 372 | * Execute a prepared statement to delete a record(s) via 373 | * PDO Connection 374 | * 375 | * @param string $table name of table 376 | * @param array $where (field_name => value) 377 | * @return int affected rows 378 | * @throws \PDOException 379 | */ 380 | public function delete($table, array $where) 381 | { 382 | $table = $this->dbConfig['db_prefix'] . $table; 383 | $whereValue = current($where); 384 | 385 | $sql = "DELETE FROM $table WHERE " . key($where) . "= ? "; 386 | $stmt = $this->conn->prepare($sql); 387 | $stmt->bindParam(1, $whereValue); 388 | 389 | if ($stmt === false) { 390 | $err = $this->conn->errorInfo(); 391 | throw new \PDOException('Query Failure ['.$err[2].']'); 392 | } else { 393 | $stmt->execute(); 394 | return $stmt->rowCount(); 395 | } 396 | } 397 | 398 | 399 | /** 400 | * Changes a camelCase table or field name to lowercase, 401 | * underscore spaced name 402 | * 403 | * @param string $string camelCase string 404 | * @return string underscore_space string 405 | */ 406 | public function camelCaseToUnderscore($string) 407 | { 408 | return strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $string)); 409 | } 410 | 411 | /** 412 | * Builds a connection string based on the database configuration 413 | * @param array $config 414 | * @return string 415 | */ 416 | protected function createConnectionString(array $config) 417 | { 418 | // Build the appropriate connection string 419 | switch ($config['driver']) { 420 | 421 | // Connection String for MySQL 422 | case 'mysql': 423 | $connStr = $config['driver'] . ":host=" . $config['host'] . ";dbname=" . $config['db_name']; 424 | if ( $config['port'] !== '') { 425 | $connStr .= ";port=" . $config['port']; 426 | } 427 | break; 428 | 429 | // Connection String for SQL Server 2005 and higher 430 | case 'sqlsrv': 431 | $connStr = $config['driver'] . ":" . $config['dsn']; 432 | break; 433 | 434 | // Connection String for ODBC connections 435 | case 'odbc': 436 | $connStr = $config['driver'] . ":" . $config['dsn'] .";Uid=" . $config['db_user'] 437 | . ";Pwd=" . $config['db_password']; 438 | break; 439 | 440 | // Connection String for SQLite 441 | case 'sqlite': 442 | // Set the user & password to blank if there is no config variable set 443 | if (! isset ($config['db_user'])) { 444 | $config['db_user'] = ''; 445 | $config['db_password'] = ''; 446 | } 447 | $connStr = $config['driver'] . ":" . $config['db_path'] . "/" . $config['db_filename']; 448 | break; 449 | 450 | case 'pgsql': 451 | $connStr = $config['driver'] . ":dbname=" . $config['db_name'] . ";host=" . $config['host']; 452 | if ($config['port'] !== '') { 453 | $connStr .= ";port=" . $config['port']; 454 | } 455 | break; 456 | } 457 | return $connStr; 458 | } 459 | 460 | /** 461 | * Sets the database connection name or default if null 462 | * 463 | * @param null $dbname 464 | * @return string 465 | */ 466 | protected function setDbName($dbname = null) 467 | { 468 | if (is_null($dbname)) { 469 | $strDbName = 'db_default'; 470 | } else { 471 | $strDbName = 'db_' . $dbname; 472 | } 473 | return $strDbName; 474 | } 475 | 476 | /** 477 | * Returns the ID of the last inserted row or sequence value 478 | * 479 | * @param string $param Name of the sequence object from which the ID should be returned. 480 | * @return string representing the row ID of the last row that was inserted into the database. 481 | */ 482 | public function lastInsertId($param = null) 483 | { 484 | return $this->conn->lastInsertId($param); 485 | } 486 | } 487 | -------------------------------------------------------------------------------- /core/data/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Directory Browsing Prohibited

8 | 9 | -------------------------------------------------------------------------------- /core/functions/global_functions.php: -------------------------------------------------------------------------------- 1 | 9 | * @copyright 2014 10 | * @license /license.txt 11 | */ 12 | 13 | if (! function_exists('debug')) { 14 | /** 15 | * Debugger Function: echoes the provided information in an easier 16 | * to read format on screen 17 | * 18 | * @param string $input 19 | */ 20 | function debug($input) 21 | { 22 | echo '
' . print_r($input, true) . '
'; 23 | } 24 | } 25 | 26 | if (! function_exists('setEnvironment')) { 27 | /** 28 | * Manages the running mode of the app. There is an auto-detect feature 29 | * that sets the mode to development if it detects that the server is 30 | * 127.0.0.1, localhost, or the domain is .dev or .local 31 | * 32 | * The auto-detect will go to testing otherwise. It will never automatically 33 | * put the site into production mode. 34 | * 35 | * The auto-detect feature can be overridden by specifying the desired run mode. 36 | * 37 | * @param null $mode 38 | * @return null|string 39 | * 40 | * @TODO: set up a way to put in User defined configurations (servers, etc) 41 | * @TODO: fix the hacky double foreach.... 42 | */ 43 | 44 | function setEnvironment($mode = null) 45 | { 46 | $runMode = 'testing'; 47 | $arrVars = array( 48 | $_SERVER['HTTP_HOST'], 49 | $_SERVER['SERVER_NAME'], 50 | $_SERVER['REMOTE_ADDR'] 51 | ); 52 | 53 | $arrLocal = array( 54 | '127.0.0.1', 55 | '.dev', 56 | '.local', 57 | 'localhost' 58 | ); 59 | 60 | if (is_null($mode)) { 61 | echo array_search($arrLocal, $arrVars); 62 | foreach ($arrVars as $value) { 63 | foreach ($arrLocal as $srchValue) { 64 | if (stristr($value, $srchValue)) { 65 | return 'development'; 66 | } 67 | } 68 | } 69 | 70 | // Set the Environment as specified if a value is passed 71 | } else { 72 | $runMode = $mode; 73 | } 74 | return $runMode; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /core/functions/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Directory Browsing Prohibited

8 | 9 | -------------------------------------------------------------------------------- /core/helper/Documentation.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright 2013 11 | * @license /license.txt 12 | */ 13 | namespace fmvc\core\helper; 14 | 15 | class Documentation 16 | { 17 | 18 | /** 19 | * Name of the Documentation Directory 20 | * @var null|string 21 | */ 22 | public $dirName; 23 | 24 | 25 | public function __construct($dirName = null) 26 | { 27 | if (is_null($dirName)) { 28 | $this->dirName = './docs'; 29 | } else { 30 | $this->dirName = $dirName; 31 | } 32 | } 33 | 34 | /** 35 | * Put the list of files in the directory into an array 36 | * @return array 37 | */ 38 | public function getDocumentationFileNames() 39 | { 40 | $output = array(); 41 | $dirList = scandir($this->dirName); 42 | foreach ($dirList as $file) { 43 | if (stristr($file, '.md')) { 44 | $output[] = $file; 45 | } 46 | } 47 | return $output; 48 | } 49 | 50 | /** 51 | * uses the \Parsedown class to convert markdown to HTML 52 | * 53 | * @param $filename 54 | * @param \Parsedown $parser 55 | * @return string 56 | */ 57 | public function parseDocumentationFile($filename, \Parsedown $parser) 58 | { 59 | $markdown = file_get_contents($this->dirName . '/' . $filename); 60 | return $parser->text($markdown); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /core/helper/Escape.php: -------------------------------------------------------------------------------- 1 | $value) { 35 | $input[$key] = htmlentities(trim($value), ENT_QUOTES); 36 | } 37 | } else { 38 | $input = htmlentities(trim($input), ENT_QUOTES); 39 | } 40 | return $input; 41 | } 42 | 43 | /** 44 | * Decodes strings and arrays that were escaped with the encode 45 | * method above 46 | * 47 | * @param $input 48 | * @return string 49 | */ 50 | public static function decode($input) 51 | { 52 | if (is_array($input)) { 53 | foreach ($input as $key => $value) { 54 | $input[$key] = html_entity_decode($value, ENT_QUOTES); 55 | } 56 | } else { 57 | $input = html_entity_decode(trim($input), ENT_QUOTES); 58 | } 59 | return $input; 60 | } 61 | 62 | 63 | 64 | } -------------------------------------------------------------------------------- /core/helper/Filter.php: -------------------------------------------------------------------------------- 1 | section 5 | * of an HTML file. This allows specifying of CSS and JS files 6 | * from a controller command. 7 | * 8 | * This class is automatically initialized in the bootstrap and is 9 | * preloaded & available in the controller at all times. 10 | * 11 | * Requires the config object as a dependency 12 | * 13 | * @category helper 14 | * @package core 15 | * @author Andrew Podner 16 | * @copyright 2013 17 | * @license /license.txt 18 | * 19 | * @todo: add support for other HTML head elements 20 | * @todo: add an auto-detector to allow a string or an array to be passed to style() and script() methods 21 | */ 22 | namespace fmvc\core\helper; 23 | 24 | class HtmlHead 25 | { 26 | /** 27 | * Configuration Dependency 28 | * @var Config 29 | */ 30 | public $config; 31 | 32 | /** 33 | * Array of script tags 34 | * @var array 35 | */ 36 | public $c_scripts = array(); 37 | 38 | /** 39 | * Array of style tags 40 | * @var array 41 | */ 42 | public $c_styles = array(); 43 | 44 | /** 45 | * Page Title 46 | * @var 47 | */ 48 | public $c_title; 49 | 50 | public function __construct(array $arrDep = array()) 51 | { 52 | // Load Dependencies 53 | if (empty($arrDep)) { 54 | throw new \Exception('Dependency Failure'); 55 | } else { 56 | foreach ($arrDep as $key => $object) { 57 | $this->$key = $object; 58 | } 59 | } 60 | 61 | // Set the default page title 62 | $this->c_title = $this->config->item('default_title'); 63 | } 64 | 65 | /** 66 | * Adds a Javascript File to the Array for the HTML HEAD 67 | * @param array $arrFile 68 | * @return Controller 69 | * @throws \Exception 70 | */ 71 | public function script(array $arrFile = array()) 72 | { 73 | if (empty($arrFile)) { 74 | throw new \Exception('No JavaScript Files Provided'); 75 | } 76 | foreach ($arrFile as $file) { 77 | $script = ''; 78 | $this->c_scripts[] = $script; 79 | } 80 | return $this; 81 | } 82 | 83 | /** 84 | * Adds a CSS File to the Array for the HTML HEAD 85 | * @param array $arrFile 86 | * @return Controller 87 | * @throws \Exception 88 | */ 89 | public function style(array $arrFile = array()) 90 | { 91 | if (empty($arrFile)) { 92 | throw new \Exception('No CSS Files Provided'); 93 | } 94 | foreach ($arrFile as $file) { 95 | $style = ''; 96 | $this->c_styles[] = $style; 97 | } 98 | return $this; 99 | } 100 | 101 | /** 102 | * Changes the Page Title from the default 103 | * @param string $title 104 | * @return Controller 105 | * @throws \Exception 106 | */ 107 | public function title($title = null) 108 | { 109 | if (is_null($title)) { 110 | throw new \Exception('No Title Provided'); 111 | } 112 | $this->c_title = $title; 113 | return $this; 114 | } 115 | 116 | /** 117 | * Returns the HTML HEAD Contents 118 | * @return string 119 | */ 120 | public function head() 121 | { 122 | $head = ''; 123 | if (! empty($this->c_scripts)) { 124 | foreach ($this->c_scripts as $link) { 125 | $head .= $link . ' 126 | '; 127 | } 128 | } 129 | if (! empty($this->c_styles)) { 130 | foreach ($this->c_styles as $link) { 131 | $head .= $link . ' 132 | '; 133 | } 134 | } 135 | $head .= ''.$this->c_title.' 136 | '; 137 | return $head; 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /core/helper/Logger.php: -------------------------------------------------------------------------------- 1 | 17 | * @copyright 2013 18 | * @license /license.txt 19 | * 20 | * @todo: Provide a configurable option to write log to SQLite database 21 | * @todo: Maybe add an API to read the logs into JSON or something like that. 22 | * @todo: Look at adapting this Logger to PSR-3 23 | * 24 | * 25 | */ 26 | namespace fmvc\core\helper; 27 | 28 | class Logger 29 | { 30 | /** 31 | * Configuration Dependency 32 | * @var Config 33 | */ 34 | public $config; 35 | 36 | /** 37 | * Types of logging events, add to this as desired 38 | * @var array 39 | */ 40 | public $levels = array( 41 | 'event', 42 | 'notice', 43 | 'warning', 44 | 'error', 45 | ); 46 | 47 | public function __construct(array $arrDep = array()) 48 | { 49 | if (empty($arrDep)) { 50 | throw new \Exception('Dependency Failure'); 51 | } else { 52 | foreach ($arrDep as $key => $object) { 53 | $this->$key = $object; 54 | } 55 | } 56 | } 57 | 58 | /** 59 | * Dynamic method caller that will allow you to use the log level as 60 | * the method name 61 | * 62 | * e.g. $log->notice($message, $data) 63 | * 64 | * @param string $method name of the method which will map to the event level 65 | * @param array $arrParams 66 | */ 67 | public function __call($method, $arrParams) 68 | { 69 | $this->logEvent($method, $arrParams[0], $arrParams[1]); 70 | } 71 | 72 | /** 73 | * Logs an event and writes it to the appropriate log file 74 | * 75 | * @param null|string $level log level 76 | * @param null|string $message human readable message 77 | * @param null|mixed $data additional data 78 | * @return int|bool number of bytes on success, false on failure 79 | * @throws \Exception 80 | */ 81 | public function logEvent($level = null, $message = null, $data = null) 82 | { 83 | // First 2 parameters are required, so fail if one is missing 84 | if (is_null($level) || is_null($message)) { 85 | throw new \Exception('Level and Log Message are Both Required'); 86 | } else { 87 | 88 | // Make sure this is a valid message level 89 | $this->checkLevelIsValid($level); 90 | 91 | // Compose the Log Message 92 | $logMessage = "----Logged $level: ".date('m-d-Y h:m:sa', time())."----- \n"; 93 | $logMessage .= "Message Content : [$message]\n"; 94 | $logMessage .= "Additional Data : " . $data . "\n"; 95 | 96 | // Open or Create the Log File, named whatever the event level is 97 | $file = $this->config->item('error_log_path').$level.'.txt'; 98 | $fh = @fopen($file, 'a'); 99 | if (! file_exists($file) || ! $fh || ! is_writable($file)) { 100 | // Throw an exception if we cannot get a file handle 101 | throw new \Exception('Log file cannot be opened or created'); 102 | } 103 | 104 | return fwrite($fh, $logMessage); 105 | } 106 | } 107 | 108 | /** 109 | * Check to see if the log level is valid 110 | * 111 | * @param null|string $level 112 | * @throws \Exception 113 | */ 114 | public function checkLevelIsValid($level = null) 115 | { 116 | if (! in_array($level, $this->levels) || is_null($level)) { 117 | throw new \Exception('Log Level is invalid'); 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /core/helper/RestApiCaller.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright 2014 11 | * @license /license.txt 12 | */ 13 | namespace fmvc\core\helper; 14 | 15 | class RestApiCaller 16 | { 17 | 18 | /** 19 | * Simple function to manage a get request. 20 | * 21 | * @param string $url location to make the API call to 22 | * @return string the data returned by the API call 23 | */ 24 | public static function get($url) 25 | { 26 | return file_get_contents($url); 27 | } 28 | 29 | /** 30 | * Helper function that manages post requests via cURL. It 31 | * will accept an associative array or an XML string. 32 | * 33 | * @param string $url Location to make the API call to 34 | * @param mixed $data associative array or XML string 35 | * @param string $dataType `fields`, `json`, or `xml` 36 | * @return boolean true return value of curl_exec() call 37 | * 38 | */ 39 | public static function post($url, $data, $dataType) 40 | { 41 | $curlInput = self::prepareData($data, $dataType); 42 | 43 | $ch = curl_init(); 44 | curl_setopt_array( 45 | $ch, 46 | array( 47 | CURLOPT_URL => $url, 48 | CURLOPT_HEADER => false, 49 | CURLOPT_RETURNTRANSFER => true, 50 | CURLOPT_POST => 1, 51 | CURLOPT_HTTPHEADER => array( 52 | 'Content-Type: ' . $curlInput['type'], 53 | 'Content-Length: ' . strlen($curlInput['data']) 54 | ), 55 | CURLOPT_POSTFIELDS => $curlInput['data'], 56 | ) 57 | ); 58 | $result = curl_exec($ch); 59 | curl_close($ch); 60 | return $result; 61 | } 62 | 63 | /** 64 | * send delete request to API 65 | * @param $url 66 | * @return mixed 67 | */ 68 | public static function delete($url) 69 | { 70 | $ch = curl_init(); 71 | curl_setopt_array( 72 | $ch, 73 | array( 74 | CURLOPT_URL => $url, 75 | CURLOPT_HEADER => false, 76 | CURLOPT_RETURNTRANSFER => true, 77 | CURLOPT_CUSTOMREQUEST => "DELETE", 78 | ) 79 | ); 80 | $result = curl_exec($ch); 81 | curl_close($ch); 82 | return $result; 83 | } 84 | 85 | /** 86 | * Helper function that manages post requests via cURL. It 87 | * will accept an associative array or an XML string. 88 | * 89 | * @param string $url Location to make the API call to 90 | * @param mixed $data associative array or XML string 91 | * @param string $dataType `fields`, `json`, or `xml` 92 | * @return boolean true return value of curl_exec() call 93 | * 94 | */ 95 | public static function put($url, $data, $dataType) 96 | { 97 | $curlInput = self::prepareData($data, $dataType); 98 | 99 | $ch = curl_init(); 100 | curl_setopt_array( 101 | $ch, 102 | array( 103 | CURLOPT_URL => $url, 104 | CURLOPT_RETURNTRANSFER => true, 105 | CURLOPT_CUSTOMREQUEST => "PUT", 106 | CURLOPT_HTTPHEADER => array( 107 | 'Content-Type: ' . $curlInput['type'], 108 | 'Content-Length: ' . strlen($curlInput['data']) 109 | ), 110 | CURLOPT_POSTFIELDS => $curlInput['data'], 111 | ) 112 | ); 113 | $result = curl_exec($ch); 114 | curl_close($ch); 115 | return $result; 116 | } 117 | 118 | /** 119 | * Prepares the data string to go into a PUT or POST 120 | * request 121 | * 122 | * @param mixed $data either an XML string or associative array 123 | * @param string $dataType type of data (`xml`, `json`, `fields`) 124 | * @return array associative array where `data` is the formatted data string and `type` 125 | * is the Content Type string for the HTTP request 126 | * 127 | */ 128 | protected static function prepareData($data, $dataType) 129 | { 130 | switch ($dataType) 131 | { 132 | // accepts an associative array of data (like $_POST from a form) 133 | case 'fields': 134 | $curlData = http_build_query($data); 135 | $contentType = 'application/x-www-form-urlencoded'; 136 | break; 137 | 138 | // expects an associative array and converts to JSON 139 | case 'json': 140 | $curlData = json_encode($data); 141 | $contentType = 'application/json'; 142 | break; 143 | 144 | //expects a properly formatted XML string 145 | case 'xml': 146 | $curlData = $data; 147 | $contentType = 'text/xml'; 148 | break; 149 | } 150 | return array('data' => $curlData, 'type' => $contentType); 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /core/helper/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Directory Browsing Prohibited

8 | 9 | -------------------------------------------------------------------------------- /core/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Directory Browsing Prohibited

8 | 9 | -------------------------------------------------------------------------------- /core/lib/Config.php: -------------------------------------------------------------------------------- 1 | 13 | * @copyright 2014 14 | * @license /license.txt 15 | */ 16 | namespace fmvc\core\lib; 17 | 18 | class Config 19 | { 20 | /** 21 | * Configuration settings 22 | * @var array 23 | */ 24 | public $c_config = array(); 25 | 26 | /** 27 | * Constructor: load configuration into property 28 | * 29 | * @param mixed $config 30 | * @return Config 31 | * @throws \Exception 32 | */ 33 | public function __construct(array $config = null) 34 | { 35 | if (is_null($config)) { 36 | throw new \Exception('No Configuration Variables Found'); 37 | } 38 | $this->c_config = $config; 39 | return $this; 40 | } 41 | 42 | /** 43 | * Retrieve a configuration item. If no item 44 | * name is provided, return all configuration items 45 | * 46 | * @param null|string $arg 47 | * @return mixed 48 | */ 49 | public function item($arg = null) 50 | { 51 | if (is_null($arg)) { 52 | return $this->c_config; 53 | } else { 54 | return $this->c_config[$arg]; 55 | } 56 | } 57 | 58 | /** 59 | * Set a new item for the configuration, used for adding runtime 60 | * configuration properties 61 | * 62 | * @param string $varName 63 | * @param string $value 64 | * @return Config 65 | * @throws \Exception 66 | */ 67 | public function set($varName = null, $value = null) 68 | { 69 | if (is_null($varName) || is_null($value)) { 70 | throw new \Exception('Invalid data passed to configuration set'); 71 | } 72 | $this->c_config[$varName] = $value; 73 | return $this; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /core/lib/Controller.php: -------------------------------------------------------------------------------- 1 | 13 | * @copyright 2014 14 | * @license /license.txt 15 | */ 16 | namespace fmvc\core\lib; 17 | 18 | class Controller 19 | { 20 | /** 21 | * Configuration Dependency 22 | * @var Config 23 | */ 24 | public $config; 25 | 26 | /** 27 | * Input Dependency 28 | * @var Input 29 | */ 30 | public $input; 31 | 32 | /** 33 | * Name of the current class 34 | * @var string 35 | */ 36 | public $class; 37 | 38 | /** 39 | * Base url of the web server 40 | * @var 41 | */ 42 | public $base_server; 43 | 44 | /** 45 | * A message to pass to the UI 46 | * @var string 47 | */ 48 | public $message; 49 | 50 | /** 51 | * Array of the URL Parameters 52 | * @var array 53 | */ 54 | public $param = array(); 55 | 56 | public function __construct(array $arrDep = array(), array $arrParam = array()) 57 | { 58 | // Load Dependencies 59 | if (empty($arrDep)) { 60 | throw new \Exception('Dependency Failure'); 61 | } else { 62 | foreach ($arrDep as $key => $object) { 63 | $this->$key = $object; 64 | } 65 | } 66 | 67 | // Load Parameters into Class Property 68 | if (! empty($arrParam)) { 69 | foreach ($arrParam as $value) { 70 | $this->param[] = $value; 71 | } 72 | } 73 | 74 | if (isset($this->input->server['HTTP_HOST'])) { 75 | $this->base_server = $this->input->server['HTTP_HOST']; 76 | } else { 77 | $this->base_server = $this->input->server['DOCUMENT_ROOT']; 78 | } 79 | 80 | $this->class = $this->setClassName(); 81 | 82 | } 83 | 84 | /** 85 | * Get the name of the current Class 86 | * @return string Class name 87 | */ 88 | protected function setClassName() 89 | { 90 | $class = get_class($this); 91 | $arr = explode('\\', $class); 92 | return end($arr); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /core/lib/Input.php: -------------------------------------------------------------------------------- 1 | 14 | * @copyright 2014 15 | * @license /license.txt 16 | */ 17 | namespace fmvc\core\lib; 18 | 19 | class Input 20 | { 21 | /** 22 | * POST superglobal array 23 | * @var array 24 | */ 25 | public $post = array(); 26 | 27 | /** 28 | * GET superglobal Array 29 | * @var array 30 | */ 31 | public $get = array(); 32 | 33 | /** 34 | * SESSION superglobal array 35 | * @var array 36 | */ 37 | public $session = array(); 38 | 39 | /** 40 | * SERVER superglobal array 41 | * @var array 42 | */ 43 | public $server = array(); 44 | 45 | /** 46 | * COOKIE superglobal array 47 | * @var array 48 | */ 49 | public $cookie = array(); 50 | 51 | /** 52 | * Constructor: initializes the superglobals into 53 | * class properties, loads test data if we are in 54 | * development mode 55 | * 56 | * @return Input 57 | */ 58 | public function __construct() 59 | { 60 | // Initialize the class properties 61 | $this->loadSuperglobals(); 62 | 63 | return $this; 64 | } 65 | 66 | /** 67 | * Put superglobal arrays into class properties 68 | * @return Input 69 | */ 70 | public function loadSuperglobals() 71 | { 72 | if (is_array($_POST)) { 73 | $this->post= array_merge($this->post, $_POST); 74 | } 75 | 76 | if (is_array($_SERVER)) { 77 | $this->server = array_merge($this->server, $_SERVER); 78 | } 79 | 80 | if (is_array($_GET)) { 81 | $this->get = array_merge($this->get, $_GET); 82 | } 83 | 84 | if (is_array($_COOKIE)) { 85 | $this->cookie = array_merge($this->cookie, $_COOKIE); 86 | } 87 | 88 | if (session_status() === PHP_SESSION_ACTIVE) { 89 | $this->session = array_merge($this->session, $_SESSION); 90 | } else { 91 | unset($this->session); 92 | } 93 | 94 | return $this; 95 | } 96 | 97 | /** 98 | * Wrapper for setting a session variable 99 | * @param string $key array key for the session variable 100 | * @param string $value value of the session variable 101 | * @return Input 102 | */ 103 | public function session($key, $value) 104 | { 105 | $_SESSION[$key] = $value; 106 | return $this; 107 | } 108 | 109 | /** 110 | * Wrapper for setting a cookie 111 | * 112 | * @param string $key name of the cookie 113 | * @param string $value value for the cookie 114 | * @param integer $lengthSec life of the cookie (30day default) 115 | * @return mixed cooke 116 | */ 117 | public function cookie($key, $value, $lengthSec = 2592000) 118 | { 119 | return setcookie($key, $value, time()+$lengthSec); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /core/lib/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Directory Browsing Prohibited

8 | 9 | -------------------------------------------------------------------------------- /core/routes.php: -------------------------------------------------------------------------------- 1 | 16 | * @copyright 2014 17 | * @license /license.txt 18 | */ 19 | 20 | // Remap the not found function 21 | Flight::map('notFound', function () { 22 | Flight::render('404.php'); 23 | }); 24 | //Use Windows Authentication to assure that there is 25 | //a legitimate user logged into the browser. App depends on Windows Auth via IIS 26 | //If we find an AUTH_USER in the IE Server Variable, set it as a configuration item 27 | //If not, render a 401 error 28 | 29 | if (Flight::config()->item('use_windows_auth') == true) { 30 | if (!isset(Flight::input()->server['AUTH_USER']) 31 | or is_null(Flight::input()->server['AUTH_USER']) 32 | or Flight::input()->server['AUTH_USER'] == '') { 33 | Flight::render('401.php'); 34 | Flight::stop(); 35 | } else { 36 | $t_user = strtoupper(str_replace(Flight::config()->item('auth_domain'), '', Flight::input()->server['AUTH_USER'])); 37 | Flight::config()->set('auth_user', $t_user); 38 | //process any additional user authentication here (e.g. load your user class 39 | 40 | } 41 | } 42 | 43 | // Set up a route handler for Application Controllers 44 | // Route accepts a controller, command and 2 arguments 45 | Flight::route('(/@controller(/@command(/@arg1(/@arg2))))', function ($controller, $command, $arg1, $arg2) { 46 | // Set `home` as the default controller 47 | if (! isset($controller)) { 48 | $controller = 'home'; 49 | } 50 | 51 | // Set `index` as the default route 52 | if (! isset($command)) { 53 | $command = 'index'; 54 | } 55 | 56 | // Set the controller name and command as config variables 57 | \Flight::config()->set('controller', $controller); 58 | \Flight::config()->set('command', $command); 59 | 60 | // Build a fully qualified controller name 61 | $fqController = 'fmvc\application\controller\\' . ucfirst($controller); 62 | 63 | try { 64 | // Put parameters into array 65 | $arrParam = array($arg1, $arg2); 66 | 67 | // Designate Dependencies to Pass into Controller 68 | // ** Always make the Config and Input classes 69 | // ** available to the controller 70 | $arrDep = array( 71 | 'config' => Flight::config(), 72 | 'input' => Flight::input(), 73 | 'head' => Flight::head() 74 | ); 75 | 76 | // Check for the controller, if it doesn't exist, go to 404 77 | if (! class_exists($fqController)) { 78 | Flight::render('404.php'); 79 | Flight::stop(); 80 | } 81 | 82 | // Load the controller & call the designated method 83 | $ctrl = new $fqController($arrDep, $arrParam); 84 | 85 | // If someone tries to call a private or protected controller method... 86 | $reflection = new \ReflectionMethod($ctrl, $command); 87 | if (! $reflection->isPublic()) { 88 | Flight::render('404.php'); 89 | Flight::stop(); 90 | } 91 | 92 | // Return a 404 error if the command is not valid 93 | if (! method_exists($fqController, $command)) { 94 | Flight::render('404.php'); 95 | } else { 96 | $ctrl->$command(); 97 | } 98 | 99 | } catch (\Exception $e) { 100 | echo $e->getMessage(); 101 | } 102 | }); 103 | 104 | 105 | // Catch all route for undefined routes in case the request 106 | // gets past the router above 107 | Flight::route('*', function () { 108 | Flight::render('404.php'); 109 | }); 110 | -------------------------------------------------------------------------------- /data/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Directory Browsing Prohibited

8 | 9 | -------------------------------------------------------------------------------- /data/sqlite/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Directory Browsing Prohibited

8 | 9 | -------------------------------------------------------------------------------- /data/sqlite/unit_test.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AndrewPodner/flight-MVC/b6c1a9187655ed1040ba2a61876e57c2b79daf80/data/sqlite/unit_test.db -------------------------------------------------------------------------------- /docs/command_line.md: -------------------------------------------------------------------------------- 1 | #Flight-MVC Command Line Interface 2 | Flight-MVC has a command line interface to make some tasks more automated in an effort to speed up development and maintenance. The following functions are available from the command line: 3 | * Start or Halt the site 4 | * Set the environment (development, testing, etc.) 5 | * Create a Model file 6 | * Create a Controller file 7 | * Create a View file 8 | 9 | ##Usage: 10 | Call the command line interface (shown here from the `cli` directory) using: `./fmvc commandName parameter1` 11 | 12 | ##Start/Stop and Environment 13 | The `environment` command can be used to start or halt the site as well as change the environment of the application. 14 | 15 | ####Valid Parameters 16 | * halt: inserts code into the `config\environment.php` file that causes the all code to stop executing 17 | * start: restarts the site by removing the halt code 18 | * auto: puts the environment into auto-detect mode 19 | * : you can pass development, testing, or any other valid environment mode you have specified. 20 | 21 | ####Examples 22 | ``` 23 | //shut down the site 24 | ./fmvc environment halt 25 | 26 | //start the site from a halt 27 | ./fmvc environment start 28 | 29 | //change to development environment 30 | ./fmvc environment development 31 | ``` 32 | 33 | ##Create a model, controller, or view 34 | The command line interface helps to automate the creation of common MVC file to speed up development. From the command line, you can create a new controller, model, or view file that will contain all of the code needed to get each type of object started. 35 | 36 | When creating an object, you can also specify subdirectory (and child namespace for models & controllers) to create the object in. If the subdirectory does not exist, it will be created for you. Additionally, the object generator will also check to see if the file you are trying to create already exists. 37 | 38 | ####Examples: 39 | Create a controller called `Test` in the `application/controller` directory 40 | ``` 41 | ./fmvc controller test 42 | ``` 43 | 44 | Create a controller called `Test` in the `application/controller/sample` directory 45 | ``` 46 | ./fmvc controller sample/test 47 | ``` 48 | 49 | Create a model called `Sample` in the `application/model` directory 50 | ``` 51 | ./fmvc model sample 52 | ``` 53 | 54 | Create a view called main.php in the `view/home` directory 55 | ``` 56 | ./fmvc view home/main 57 | ``` 58 | 59 | -------------------------------------------------------------------------------- /docs/controllers.md: -------------------------------------------------------------------------------- 1 | #Using Controllers 2 | 3 | ##General 4 | * All controller classes must extend the `\core\lib\Controller` class 5 | * example: `class Home extends \core\lib\Controller` 6 | * Controllers should typically be located in the `application\controller\` directory and should also be in that namespace as well 7 | * The name of the controller class must be the same as its filename. 8 | 9 | ##Constructor 10 | The constructor of the controller class must call the parent constructor, as shown below 11 | ``` 12 | public function __construct($deps, $params) 13 | { 14 | parent::__construct($deps, $params); 15 | 16 | } 17 | ``` 18 | 19 | Other code can be added to the constructor (e.g. instantiating a data connection object into a controller class property), but the a call to the parent constructor must be part of the code. 20 | 21 | ##Dependencies 22 | When a controller is called via the URL router, it is automatically loaded with the following dependencies: 23 | * `$this->config`: The current application configuration 24 | * `$this->input` : The object containing superglobals 25 | * `this->head`: The object for managing the HTML head section of a view 26 | 27 | >Note: You can modify how/what the router automatically loads by changing the `/core/routes.php` file around line 52. 28 | 29 | ##Parameters 30 | The router also loads URL parameters into the controller each time it loads. The parameters can be found in the `$this->param` property which is an array. The first parameter is `$param[0]` and the second parameter will be loaded as `$param[1]. 31 | 32 | ####Example 33 | ``` 34 | http://example.com/home/index/foo/bar 35 | 36 | Controller: Home 37 | Command: index() 38 | $param[0] = 'foo' 39 | $param[1] = 'bar' 40 | 41 | ``` 42 | >NOTE: at this time, only 2 parameters are supported. 43 | 44 | ##Commands 45 | Each function (and they need to have public scope) serves a a command in the controller you are working in. For example the URL: `http://example.com/home/index` will call the `index()` function in the `Home` class. Every class should typically have an `index()` command, unless you are certain that this will not be needed. If a URL is specified in a browser which has a controller but no command (e.g. `http://example.com/home`), the app will default to the `index()` command. If there is not one, a 404 error will be displayed. 46 | 47 | ##Working inside a controller command 48 | Within the command, you should be calling data from your models and then rendering it out to a view, or passing it however you want if your application is an API. 49 | 50 | ####Example 51 | ``` 52 | public function viewdata() 53 | { 54 | //Open a connection to the data source 55 | $db = new \core\data\PdoConn(array('config' => \Flight::config())); 56 | 57 | //Get an array of all of the data in the companies table 58 | $rs = $db->getAll('companies'); 59 | 60 | //Use Flight's rendering method to open the `views/home/viewdata.php` 61 | // view and put the data into the $data variable in the view. 62 | \Flight::render('home/viewdata', array('data' => $rs)); 63 | } 64 | ``` 65 | 66 | 67 | -------------------------------------------------------------------------------- /docs/databases.md: -------------------------------------------------------------------------------- 1 | #Working with Databases 2 | 3 | Native support for database connections is managed through a wrapper class for the PDO class. Presently, connections to the following databases are supported in the wrapper. All methods in the wrapper class use prepared statements. 4 | * Mysql 5 | * SQL Server 6 | * ODBC 7 | * Sqlite 8 | * Postgres 9 | 10 | ##Connecting 11 | Connecting to a database is managed via the configuration file. The database configuration resides in a multi-dimensional array where each top level element is the configuration for a data connection (e.g. `$confg['db_default']) 12 | 13 | `db_default` is the fallback connection that will be used if no connection is specified when the `PdoConn` class is instantiated. If a configuration is specified, only the part after the `db_` is passed into the instantiation statement. For instance, if there is a configuration called `$config['db_foo']`, it is called with the following statement: 14 | 15 | ``` 16 | 17 | $foo = new \core\data\PdoConn(array('config' => \Flight::config()), 'foo'); 18 | 19 | ``` 20 | The PDO connection can be directly accessed from the PdoConn object using the `conn` property (e.g. `$foo->conn`) 21 | 22 | The array elements for each type of database vary from platform to platform. The `config/config_template.php` file gives more details as to which elements are needed for each database system. 23 | * Mysql 24 | * driver: 'mysql' 25 | * host 26 | * db_user 27 | * db_password 28 | * db_name 29 | * SQL Server 30 | * driver: 'sqlsrv' 31 | * dsn 32 | * db_user 33 | * db_password 34 | * ODBC 35 | * driver: 'odbc' 36 | * dsn 37 | * db_user 38 | * db_password 39 | * Sqlite 40 | * driver: 'sqlite' 41 | * db_path (if null, `/data/sqlite` is the default path) 42 | * db_filename 43 | * Postgres 44 | * driver: 'pgsql' 45 | * host 46 | * db_user 47 | * db_password 48 | * db_name 49 | 50 | ##Dynamic Methods 51 | 52 | The PdoConn class supports a variety of dynamic method names using the PHP `__call()` magic method. There are 6 database operations supported via dynamic methods. Method names are always in camelCase with the first letter being lowercase (e.g. `getTableByField`). The system converts camelCase to underscores in the database, so your database fields and tables should always be in underscore. 53 | 54 | ####Example 55 | The dynamic method `getCompanyByCompanyName('Example')` would look for an exact match to 'Example' in the `company_name` field of the `company` table. 56 | 57 | >NOTE: you can specify a table prefix in the database configuration, `$config['db_prefix']` such as `ABC_`. If you add a prefix, then the dynamic call to `getCompanyByCompanyName('Example')` would look for the `ABC_company` table. 58 | 59 | * get: This is the basic select method. It accepts 1 parameter, which is the value of the field you are searching. The get method looks for exact matches to whatever parameter is specified. Usage: `$foo->getCompanyByAccountStatus('active')` looks for companies with an account status of active. Results are given in a multidimensional array as follows: `$row[0]['field_name']` 60 | 61 | * filter: This is a select method that accepts and sorts. It accepts 1 parameter, which is the value of the field you are searching. The get method looks for exact matches to whatever parameter is specified. Usage: `$foo->filterCompanyByAccountStatus('act*')` looks for companies with an account status that begins with `act`. Asteriks are used as wildcards. Results are given in a multidimensional array as follows: `$row[0]['field_name']` 62 | 63 | * all: This will retrieve all fields of all rows for the specified table. Usage: `$foo->allCompany()` is the same as saying "SELECT * FROM company"; 64 | 65 | * insert: This mimics the SQL insert method. The parameter is a multidimensional array in the form of `$row[0]['field_name'] = 'value'` Each record to be inserted must have the same number of fields. Any number of fields in the table can be part of the insert statement. It returns the last insert id (return value may not work properly in ODBC). 66 | 67 | * update: This mimics the SQL update method. The parameters are 2 arrays, the first array is a the field names and values in the form `$row['field_name']='value'` and the second is an array for the where clause in the form of `$where['field_name']='value'`. Returns the number of affected rows. 68 | 69 | * delete: Works similar to get. Usage: `$foo->deleteCompanyByStatus('inactive')` will delete all companies with the status 'inactive'. Returns the number of affected rows. 70 | 71 | ##Other methods 72 | The get, filter, update, insert, delete, and getAll methods can also be used without calling a dynamic method name. These methods are all documented in the PDOConn class method comments. 73 | 74 | For more complex queries, it is recommended that the PDO connection be called directly using the `conn` propery (e.g. $foo->conn->prepare()). Dynamic methods are provided to reduce the lines of code needed to execute simple CRUD operations. -------------------------------------------------------------------------------- /docs/debugging.md: -------------------------------------------------------------------------------- 1 | #Debugging 2 | 3 | There is a global function called `debug()` that can be called. It will provide an easily readable view of whatever array / object you are trying to view 4 | 5 | Additionally, there are a few commands in the default `Debug` controller like: 6 | * `this`: shows the debug dump of the Controller object 7 | * `info`: shows `phpinfo() 8 | * `config`: show the debug dump of the config object 9 | 10 | These commands do not work in production mode, but it is highly recommended to delete them from the controller or delete the controller entirely if they are not needed to protect application security. 11 | 12 | -------------------------------------------------------------------------------- /docs/html_head_generator.md: -------------------------------------------------------------------------------- 1 | #Managing the `` section of an HTML page 2 | 3 | The `` section of your HTML pages can be managed with the HTML Head helper class. This class loads automatically when the controller loads. This helper is designed primarily to manage 3 things: 4 | * Including stylesheets (CSS files) 5 | * Including Javascript files 6 | * Manipulating the `` tag of a page. 7 | 8 | Other tags can be written in to the head section of your pages using views and/or layouts, but as stylesheets, scripts, and titles are often dynamic within the application, support for easy manipulation of these is provided via the helper. 9 | 10 | The default title for the application can be set in the configuration file for each running environment using the `$config['default_title']` element of the configuration array. This will be used if the title is not set at runtime. 11 | 12 | ##Usage 13 | The class expects javascript file to be located in the `./web/scripts` directory, or a subdirectory of it. It also expects javascript files to end in the `.js` file extension. Likewise, stylesheets should be located in the `./web/css` directory (or a subdirectory) and end with the `.css` file extension. 14 | 15 | To use the helper, call the `style()` or `script()` methods and pass an array of filenames (no extension) to the method. If you were trying to load a file in subdirectory, your would prefix the filename with the directory name and a `/` character (e.g. `subdir/file`). You can pass multiple array elements to load multiple script or stylesheet files with a single method call. 16 | 17 | To change the page title, call the `title()` method and use a string for whatever title you want to use. 18 | 19 | ####Let's do an example....from a controller command: 20 | ``` 21 | public function index() 22 | { 23 | //add a style sheet 24 | $this->head->style(array('main')); 25 | 26 | //add script files 27 | $this->head->script(array('foojava', 'barjava', 'foobar/java')); 28 | 29 | //change the title 30 | $this->head->title('My title'); 31 | 32 | //Pass the head section as the $head variable to the view via a render call 33 | \Flight::render('home/index', array('html_head' => $this->head->head())); 34 | } 35 | 36 | ``` 37 | 38 | ####In the view.... 39 | ``` 40 | <html> 41 | <head> 42 | <?=$html_head?> 43 | </head> 44 | </html> 45 | 46 | ``` 47 | 48 | ####Will produce..... 49 | ``` 50 | <html> 51 | <head> 52 | <script type="text/javascript" src="./web/scripts/foojava.js"></script> 53 | <script type="text/javascript" src="./web/scripts/barjava.js"></script> 54 | <script type="text/javascript" src="./web/scripts/foobar/java.js"></script> 55 | <link rel="stylesheet" href="./web/css/main.css" /> 56 | <title>My title 57 | 58 | 59 | ``` -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Directory Browsing Prohibited

8 | 9 | -------------------------------------------------------------------------------- /docs/input_filtering.md: -------------------------------------------------------------------------------- 1 | #Input Filtering 2 | 3 | The `core\helper\Filter` class includes several static methods that can be useful for filtering data that comes into the application. Many of the filters are just simple implementations of built in methods like `ctype`, but as filtering in web applications is an ever evolving process, using these static wrapper methods, you can adapt your filtering requirements as time goes on by simply updating the static method code rather than endlessly hunt for filtering logic throughout the application. 4 | 5 | The following filters are built into the class: 6 | * filename: by default, accepts alphanumerics plus periods and underscores 7 | * integer 8 | * numeric 9 | * alphanumeric 10 | * alpha 11 | * email (implements the Email type on filter_var) 12 | * boolean 13 | * pageName: by default accepts alphanumeric plus underscore 14 | * databaseField: by default, accepts alphanumerics plus periods and underscores 15 | * checkDateIsValid: this one needs simplification work, I know, but it is functional for now. I am sure there are better ways 16 | 17 | Usage: 18 | `Filter::numeric($data)` 19 | 20 | Returns `true` or `false` depending on if the data is valid. 21 | 22 | 23 | -------------------------------------------------------------------------------- /docs/logger.md: -------------------------------------------------------------------------------- 1 | #Using the Logger 2 | 3 | The logger is meant to be very simple and intended to implement basic logging functions. The logger class is not loaded by default into the Controller class, and needs to be instantiated. 4 | 5 | ##Configuring 6 | The config object must be passed into the logger. 7 | 8 | The configuration file for each environment contains a `$config['error_log_path']` element which is set to the `error_log/`; directory by default. 9 | 10 | By default, the logger has 4 logging levels: 11 | * event 12 | * notice 13 | * warning 14 | * error 15 | 16 | These levels are setup in the `core/helper/Logger.php` class file in the $foo->levels property of the class. You can modify these logging levels as desired by changing the contents of the array. 17 | 18 | ## Using the logger: 19 | Dynamic methods are used to log events. If you want to log a warning, for example, then you would use the `$foo->warning()` method. The dynamic logger methods accept 2 parameters. The first parameter is the message or description of the log event and the second parameter is any data you want to capture with the log event. 20 | 21 | The logger stores logged events in a text file in the directory that is specified. The name of the file will correspond to the log level like `warning.txt`, `notice.txt`, and so forth. 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /docs/models.md: -------------------------------------------------------------------------------- 1 | #Using Models 2 | 3 | Models are where most of the work should be getting done in your application. This is where the processing takes place and then the results are passed back to the controller and then rendered to a view. 4 | 5 | All models in this extension can pretty well stand on their own and bring in dependencies as needed. The only requirement is adding an appropriate namespace based on the location of the file which at the simplest level will be `application\model`. You can add more subfolders for organization as needed, just be sure to include the appropriate namespace 6 | 7 | You are free to handle your models however you see fit, but the best result will be found in using solid coding practices and observing the concepts of dependency injection, writing testable code, etc. Volumes have been written on these subjects, and you will hopefully find in a study of this extension's code, that every effort was made to develop using these best practices. -------------------------------------------------------------------------------- /docs/multiple_environments.md: -------------------------------------------------------------------------------- 1 | #Mutliple Environments 2 | 3 | Multiple environments are supported through the use of environment specific configuration files, which are stored in the `/config` directory. 4 | 5 | The environment is determined in 2 ways: 6 | * In the `/config/environment.php` file, you can explicitly set the environment by providing a value for the `APP_ENVIRONMENT` constant 7 | * If you leave the `APP_ENVIRONMENT` constant as a null value, then the auto-detector will take over from and try to determine if you are in a development or testing environment. The `$_SERVER` superglobal array elements `HTTP_HOST, SERVER_NAME, SERVER_ADDRESS, and REMOTE_ADDR` will be searched for a match to anything containing: 8 | * 127.0.0.1 9 | * localhost 10 | * any domain ending in *.dev 11 | * any domain ending in *.local 12 | 13 | If a match is found, the environment will be set to `development`. If no match is found, the environment will be set to testing. The auto detect script will not put the application into the production environment under any circumstances, this must be done manually. 14 | 15 | > The superglobal values and the values that trigger a positive response to go into development mode can be adjusted in the `/core/global_functions.php` file. 16 | 17 | Other custom environments like `staging` can be deployed by adding a `staging.php` file in the `/config` directory, but it will be necessary to explicitly set the environment from the `environment.php` file. 18 | -------------------------------------------------------------------------------- /docs/views.md: -------------------------------------------------------------------------------- 1 | #Using Views 2 | 3 | Most of the documentation for views can be found by looking at the documentation for Flight at [http://flightphp.com]. The main thing to understand about how this extension implements views is that the views are simply organized into the `application/views` folder. The bootstrapper sets the default view path to this directory. 4 | 5 | I recommend adding a subfolder for each controller to keep things tidy. 6 | 7 | You can call views in a subfolder as follows: 8 | 9 | ``` 10 | //let's say we want to render the application/views/home/index.php view file. 11 | 12 | \Flight::render('home/index', array()); 13 | 14 | ``` 15 | 16 | Layouts work the same way as views as far as directory and file structure are involved. The Flight documentation explains how layouts/templates are implemented. 17 | -------------------------------------------------------------------------------- /docs/windows_authentication.md: -------------------------------------------------------------------------------- 1 | #Windows Authentication 2 | Flight-MVC has optional Windows authentication built into the router. To enable, 3 | set the configuration variable for using Windows authentication to `true`. 4 | 5 | Note that you will also need to enable Windows Authentication and disable anonymous 6 | authentication in IIS. 7 | 8 | Once you have enabled Windows authentication, you can also enter a domain name (with 9 | a trailing backslash) in the domain config variable to strip the domain name from 10 | the user name if desired. 11 | 12 | To add in more processing when the Windows authentication check takes place, modify 13 | the `core\routes.php` file in the designate area to make it work for you. -------------------------------------------------------------------------------- /humans.txt: -------------------------------------------------------------------------------- 1 | /* TEAM */ 2 | Developer: Andrew Podner 3 | Twitter: @PHPAndy 4 | Location: USA 5 | 6 | /* THANKS */ 7 | Flight Micro Framework: http://flightphp.com 8 | Emanuil Rusev: http://erusev.com (Parsedown library) 9 | 10 | 11 | /* SITE */ 12 | Last update: 2014/07/15 13 | Software: phpStorm -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | NOTE: This license applies only to the code as developed by Andrew Podner. All 24 | other software is licensed as per the license specified by the original developer. -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | ## Unit Testing for Flight-MVC 2 | 3 | All of the code for the MVC extension is tested using phpUnit. For the PdoConn class, there is a `unit_test.db` sqlite database in the `/data/sqlite` subfolder. This database is used for some read/write tests. If you find that the tests are failing, make sure that the directory that the database is in is writeable. 4 | -------------------------------------------------------------------------------- /tests/api_test/delete.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright 2014 9 | * @license /license.txt 10 | */ 11 | if ($_SERVER['REQUEST_METHOD'] == 'DELETE') { 12 | echo 'Working'; 13 | } else { 14 | echo 'ERROR: not a DELETE Request'; 15 | } -------------------------------------------------------------------------------- /tests/api_test/get.php: -------------------------------------------------------------------------------- 1 | Testing Get Call -------------------------------------------------------------------------------- /tests/api_test/post-json.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright 2014 9 | * @license /license.txt 10 | */ 11 | 12 | echo file_get_contents("php://input"); -------------------------------------------------------------------------------- /tests/api_test/post-xml.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright 2014 9 | * @license /license.txt 10 | */ 11 | echo file_get_contents("php://input"); -------------------------------------------------------------------------------- /tests/api_test/post.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright 2014 9 | * @license /license.txt 10 | */ 11 | 12 | echo $_POST['b']; -------------------------------------------------------------------------------- /tests/api_test/put.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright 2014 9 | * @license /license.txt 10 | */ 11 | if ($_SERVER['REQUEST_METHOD'] == 'PUT') { 12 | print_r(getallheaders()); 13 | echo file_get_contents("php://input"); 14 | } else { 15 | echo 'ERROR: not a PUT Request'; 16 | } 17 | -------------------------------------------------------------------------------- /tests/cli/CliEnvironmentTest.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright 2013 9 | * @license /license.txt 10 | */ 11 | 12 | 13 | class CliEnvironmentTest extends PHPUnit_Framework_TestCase 14 | { 15 | public $config; 16 | 17 | public function setUp() 18 | { 19 | require_once '../cli/lib/Environment.php'; 20 | } 21 | 22 | public function tearDown() {} 23 | 24 | /** 25 | * @expectedException Exception 26 | */ 27 | public function testNullConstructor() { 28 | $test = new \fmvc\cli\lib\Environment(); 29 | } 30 | 31 | /** 32 | * @expectedException Exception 33 | */ 34 | public function testNullConstructor2() { 35 | $test = new \fmvc\cli\lib\Environment('test'); 36 | } 37 | 38 | public function testConstructor() 39 | { 40 | $test = new \fmvc\cli\lib\Environment('test', 'file.php'); 41 | $this->assertEquals('test', $test->mode); 42 | $this->assertEquals('file.php', $test->fileName); 43 | } 44 | 45 | public function testWriteFile() 46 | { 47 | $file = 'temp/testwrite.txt'; 48 | if (file_exists($file)) { 49 | unlink($file); 50 | } 51 | $env = new \fmvc\cli\lib\Environment('test', $file); 52 | 53 | file_put_contents($file, 'Test data'); 54 | $this->assertTrue($env->writeFile('my test data')); 55 | 56 | $newData = file_get_contents($file); 57 | $this->assertEquals('my test data', $newData); 58 | unlink($file); 59 | } 60 | 61 | public function testWriteFileFail() 62 | { 63 | $file = 'temp/testwrite.txt'; 64 | if (file_exists($file)) { 65 | unlink($file); 66 | } 67 | file_put_contents($file, 'Test data'); 68 | $env = new \fmvc\cli\lib\Environment('test', $file); 69 | $this->assertFalse($env->writeFile('')); 70 | } 71 | 72 | public function testHalt() 73 | { 74 | $file = 'temp/testwrite.txt'; 75 | if (file_exists($file)) { 76 | unlink($file); 77 | } 78 | file_put_contents($file, 'Test data'); 79 | $env = new \fmvc\cli\lib\Environment('halt', $file); 80 | $this->assertTrue($env->toggleHalt()); 81 | 82 | $data = file_get_contents($file); 83 | $this->assertStringStartsWith("assertFalse($env->toggleHalt()); 95 | } 96 | public function testStart() 97 | { 98 | $file = 'temp/testwrite.txt'; 99 | if (file_exists($file)) { 100 | unlink($file); 101 | } 102 | file_put_contents($file, 'Test data'); 103 | $env = new \fmvc\cli\lib\Environment('start', $file); 104 | $this->assertTrue($env->toggleHalt()); 105 | 106 | $data = file_get_contents($file); 107 | $this->assertEquals("assertTrue($env->toggleEnvironment()); 120 | 121 | $data = file_get_contents($file); 122 | $this->assertEquals("define('APP_ENVIRONMENT', 'development');\r\n", $data); 123 | unlink($file); 124 | } 125 | 126 | public function testToggleEnvironmentFail() 127 | { 128 | $file = 'temp/testwrite.txt'; 129 | if (file_exists($file)) { 130 | unlink($file); 131 | } 132 | $env = new \fmvc\cli\lib\Environment('start', $file); 133 | $this->assertFalse($env->toggleEnvironment()); 134 | } 135 | 136 | public function testAutoDetect() 137 | { 138 | $file = 'temp/testwrite.txt'; 139 | if (file_exists($file)) { 140 | unlink($file); 141 | } 142 | file_put_contents($file, ''); 143 | $env = new \fmvc\cli\lib\Environment('auto', $file); 144 | $this->assertTrue($env->toggleEnvironment()); 145 | 146 | $data = file_get_contents($file); 147 | $this->assertEquals("define('APP_ENVIRONMENT', null);\r\n", $data); 148 | unlink($file); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /tests/cli/CliFilegenTest.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright 2013 9 | * @license /license.txt 10 | */ 11 | class CliFilegenTest extends PHPUnit_Framework_TestCase 12 | { 13 | 14 | public function setUp() 15 | { 16 | require_once '../cli/lib/Filegen.php'; 17 | } 18 | 19 | public function tearDown() 20 | { 21 | if (file_exists('temp/test.php')) unlink('temp/test.php'); 22 | if (file_exists('temp/my')) rmdir('temp/my'); 23 | } 24 | 25 | public function testCreateObject() 26 | { 27 | $fgen = new \fmvc\cli\lib\Filegen(); 28 | $result = $fgen->createObject('controller', 'test', 'temp/', '../cli/templates/'); 29 | $text = file_get_contents('temp/Test.php'); 30 | $test = (stristr($text, 'class Test extends \fmvc\core\lib\Controller') !== false) ? true : false; 31 | $this->assertFileExists('temp/Test.php'); 32 | unlink('temp/Test.php'); 33 | $this->assertTrue($test); 34 | } 35 | 36 | public function testCreateObjectWithSubdir() 37 | { 38 | $fgen = new \fmvc\cli\lib\Filegen(); 39 | $result = $fgen->createObject('controller', 'my/test', 'temp/', '../cli/templates/'); 40 | $text = file_get_contents('temp/my/Test.php'); 41 | $test = (stristr($text, 'class Test extends \fmvc\core\lib\Controller') !== false) ? true : false; 42 | $this->assertFileExists('temp/my/Test.php'); 43 | unlink('temp/my/Test.php'); 44 | rmdir('temp/my'); 45 | $this->assertTrue($test); 46 | } 47 | 48 | public function testCreateView() 49 | { 50 | $fgen = new \fmvc\cli\lib\Filegen(); 51 | $result = $fgen->createObject('view', 'test', 'temp/', '../cli/templates/'); 52 | $text = file_get_contents('temp/test.php'); 53 | $test = (stristr($text, '') !== false) ? true : false; 54 | $this->assertFileExists('temp/test.php'); 55 | unlink('temp/test.php'); 56 | $this->assertTrue($test); 57 | } 58 | 59 | /** 60 | * @expectedException Exception 61 | */ 62 | public function testCreateObjectFailAlreadyExists() 63 | { 64 | file_put_contents('temp/test.php', 'test 123'); 65 | $fgen = new \fmvc\cli\lib\Filegen(); 66 | $result = $fgen->createObject('view', 'test', 'temp/', '../cli/templates/'); 67 | } 68 | 69 | /** 70 | * @expectedException Exception 71 | */ 72 | public function testCreateWriteFileFailure() 73 | { 74 | mkdir('temp/my'); 75 | chmod('temp/my', 0000); 76 | $fgen = new \fmvc\cli\lib\Filegen(); 77 | $result = $fgen->createFile('temp/my', null, null); 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /tests/core/ConfigTest.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright 2013 9 | * @license /license.txt 10 | */ 11 | class ConfigTest extends PHPUnit_Framework_TestCase 12 | { 13 | public $config; 14 | 15 | public function setUp() 16 | { 17 | require_once '../core/lib/Config.php'; 18 | $configTest = array(0 => 'apples', 19 | 1 => 'pears', 20 | 2 => 'bananas'); 21 | $this->config = new \fmvc\core\lib\Config($configTest); 22 | } 23 | 24 | public function tearDown() {} 25 | 26 | /** 27 | * @expectedException Exception 28 | */ 29 | public function testNullConstructor() { 30 | $test = new \fmvc\core\lib\Config(); 31 | } 32 | 33 | public function testConstructor() 34 | { 35 | $cfg = $this->config->c_config; 36 | $this->assertEquals('apples', $cfg[0]); 37 | $this->assertEquals(3, count($cfg)); 38 | } 39 | 40 | public function testItem() 41 | { 42 | $this->assertEquals('apples', $this->config->item(0)); 43 | $this->assertEquals(3, count($this->config->item())); 44 | } 45 | 46 | public function testSetItem() 47 | { 48 | $this->config->set('value', 'testValue'); 49 | $this->assertEquals('testValue', $this->config->item('value')); 50 | } 51 | 52 | /** 53 | * @expectedException Exception 54 | */ 55 | public function testSetNull() { 56 | $this->config->set('item'); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /tests/core/ControllerTest.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright 2013 9 | * @license /license.txt 10 | */ 11 | require_once '../core/lib/Controller.php'; 12 | require_once '../core/lib/Input.php'; 13 | 14 | use \fmvc\core\lib\Input; 15 | 16 | if (! session_id()) { 17 | session_start(); 18 | } 19 | 20 | class ControllerTest extends PHPUnit_Framework_TestCase 21 | 22 | { 23 | public $input; 24 | 25 | public function setUp() 26 | { 27 | 28 | } 29 | 30 | public function tearDown() 31 | { 32 | 33 | } 34 | 35 | public function testConstructorDocRoot() 36 | { 37 | $stub = $this->getMockBuilder('config') 38 | ->getMock(); 39 | $input = new Input(array('config'=>$stub)); 40 | $arrParams = array('param1', 'param2'); 41 | $ctrl = new \fmvc\core\lib\Controller(array('config' => $stub, 'input' => $input), $arrParams); 42 | } 43 | 44 | public function testConstructorHttpHost() 45 | { 46 | $stub = $this->getMockBuilder('config') 47 | ->getMock(); 48 | $input = new Input(array('config'=>$stub)); 49 | $input->server['HTTP_HOST'] = 'example.com'; 50 | $arrParams = array('param1', 'param2'); 51 | $ctrl = new \fmvc\core\lib\Controller(array('config' => $stub, 'input' => $input), $arrParams); 52 | } 53 | 54 | /** 55 | * @expectedException \Exception 56 | */ 57 | public function testConstructorNull() 58 | { 59 | $fail = new \fmvc\core\lib\Controller(); 60 | } 61 | 62 | 63 | 64 | } -------------------------------------------------------------------------------- /tests/core/DocumentationTest.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright 2013 9 | * @license /license.txt 10 | */ 11 | require_once '../core/helper/Documentation.php'; 12 | 13 | use fmvc\core\helper\Documentation; 14 | 15 | class DocumentationTest extends PHPUnit_Framework_TestCase 16 | { 17 | 18 | 19 | /** 20 | * Mock of the Parsedown Object 21 | * @var 22 | */ 23 | public $parse; 24 | 25 | 26 | public function setUp() 27 | { 28 | $this->parse = $this->getMockBuilder('Parsedown') 29 | ->disableOriginalConstructor() 30 | ->setMethods(array('text')) 31 | ->getMock(); 32 | 33 | 34 | } 35 | 36 | public function tearDown() 37 | { 38 | 39 | } 40 | 41 | public function testConstructor() 42 | { 43 | $doc = new Documentation('testVal'); 44 | $this->assertEquals('testVal', $doc->dirName); 45 | } 46 | 47 | public function testConstructorNull() 48 | { 49 | $doc = new Documentation(); 50 | $this->assertEquals('./docs', $doc->dirName); 51 | } 52 | 53 | public function testGetDocumentationFilenames() 54 | { 55 | $doc = new Documentation('../docs'); 56 | $array = $doc->getDocumentationFileNames(); 57 | $this->assertArrayHasKey(1,$array); 58 | } 59 | 60 | public function testParseDocumentationFile() 61 | { 62 | $doc = new Documentation('../temp'); 63 | 64 | $this->parse->expects($this->once()) 65 | ->method('text') 66 | ->will($this->returnValue('

test123

')); 67 | 68 | file_put_contents('../temp/test.md', '#test123'); 69 | $result = $doc->parseDocumentationFile('test.md', $this->parse); 70 | if (file_exists('../temp/test.md')) { 71 | unlink('../temp/test.md'); 72 | } 73 | } 74 | 75 | } -------------------------------------------------------------------------------- /tests/core/FilterTest.php: -------------------------------------------------------------------------------- 1 | assertTrue(Filter::filename($val)); 29 | } 30 | 31 | $bad = array( 32 | 'config-test.php', 33 | 'co(fig.php', 34 | 'me@example.com' 35 | ); 36 | 37 | foreach($bad as $badVal) 38 | { 39 | $this->assertFalse(Filter::filename($badVal)); 40 | } 41 | 42 | 43 | } 44 | 45 | public function testInteger() 46 | { 47 | $vals = array(1,2354,6543,2,24); 48 | $badVals = array('x','ABCD', 1.5, '1.33'); 49 | 50 | foreach ($vals as $val) 51 | { 52 | $this->assertTrue(Filter::integer($val),"Tested $val for Integer Filter"); 53 | } 54 | 55 | foreach ($badVals as $bad) { 56 | $this->assertFalse(Filter::integer($bad), "Tested $bad for Numeric Fail Filter"); 57 | } 58 | } 59 | 60 | public function testNumeric() 61 | { 62 | $vals = array(1,2354,6543,2,24.6,1.2354); 63 | $badVals = array('x','ABCD','1.33z'); 64 | 65 | foreach ($vals as $val) 66 | { 67 | $this->assertTrue(Filter::numeric($val), "Tested $val for Numeric Filter"); 68 | } 69 | 70 | foreach ($badVals as $bad) { 71 | $this->assertFalse(Filter::numeric($bad), "Tested $bad for Numeric Fail Filter"); 72 | } 73 | } 74 | 75 | public function testAlphanumeric() 76 | { 77 | $vals = array(2354,6543,'2abcs', 'mnlkkjdsa', 'asdejfjaASDEV1234'); 78 | $badVals = array('space Val','ABCD@','1.33z', 'test-value', 'test_value'); 79 | 80 | foreach ($vals as $val) 81 | { 82 | $this->assertTrue(Filter::alphanumeric($val), "Tested $val for Alphanumeric Filter"); 83 | } 84 | 85 | foreach ($badVals as $bad) { 86 | $this->assertFalse(Filter::alphanumeric($bad), "Tested $bad for Numeric Fail Filter"); 87 | } 88 | } 89 | 90 | public function testAlpha() 91 | { 92 | $vals = array('abcs', 'mnlkkjdsa', 'asdejfjaASDEV'); 93 | $badVals = array('space Val','ABCD@','1.33z', 'test-value', 'test_value'); 94 | 95 | foreach ($vals as $val) 96 | { 97 | $this->assertTrue(Filter::alpha($val), "Tested $val for Alpha Filter"); 98 | } 99 | 100 | foreach ($badVals as $bad) { 101 | $this->assertFalse(Filter::alpha($bad), "Tested $bad for Alpha Fail Filter"); 102 | } 103 | } 104 | 105 | 106 | public function testEmail() 107 | { 108 | $vals = array('test@mail.test.com', 'p.diddy@example.net', 'joe_blow@test.org'); 109 | $badVals = array('www.test.com','joe@example','tim#excampl.com'); 110 | 111 | foreach ($vals as $val) 112 | { 113 | $this->assertTrue(Filter::email($val), "Tested $val for Email Filter"); 114 | } 115 | 116 | foreach ($badVals as $bad) { 117 | $this->assertFalse(Filter::email($bad), "Tested $bad for Email Fail Filter"); 118 | } 119 | } 120 | 121 | public function testBoolean() 122 | { 123 | $vals = array(true, 1, 'on', 'yes'); 124 | $badVals = array('www.test.com', 0, null, false); 125 | 126 | foreach ($vals as $val) 127 | { 128 | $this->assertTrue(Filter::boolean($val), "Tested $val for Boolean Filter"); 129 | } 130 | 131 | foreach ($badVals as $bad) { 132 | $this->assertFalse(Filter::boolean($bad), "Tested $bad for Boolean Fail Filter"); 133 | } 134 | } 135 | 136 | 137 | public function testPageName() 138 | { 139 | $vals = array('test', 'testPage1', 'test_page'); 140 | $badVals = array('test-page', 'test.page', 'test page'); 141 | 142 | foreach ($vals as $val) 143 | { 144 | $this->assertTrue(Filter::pageName($val), "Tested $val for PageName Filter"); 145 | } 146 | 147 | foreach ($badVals as $bad) { 148 | $this->assertFalse(Filter::pageName($bad), "Tested $bad for PageName Fail Filter"); 149 | } 150 | } 151 | 152 | public function testDatabaseField() 153 | { 154 | $vals = array('test', 'testPage1', 'test_page', 'test.page'); 155 | $badVals = array('test-page', 'test page', 'test%page'); 156 | 157 | foreach ($vals as $val) 158 | { 159 | $this->assertTrue(Filter::databaseField($val), "Tested $val for Field Filter"); 160 | } 161 | 162 | foreach ($badVals as $bad) { 163 | $this->assertFalse(Filter::databaseField($bad), "Tested $bad for Field Fail Filter"); 164 | } 165 | } 166 | 167 | public function testCheckDateIsValid() 168 | { 169 | $vals = array('1/12/15', '1/1/15', '01/02/2015', '12/25/2015', '12/16/14'); 170 | $badVals = array('1/32/2013', '13/1/1999', '2/29/1999', '11/10/234015', '1/15'); 171 | 172 | foreach ($vals as $val) 173 | { 174 | $this->assertTrue(Filter::checkDateIsValid($val), "Tested $val for Date Filter"); 175 | } 176 | 177 | foreach ($badVals as $bad) { 178 | $this->assertFalse(Filter::checkDateIsValid($bad), "Tested $bad for Date Fail Filter"); 179 | } 180 | } 181 | 182 | } 183 | -------------------------------------------------------------------------------- /tests/core/HtmlHeadTest.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright 2013 9 | * @license /license.txt 10 | */ 11 | require_once '../core/helper/HtmlHead.php'; 12 | require_once '../core/lib/Config.php'; 13 | 14 | 15 | class HtmlHeadTest extends PHPUnit_Framework_TestCase 16 | { 17 | public $config; 18 | public $class; 19 | 20 | public function setUp() 21 | { 22 | $config = array( 23 | 'default_title' => 'Test123' 24 | ); 25 | $this->config = new \fmvc\core\lib\Config($config); 26 | $this->class = new \fmvc\core\helper\HtmlHead(array('config' => $this->config)); 27 | 28 | } 29 | 30 | public function tearDown() {} 31 | 32 | public function testConstructor() 33 | { 34 | $dep = array('config' => $this->config); 35 | $class = new \fmvc\core\helper\HtmlHead($dep); 36 | $this->assertEquals('Test123', $class->c_title); 37 | } 38 | 39 | /** 40 | * @expectedException \Exception 41 | */ 42 | public function testConstructorFail() 43 | { 44 | $class = new \fmvc\core\helper\HtmlHead(); 45 | } 46 | 47 | public function testStyle() 48 | { 49 | $this->class->style(array('testStyle')); 50 | 51 | $result = is_numeric(strpos($this->class->c_styles[0], 'testStyle')); 52 | $this->assertTrue($result); 53 | } 54 | 55 | 56 | /** 57 | * @expectedException \Exception 58 | */ 59 | public function testStyleNoParam() 60 | { 61 | $this->class->style(); 62 | } 63 | 64 | /** 65 | * @expectedException \Exception 66 | */ 67 | public function testStyleEmptyParam() 68 | { 69 | $this->class->style(array()); 70 | } 71 | 72 | /** 73 | * @expectedException \Exception 74 | */ 75 | public function testScriptNoParam() 76 | { 77 | $this->class->script(); 78 | } 79 | 80 | /** 81 | * @expectedException \Exception 82 | */ 83 | public function testScriptEmptyParam() 84 | { 85 | $this->class->style(array()); 86 | } 87 | 88 | public function testScript() 89 | { 90 | $this->class->script(array('testScript')); 91 | 92 | $result = is_numeric(strpos($this->class->c_scripts[0], 'testScript')); 93 | $this->assertTrue($result); 94 | } 95 | 96 | public function testTitle() 97 | { 98 | $this->class->title('NewTitle'); 99 | $title = $this->class->c_title; 100 | $this->assertEquals('NewTitle', $title); 101 | } 102 | 103 | /** 104 | * @expectedException \Exception 105 | */ 106 | public function testTitleNull() 107 | { 108 | $this->class->title(); 109 | } 110 | 111 | public function testHead() 112 | { 113 | $this->class->script(array('testScript')); 114 | $this->class->style(array('testStyle')); 115 | $head = $this->class->head(); 116 | $result = strpos($head, 'testScript'); 117 | $this->assertTrue(is_numeric($result)); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /tests/core/InputTest.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright 2013 9 | * @license /license.txt 10 | */ 11 | use \fmvc\core\lib\Input; 12 | 13 | if (! session_id()) { 14 | session_start(); 15 | } 16 | class InputTest extends PHPUnit_Framework_TestCase 17 | { 18 | public $input; 19 | 20 | public function setUp() 21 | { 22 | require_once '../core/lib/Input.php'; 23 | $this->input = new Input('development'); 24 | 25 | } 26 | 27 | public function tearDown() { 28 | 29 | } 30 | 31 | 32 | public function testConstructor() 33 | { 34 | $this->assertTrue(is_array($this->input->server)); 35 | $return = $this->input; 36 | $this->assertObjectHasAttribute('server', $return); 37 | $this->assertObjectHasAttribute('cookie', $return); 38 | $this->assertObjectHasAttribute('get', $return); 39 | $this->assertObjectHasAttribute('post', $return); 40 | $this->assertObjectHasAttribute('session', $return); 41 | } 42 | 43 | public function testLoadSuperglobals() { 44 | $return = $this->input->loadSuperglobals(); 45 | $this->assertObjectHasAttribute('server', $return); 46 | $this->assertObjectHasAttribute('cookie', $return); 47 | $this->assertObjectHasAttribute('get', $return); 48 | $this->assertObjectHasAttribute('post', $return); 49 | $this->assertObjectHasAttribute('session', $return); 50 | } 51 | 52 | public function testSetSessionVariable() 53 | { 54 | $return = $this->input->session('test','test123'); 55 | $this->assertEquals('test123', $_SESSION['test']); 56 | } 57 | 58 | /** 59 | * @runInSeparateProcess 60 | */ 61 | public function testSetCookieVariable() 62 | { 63 | ob_start(); 64 | $return = $this->input->cookie('test','test123'); 65 | $this->assertTrue($return); 66 | ob_end_flush(); 67 | } 68 | 69 | } -------------------------------------------------------------------------------- /tests/core/LoggerTest.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright 2013 9 | * @license /license.txt 10 | */ 11 | 12 | date_default_timezone_set('America/New_York'); 13 | use \fmvc\core\helper\Logger; 14 | require_once '../core/helper/Logger.php'; 15 | require_once '../core/lib/Config.php'; 16 | 17 | class LoggerTest extends PHPUnit_Framework_TestCase 18 | { 19 | public $log; 20 | public $conf; 21 | 22 | public function setUp() 23 | { 24 | $config['error_log_path'] = 'temp/'; 25 | $this->conf = new \fmvc\core\lib\Config($config); 26 | $this->log = new Logger(array('config' => $this->conf)); 27 | } 28 | 29 | public function tearDown() 30 | { 31 | //exec('mv ./temp1 ./temp'); 32 | //exec('chmod 0777 ./temp'); 33 | } 34 | 35 | /** 36 | * @expectedException \Exception 37 | */ 38 | public function testLoggerConstructorFail() 39 | { 40 | $log = new Logger(); 41 | } 42 | 43 | 44 | public function testLogger() 45 | { 46 | if ( ! is_writeable('./temp/notice.txt')) { 47 | exec("chmod 777 ./temp/notice.txt"); 48 | } 49 | $this->log->notice('Test 123 Notice', 'Some Data'); 50 | 51 | $file = file_get_contents('temp/notice.txt'); 52 | $this->assertFileExists('temp/notice.txt'); 53 | $this->assertStringStartsWith('----Logged', $file); 54 | //unlink('temp/notice.txt'); 55 | 56 | } 57 | 58 | /** 59 | * @expectedException \Exception 60 | */ 61 | public function testLoggerFail() 62 | { 63 | if ( ! is_writeable('./temp/notice.txt')) { 64 | exec("chmod 777 ./temp/notice.txt"); 65 | } 66 | $this->log->notice(null, null); 67 | 68 | $file = file_get_contents('temp/notice.txt'); 69 | $this->assertFileExists('temp/notice.txt'); 70 | $this->assertStringStartsWith('----Logged', $file); 71 | //unlink('temp/notice.txt'); 72 | 73 | } 74 | 75 | /** 76 | * @expectedException \Exception 77 | */ 78 | public function testLoggerFailMethodName() 79 | { 80 | $this->log->notic('Test 123 Notice', 'Some Data'); 81 | } 82 | 83 | /** 84 | * @expectedException \Exception 85 | */ 86 | public function testLoggerFailParams() 87 | { 88 | $this->log->notice(); 89 | } 90 | 91 | /** 92 | * @expectedException \Exception 93 | */ 94 | public function testFileOpenFail() 95 | { 96 | $this->log->levels = array_merge($this->log->levels, array('hello/hello')); 97 | $this->log->logEvent('hello/hello','test', 'test'); 98 | } 99 | 100 | /** 101 | * @expectedException \Exception 102 | */ 103 | public function testFileWriteFail() 104 | { 105 | 106 | if (is_writeable('./temp/notice.txt')) { 107 | exec("chmod 444 ./temp/notice.txt"); 108 | } 109 | $this->log->logEvent('notice', 'test', 'test'); 110 | } 111 | 112 | 113 | } 114 | -------------------------------------------------------------------------------- /tests/core/PdoConnTest.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright 2013 9 | * @license /license.txt 10 | */ 11 | use \fmvc\core\data\PdoConn; 12 | use \fmvc\core\lib\Config; 13 | require_once '../core/data/PdoConn.php'; 14 | require_once '../core/lib/Config.php'; 15 | 16 | class PdoConnTest extends PHPUnit_Framework_TestCase 17 | { 18 | public $db; 19 | public $conf; 20 | public $insert_id; 21 | 22 | public function setUp() 23 | { 24 | $config['db_default']['db_path'] = '../data/sqlite'; 25 | $config['db_default']['db_filename'] = 'unit_test.db'; 26 | $config['db_default']['driver'] = 'sqlite'; 27 | $config['db_default']['db_prefix'] = ''; 28 | $this->conf = new Config($config); 29 | 30 | $this->db = new PdoConn(array('config' => $this->conf)); 31 | } 32 | 33 | public function tearDown() 34 | { 35 | $this->db = null; 36 | } 37 | 38 | 39 | public function testMysqlConnection() 40 | { 41 | $this->assertObjectHasAttribute('conn', $this->db); 42 | } 43 | 44 | /** 45 | * @expectedException \Exception 46 | */ 47 | public function testSqlServerConnectionAndConnFailure() 48 | { 49 | $config2['db_default']['dsn'] = 'localhost:1433'; 50 | $config2['db_default']['db_user'] = 'user'; 51 | $config2['db_default']['db_password'] = 'sample'; 52 | $config2['db_default']['driver'] = 'sqlsrv'; 53 | $config2['db_prefix'] = ''; 54 | $conf2 = new Config($config2); 55 | $db3 = new PdoConn(array('config'=>$conf2)); 56 | $db3 = null; 57 | } 58 | 59 | /** 60 | * @expectedException \Exception 61 | */ 62 | public function testOdbcConnectionAndConnFailure() 63 | { 64 | $config2['db_default']['dsn'] = 'localhost:9999'; 65 | $config2['db_default']['db_user'] = 'user'; 66 | $config2['db_default']['db_password'] = 'sample'; 67 | $config2['db_default']['driver'] = 'odbc'; 68 | $config2['db_prefix'] = ''; 69 | $conf2 = new Config($config2); 70 | $db3 = new PdoConn(array('config'=>$conf2)); 71 | $db3 = null; 72 | } 73 | 74 | /** 75 | * @expectedException \Exception 76 | */ 77 | public function testMysqlConnectionAndConnFailure() 78 | { 79 | $config2['db_default']['host'] = 'localhost'; 80 | $config2['db_default']['port'] = '8889'; 81 | $config2['db_default']['db_user'] = 'root'; 82 | $config2['db_default']['db_name'] = 'test'; 83 | $config2['db_default']['db_password'] = 'mysql2'; 84 | $config2['db_default']['driver'] = 'mysql'; 85 | $config2['db_prefix'] = 'pims_'; 86 | $conf2 = new Config($config2); 87 | $db3 = new PdoConn(array('config'=>$conf2)); 88 | $db3 = null; 89 | } 90 | 91 | /** 92 | * @expectedException \Exception 93 | */ 94 | public function testPostgresConnectionAndConnFailure() 95 | { 96 | $config2['db_default']['db_user'] = 'root'; 97 | $config2['db_default']['db_name'] = 'test'; 98 | $config2['db_default']['db_password'] = 'mysql2'; 99 | $config2['db_default']['port'] ='1234'; 100 | $config2['db_default']['host'] = 'localhost'; 101 | $config2['db_default']['driver'] = 'pgsql'; 102 | $conf2 = new Config($config2); 103 | $db3 = new PdoConn(array('config'=>$conf2)); 104 | $db3 = null; 105 | } 106 | 107 | /** 108 | * @runInSeparateProcess 109 | * @expectedException \Exception 110 | */ 111 | public function testPostgresPortConnectionAndConnFailure() 112 | { 113 | $config2['db_default']['db_user'] = 'root'; 114 | $config2['db_default']['db_name'] = 'test'; 115 | $config2['db_default']['port'] = '5444'; 116 | $config2['db_default']['db_password'] = 'mysql2'; 117 | $config2['db_default']['driver'] = 'pgsql'; 118 | $conf2 = new Config($config2); 119 | $db3 = new PdoConn(array('config'=>$conf2)); 120 | $db3 = null; 121 | } 122 | 123 | 124 | /** 125 | * @expectedException \Exception 126 | */ 127 | public function testSqliteConnectionAndConnFailure() 128 | { 129 | $config2['db_default']['db_path'] = null; 130 | $config2['db_default']['driver'] = 'sqlite'; 131 | $conf2 = new Config($config2); 132 | $db3 = new PdoConn(array('config'=>$conf2)); 133 | $db3 = null; 134 | } 135 | 136 | /** 137 | * @expectedException \Exception 138 | */ 139 | public function testConnectionDependencyFailure() 140 | { 141 | $db = new PdoConn(array()); 142 | } 143 | 144 | /** 145 | * 146 | */ 147 | public function testConnectionWithName() 148 | { 149 | $db2 = new PdoConn(array('config' => $this->conf), 'default'); 150 | $this->assertObjectHasAttribute('conn', $db2); 151 | $db2 = null; 152 | } 153 | 154 | 155 | /** 156 | * 157 | */ 158 | public function testInit() 159 | { 160 | $db2 = new PdoConn(array('config' => $this->conf), 'default'); 161 | $db2->init(); 162 | $this->assertObjectHasAttribute('conn', $db2); 163 | $db2 = null; 164 | } 165 | 166 | public function testOverloadGet() 167 | { 168 | $arrOutput = $this->db->getCompaniesById(1); 169 | $this->assertArrayHasKey('abbr', $arrOutput[0]); 170 | } 171 | 172 | 173 | /** 174 | * @expectedException \PDOException 175 | */ 176 | public function testOverloadGetFail() 177 | { 178 | $arrOutput = $this->db->getCompaniesByIx(1); 179 | //$this->assertArrayHasKey('abbr', $arrOutput[0]); 180 | } 181 | 182 | public function testOverloadFiler() 183 | { 184 | $arrOutput = $this->db->filterCompaniesById(1); 185 | $this->assertArrayHasKey('abbr', $arrOutput[0]); 186 | } 187 | public function testFilterSort() 188 | { 189 | $arrOutput = $this->db->filter('companies', 'id', '1', 'abbr'); 190 | $this->assertArrayHasKey('abbr', $arrOutput[0]); 191 | } 192 | 193 | 194 | public function testFilter() 195 | { 196 | $arrOutput = $this->db->filter('companies', 'id', 1); 197 | $this->assertArrayHasKey('abbr', $arrOutput[0]); 198 | 199 | $arrOutput = $this->db->filter('companies', 'id', '1*'); 200 | $this->assertArrayHasKey('abbr', $arrOutput[0]); 201 | 202 | 203 | } 204 | 205 | /** 206 | * @expectedException \PDOException 207 | */ 208 | public function testFilterFail() 209 | { 210 | $arrOutput = $this->db->filter('companies', 'ix', 1); 211 | //$this->assertArrayHasKey('abbr', $arrOutput[0]); 212 | } 213 | 214 | public function testOverloadInsert() 215 | { 216 | $arr = array( 217 | 'abbr' => "TST", 218 | 'descr' => "TEST COMPANY", 219 | ); 220 | $result = $this->db->insertCompanies($arr); 221 | $this->insert_id = $result; 222 | $rs = $this->db->getCompaniesById($result); 223 | $this->assertArrayHasKey('abbr', $rs[0]); 224 | $this->assertEquals('TST', $rs[0]['abbr']); 225 | } 226 | 227 | /** 228 | * @expectedException \PDOException 229 | */ 230 | public function testOverloadInsertFail() 231 | { 232 | $arr = array( 233 | 'abbrev' => "TST", 234 | 'descr' => "TEST COMPANY", 235 | ); 236 | $result = $this->db->insertCompanies($arr); 237 | 238 | } 239 | 240 | public function testOverloadUpdate() 241 | { 242 | 243 | $arr = array('abbr' => 'TTS'); 244 | $this->db->updateCompaniesByAbbr('TST' , $arr); 245 | $rs = $this->db->getCompaniesByAbbr('TTS'); 246 | $this->assertArrayHasKey('abbr', $rs[0]); 247 | $this->assertEquals('TTS', $rs[0]['abbr']); 248 | } 249 | 250 | /** 251 | * @expectedException \PDOException 252 | */ 253 | public function testOverloadUpdateFail() 254 | { 255 | $arr = array('abbrev' => 'TTS'); 256 | $this->db->updateCompaniesById('TST', $arr); 257 | } 258 | 259 | public function testOverloadDelete() 260 | { 261 | 262 | $rs = $this->db->deleteCompaniesByAbbr('TTS'); 263 | $this->assertEquals(1, $rs); 264 | } 265 | 266 | /** 267 | * @expectedException \PDOException 268 | */ 269 | public function testOverloadDeleteFail() 270 | { 271 | $rs = $this->db->deleteCompaniesByIx('TTS'); 272 | } 273 | 274 | public function testOverloadGetAll() 275 | { 276 | $rs = $this->db->allCompanies(); 277 | $this->assertArrayHasKey('abbr', $rs[0]); 278 | } 279 | 280 | /** 281 | * @expectedException \PDOException 282 | */ 283 | public function testOverloadGetAllFail() 284 | { 285 | $rs = $this->db->allCompaniess(); 286 | } 287 | 288 | 289 | public function testCamelCaseToUnderscore() 290 | { 291 | $val = 'SomeTest'; 292 | $expected = 'some_test'; 293 | $ret = $this->db->camelCaseToUnderscore($val); 294 | $this->assertEquals($expected, $ret); 295 | } 296 | 297 | public function testGetIn() 298 | { 299 | $rs = $this->db->getIn('companies', 'id', '1'); 300 | $this->assertArrayHasKey('abbr', $rs[0]); 301 | } 302 | 303 | /** 304 | * @expectedException \PDOException 305 | */ 306 | public function testGetInFail() 307 | { 308 | $rs = $this->db->getIn('company', 'id', '100'); 309 | $this->assertArrayHasKey('abbr', $rs[0]); 310 | } 311 | 312 | public function testDoSql() 313 | { 314 | $rs = $this->db->doSql("SELECT * FROM companies WHERE id = 1"); 315 | $this->assertArrayHasKey('abbr', $rs[0]); 316 | } 317 | 318 | /** 319 | * @expectedException \PDOException 320 | */ 321 | public function testDoSqlFail() 322 | { 323 | $rs = $this->db->doSql('SELECT * FROM company where id = 1'); 324 | $this->assertArrayHasKey('abbr', $rs[0]); 325 | } 326 | } 327 | -------------------------------------------------------------------------------- /tests/core/RestApiCallerTest.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright 2014 11 | * @license /license.txt 12 | */ 13 | use fmvc\core\helper\RestApiCaller; 14 | 15 | class RestApiCallerTest extends PHPUnit_Framework_TestCase 16 | { 17 | public $baseUrl; 18 | 19 | 20 | public function setUp() 21 | { 22 | require_once '../core/helper/RestApiCaller.php'; 23 | $this->baseUrl = 'http://localhost:8888/flight-MVC/tests/api_test/' ; 24 | } 25 | 26 | public function testGet() 27 | { 28 | $url = $this->baseUrl . 'get.php'; 29 | $data = RestApiCaller::get($url); 30 | $this->assertEquals('Testing Get Call', $data); 31 | } 32 | 33 | public function testPostFields() 34 | { 35 | $url = $this->baseUrl . 'post.php'; 36 | $data = array('a' => 'Foo', 'b' => 'Bar'); 37 | $type = 'fields'; 38 | 39 | $this->assertEquals('Bar', RestApiCaller::post($url, $data, $type)); 40 | } 41 | 42 | public function testPostJson() 43 | { 44 | $url = $this->baseUrl . 'post-json.php'; 45 | $data = array('a' => 'Foo', 'b' => 'Bar'); 46 | $type = 'json'; 47 | 48 | $result = json_decode(RestApiCaller::post($url,$data,$type)); 49 | $this->assertEquals('Bar', $result->b); 50 | } 51 | 52 | public function testPostXml() 53 | { 54 | $url = $this->baseUrl . 'post-xml.php'; 55 | $data = 'Some text to test'; 56 | $type = 'xml'; 57 | 58 | $result = RestApiCaller::post($url,$data,$type); 59 | $this->assertEquals('Some text to test', $result); 60 | } 61 | 62 | public function testPutJson() 63 | { 64 | $url = $this->baseUrl . 'put.php'; 65 | $data = array('a' => 'Foo', 'b' => 'Bar'); 66 | $type = 'json'; 67 | $result = json_decode(RestApiCaller::put($url,$data,$type)); 68 | 69 | $this->assertEquals('Bar', $result->b); 70 | } 71 | 72 | public function testDelete() 73 | { 74 | $url = $this->baseUrl . 'delete.php'; 75 | $result = RestApiCaller::delete($url); 76 | $this->assertEquals('Working', $result); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /tests/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Directory Browsing Prohibited

8 | 9 | -------------------------------------------------------------------------------- /version.txt: -------------------------------------------------------------------------------- 1 | 0.2.1 2 | -------------------------------------------------------------------------------- /web/css/.htaccess: -------------------------------------------------------------------------------- 1 | RewriteEngine Off -------------------------------------------------------------------------------- /web/css/docs.css: -------------------------------------------------------------------------------- 1 | body { 2 | max-width: 960px; 3 | margin: auto; 4 | padding: 1em; 5 | line-height: 20px; 6 | font-family: Helvetica, Arial, sans-serif; 7 | font-size: 13px; 8 | } 9 | 10 | .wrapper { 11 | width: 960px; 12 | margin-left: auto; 13 | margin-right: auto; 14 | } 15 | 16 | .leftCol { 17 | width: 190px; 18 | padding: 5px; 19 | float: left; 20 | margin-right: auto; 21 | border-radius: 5px; 22 | background-color: #cccccc; 23 | } 24 | 25 | .rightCol { 26 | width: 750px; 27 | height: 500px; 28 | overflow-y: auto; 29 | float: right; 30 | padding: 5px; 31 | } 32 | 33 | tt, code, pre { 34 | font-family: 'Lucida Console', Consolas, Monaco, monospace; 35 | } 36 | 37 | h1 { 38 | font-size:2.0em; 39 | } 40 | 41 | h2 { 42 | font-size:1.6em; 43 | } 44 | 45 | h3 { 46 | font-size:1.2em; 47 | } 48 | 49 | h4 { 50 | font-size:0.9em; 51 | } 52 | 53 | h5 { 54 | font-size:0.8em; 55 | } 56 | 57 | h6 { 58 | font-size:0.7em; 59 | } 60 | 61 | a:visited { 62 | color: rgb(50%, 0%, 50%); 63 | } 64 | 65 | pre, img { 66 | max-width: 100%; 67 | } 68 | 69 | pre code { 70 | display: block; padding: 0.5em; 71 | } 72 | 73 | code { 74 | font-size: 100%; 75 | border: 1px solid #ccc; 76 | } 77 | 78 | code[class] { 79 | background-color: #F8F8F8; 80 | } 81 | 82 | table, td, th { 83 | border: none; 84 | } 85 | 86 | blockquote { 87 | color:#666666; 88 | margin:0; 89 | padding-left: 1em; 90 | border-left: 0.5em #EEE solid; 91 | } 92 | 93 | hr { 94 | height: 0px; 95 | border-bottom: none; 96 | border-top-width: thin; 97 | border-top-style: dotted; 98 | border-top-color: #999999; 99 | } 100 | 101 | a, a:visited { 102 | text-decoration: none; 103 | color: #000000; 104 | } 105 | 106 | a:hover { 107 | text-decoration: underline; 108 | } 109 | -------------------------------------------------------------------------------- /web/css/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Directory Browsing Prohibited

8 | 9 | -------------------------------------------------------------------------------- /web/img/.htaccess: -------------------------------------------------------------------------------- 1 | RewriteEngine Off -------------------------------------------------------------------------------- /web/img/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Directory Browsing Forbidden

8 | 9 | -------------------------------------------------------------------------------- /web/index.php: -------------------------------------------------------------------------------- 1 | 11 | * @copyright 2014 12 | * @license /license.txt 13 | */ 14 | 15 | // Load the environment configuration file 16 | require_once dirname(__DIR__) . '/config/environment.php'; 17 | 18 | // include autoloader files 19 | require_once dirname(__DIR__) . '/libraries/autoload.php'; 20 | 21 | // include global functions 22 | require_once dirname(__DIR__) . '/core/functions/global_functions.php'; 23 | 24 | // Load the environment based configuration 25 | require_once dirname(__DIR__) . '/config/' .setEnvironment(APP_ENVIRONMENT). '.php'; 26 | 27 | // load the bootstrap file 28 | require_once dirname(__DIR__) . '/core/bootstrap.php'; 29 | 30 | // here we go! 31 | Flight::start(); -------------------------------------------------------------------------------- /web/scripts/.htaccess: -------------------------------------------------------------------------------- 1 | RewriteEngine Off -------------------------------------------------------------------------------- /web/scripts/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Directory Browsing Prohibited

8 | 9 | --------------------------------------------------------------------------------