PageRenderTime 48ms CodeModel.GetById 5ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/ruckusing/lib/classes/class.Ruckusing_FrameworkRunner.php

https://github.com/radicaldesigns/jaguar
PHP | 254 lines | 174 code | 29 blank | 51 comment | 33 complexity | 95623ef92800916891e692585e496f0d MD5 | raw file
Possible License(s): MIT, LGPL-2.1
  1. <?php
  2. //requirements
  3. require_once RUCKUSING_BASE . '/lib/classes/task/class.Ruckusing_TaskManager.php';
  4. /*
  5. Primary work-horse class. This class bootstraps the framework by loading
  6. all adapters and tasks.
  7. */
  8. class Ruckusing_FrameworkRunner {
  9. private $db = null; //reference to our DB connection
  10. private $active_db_config; //the currently active config
  11. private $config = array(); //all available DB configs (e.g. test,development, production)
  12. private $task_mgr = null;
  13. private $adapter = null;
  14. private $cur_task_name = "";
  15. private $task_options = "";
  16. private $ENV = "development"; //default (can also be one 'test', 'production')
  17. //set up some defaults
  18. private $opt_map = array(
  19. 'ENV' => 'development'
  20. );
  21. function __construct($config, $argv) {
  22. try {
  23. set_error_handler( array("Ruckusing_FrameworkRunner", "scr_error_handler"), E_ALL );
  24. //parse arguments
  25. $this->parse_args($argv);
  26. //initialize logger
  27. $log_dir = RUCKUSING_BASE . "/logs";
  28. if(is_dir($log_dir) && !is_writable($log_dir)) {
  29. die("\n\nCannot write to log directory: $log_dir\n\nCheck permissions.\n\n");
  30. }elseif(!is_dir($log_dir)){
  31. //try and create the log directory
  32. mkdir($log_dir);
  33. }
  34. $log_name = sprintf("%s.log", $this->ENV);
  35. $this->logger = Ruckusing_Logger::instance($log_dir . "/" . $log_name);
  36. //include all adapters
  37. $this->load_all_adapters(RUCKUSING_BASE . '/lib/classes/adapters');
  38. $this->config = $config;
  39. $this->initialize_db();
  40. $this->init_tasks();
  41. }catch(Exception $e) {
  42. }
  43. }//constructor
  44. function __destruct() {
  45. }
  46. //-------------------------
  47. // PUBLIC METHODS
  48. //-------------------------
  49. public function execute() {
  50. if($this->task_mgr->has_task($this->cur_task_name)) {
  51. $output = $this->task_mgr->execute($this, $this->cur_task_name, $this->task_options);
  52. $this->display_results($output);
  53. exit(0); // 0 is success
  54. } else {
  55. trigger_error(sprintf("Task not found: %s", $this->cur_task_name));
  56. exit(1);
  57. }
  58. if($this->logger) {
  59. $this->logger->close();
  60. }
  61. }
  62. public function get_adapter() {
  63. return($this->adapter);
  64. }
  65. public function init_tasks() {
  66. $this->task_mgr = new Ruckusing_TaskManager($this->adapter);
  67. }
  68. public function migrations_directory() {
  69. return $this->config['migrations_dir'];
  70. }
  71. public function initialize_db() {
  72. try {
  73. $this->verify_db_config();
  74. $db = $this->config['db'][$this->ENV];
  75. $adapter = $this->get_adapter_class($db['type']);
  76. if($adapter === null) {
  77. trigger_error(sprintf("No adapter available for DB type: %s", $db['type']));
  78. }
  79. //construct our adapter
  80. $this->adapter = new $adapter($db, $this->logger);
  81. }catch(Exception $ex) {
  82. trigger_error(sprintf("\n%s\n",$ex->getMessage()));
  83. }
  84. }
  85. /*
  86. $argv is our complete command line argument set.
  87. PHP gives us:
  88. [0] = the actual file name we're executing
  89. [1..N] = all other arguments
  90. Our task name should be at slot [1]
  91. Anything else are additional parameters that we can pass
  92. to our task and they can deal with them as they see fit.
  93. */
  94. private function parse_args($argv) {
  95. $num_args = count($argv);
  96. if($num_args >= 2) {
  97. $this->cur_task_name = $argv[1];
  98. $options = array();
  99. for($i = 2; $i < $num_args;$i++) {
  100. $arg = $argv[$i];
  101. if(strpos($arg, '=') !== FALSE) {
  102. list($key, $value) = explode("=", $arg);
  103. $options[$key] = $value;
  104. if($key == 'ENV') {
  105. $this->ENV = $value;
  106. }
  107. }
  108. }
  109. $this->task_options = $options;
  110. }
  111. }//parse_args()
  112. /*
  113. Global error handler to process all errors
  114. during script execution
  115. */
  116. public static function scr_error_handler($errno, $errstr, $errfile, $errline) {
  117. echo(sprintf("\n\n(%s:%d) %s\n\n", basename($errfile), $errline, $errstr));
  118. exit(1); // exit with error
  119. }
  120. /*
  121. Update the local schema to handle multiple records versus the prior architecture
  122. of storing a single version. In addition take all existing migration files
  123. and register them in our new table, as they have already been executed.
  124. */
  125. public function update_schema_for_timestamps() {
  126. //only create the table if it doesnt already exist
  127. $this->adapter->create_schema_version_table();
  128. //insert all existing records into our new table
  129. $migrator_util = new Ruckusing_MigratorUtil($this->adapter);
  130. $files = $migrator_util->get_migration_files($this->migrations_directory(), 'up');
  131. foreach($files as $file) {
  132. if( (int)$file['version'] >= PHP_INT_MAX) {
  133. //its new style like '20081010170207' so its not a candidate
  134. continue;
  135. }
  136. //query old table, if it less than or equal to our max version, then its a candidate for insertion
  137. $query_sql = sprintf("SELECT version FROM %s WHERE version >= %d", RUCKUSING_SCHEMA_TBL_NAME, $file['version']);
  138. $existing_version_old_style = $this->adapter->select_one($query_sql);
  139. if(count($existing_version_old_style) > 0) {
  140. //make sure it doesnt exist in our new table, who knows how it got inserted?
  141. $new_vers_sql = sprintf("SELECT version FROM %s WHERE version = %d", RUCKUSING_TS_SCHEMA_TBL_NAME, $file['version']);
  142. $existing_version_new_style = $this->adapter->select_one($new_vers_sql);
  143. if(empty($existing_version_new_style)) {
  144. // use printf & %d to force it to be stripped of any leading zeros, we *know* this represents an old version style
  145. // so we dont have to worry about PHP and integer overflow
  146. $insert_sql = sprintf("INSERT INTO %s (version) VALUES (%d)", RUCKUSING_TS_SCHEMA_TBL_NAME, $file['version']);
  147. $this->adapter->query($insert_sql);
  148. }
  149. }
  150. }//foreach
  151. } // update_schema_for_timestamps()
  152. //-------------------------
  153. // PRIVATE METHODS
  154. //-------------------------
  155. private function display_results($output) {
  156. return;
  157. //deprecated
  158. echo "\nStarted: " . date('Y-m-d g:ia T') . "\n\n";
  159. echo "\n\n";
  160. echo "\n$output\n";
  161. echo "\nFinished: " . date('Y-m-d g:ia T') . "\n\n";
  162. }
  163. private function set_opt($key, $value) {
  164. if(!$key) { return; }
  165. $this->opt_map[$key] = $value;
  166. }
  167. private function verify_db_config() {
  168. if( !array_key_exists($this->ENV, $this->config['db'])) {
  169. throw new Exception(sprintf("Error: '%s' DB is not configured",$this->opt_map[$ENV]));
  170. }
  171. $env = $this->ENV;
  172. $this->active_db_config = $this->config['db'][$this->ENV];
  173. if(!array_key_exists("type",$this->active_db_config)) {
  174. throw new Exception(sprintf("Error: 'type' is not set for '%s' DB",$this->ENV));
  175. }
  176. if(!array_key_exists("host",$this->active_db_config)) {
  177. throw new Exception(sprintf("Error: 'host' is not set for '%s' DB",$this->ENV));
  178. }
  179. if(!array_key_exists("database",$this->active_db_config)) {
  180. throw new Exception(sprintf("Error: 'database' is not set for '%s' DB",$this->ENV));
  181. }
  182. if(!array_key_exists("user",$this->active_db_config)) {
  183. throw new Exception(sprintf("Error: 'user' is not set for '%s' DB",$this->ENV));
  184. }
  185. if(!array_key_exists("password",$this->active_db_config)) {
  186. throw new Exception(sprintf("Error: 'password' is not set for '%s' DB",$this->ENV));
  187. }
  188. }//verify_db_config
  189. private function get_adapter_class($db_type) {
  190. $adapter_class = null;
  191. switch($db_type) {
  192. case 'mysql':
  193. $adapter_class = "Ruckusing_MySQLAdapter";
  194. break;
  195. case 'mssql':
  196. $adapter_class = "Ruckusing_MSSQLAdapter";
  197. break;
  198. case 'pgsql':
  199. $adapter_class = "Ruckusing_PostgresAdapter";
  200. break;
  201. }
  202. return $adapter_class;
  203. }
  204. /*
  205. DB adapters are classes in lib/classes/adapters
  206. and they follow the file name syntax of "class.<DB Name>Adapter.php".
  207. See the function "get_adapter_class" in this class for examples.
  208. */
  209. private function load_all_adapters($adapter_dir) {
  210. if(!is_dir($adapter_dir)) {
  211. trigger_error(sprintf("Adapter dir: %s does not exist", $adapter_dir));
  212. return false;
  213. }
  214. $files = scandir($adapter_dir);
  215. $regex = '/^class\.(\w+)Adapter\.php$/';
  216. foreach($files as $f) {
  217. //skip over invalid files
  218. if($f == '.' || $f == ".." || !preg_match($regex,$f) ) { continue; }
  219. require_once $adapter_dir . '/' . $f;
  220. }
  221. }
  222. }//class
  223. ?>