/** * * * @param int $argc * @param array $argv * * @return void * * @throws \InvalidArgumentException * @throws \RuntimeException if this function is called in a script that is not run at the command line. */ function createController($argc, array $argv) { ////////////////////////////////////////// // START: Environment and Args Validation ////////////////////////////////////////// if (!isPhpRunningInCliMode()) { $err_msg = '`' . __FUNCTION__ . '($argc, array $argv)` should only be called from within' . ' php scripts that should be run via the command line!!!' . PHP_EOL; throw new \RuntimeException($err_msg); } if (is_string($argc) && is_numeric($argc)) { $argc = (int) $argc; } if (!is_int($argc)) { $err_msg = 'The expected value for the first argument to ' . '`' . __FUNCTION__ . '($argc, array $argv)` should be an int.' . ' `' . ucfirst(gettype($argc)) . '` with the value below was supplied:' . PHP_EOL . var_export($argc, true) . PHP_EOL . PHP_EOL . 'Good bye!!!'; throw new \InvalidArgumentException($err_msg); } if (count($argv) < 1) { $err_msg = 'The expected value for the second argument to ' . '`' . __FUNCTION__ . '($argc, array $argv)` should be an array with at least one element. Empty Array was supplied.' . 'This second argument is expected to be the $argv array passed by PHP to the script calling this function.'; throw new \InvalidArgumentException($err_msg); } ////////////////////////////////////////// // END: Environment and Args Validation ////////////////////////////////////////// ////////////////////////////////// ///START: COMMAND PROCESSING ////////////////////////////////// $ds = DIRECTORY_SEPARATOR; if ($argc < 5 || in_array('--help', $argv) || in_array('-help', $argv) || in_array('-h', $argv) || in_array('-?', $argv)) { displayHelp(basename($argv[0])); } else { if ($argc === 5 && (in_array('--controller-name', $argv) || in_array('-c', $argv)) && (in_array('--path-to-src-folder', $argv) || in_array('-p', $argv)) || $argc >= 7 && (in_array('--controller-name', $argv) || in_array('-c', $argv)) && (in_array('--path-to-src-folder', $argv) || in_array('-p', $argv)) && (in_array('--extends-controller', $argv) || in_array('-e', $argv))) { $templates_dir = dirname(__DIR__) . $ds . 'templates' . $ds; $controller_name = getOptVal('--controller-name', $argv); if ($controller_name === false) { $controller_name = getOptVal('-c', $argv); } $studly_controller_name = \Slim3MvcTools\Functions\Str\dashesToStudly(\Slim3MvcTools\Functions\Str\underToStudly($controller_name)); $dashed_controller_name = \Slim3MvcTools\Functions\Str\toDashes($controller_name); if (!isValidClassName($studly_controller_name)) { printError("Invalid controller class name `{$controller_name}` supplied. Goodbye!!"); return; } $src_folder_path = getOptVal('--path-to-src-folder', $argv); if ($src_folder_path === false) { $src_folder_path = getOptVal('-p', $argv); } $src_folder_path = normalizeFolderPathForOs($src_folder_path); if (!file_exists($src_folder_path) || !is_dir($src_folder_path)) { printError("The src folder path `{$src_folder_path}` supplied is a non-existent directory. Goodbye!!"); return; } //////////////////////////////////////////////////////////////////////////// $default_controller_2_extend = '\\Slim3MvcTools\\Controllers\\BaseController'; $controller_2_extend = getOptVal('--extends-controller', $argv); if ($controller_2_extend === false) { $controller_2_extend = getOptVal('-e', $argv); if ($controller_2_extend !== false) { if (!isValidExtendsClassName($controller_2_extend)) { printError("Invalid controller class name `{$controller_2_extend}` for extension supplied. Goodbye!!"); return; } } else { //use default controller class to be extended $controller_2_extend = $default_controller_2_extend; } } else { if (!isValidExtendsClassName($controller_2_extend)) { printError("Invalid controller class name `{$controller_2_extend}` for extension supplied. Goodbye!!"); return; } } //////////////////////////////////////////////////////////////////////////// $namepace_declaration = ''; //omit namespace declaration by default $namepace_4_controller = getOptVal('--namespace-4-controller', $argv); if ($namepace_4_controller === false) { $namepace_4_controller = getOptVal('-n', $argv); if ($namepace_4_controller !== false) { if (!isValidNamespaceName($namepace_4_controller)) { printError("Invalid namespace `{$namepace_4_controller}` supplied. Goodbye!!"); return; } //validation passed $namepace_declaration = "namespace {$namepace_4_controller};"; } else { $namepace_4_controller = ''; } } else { if (!isValidNamespaceName($namepace_4_controller)) { printError("Invalid namespace `{$namepace_4_controller}` supplied. Goodbye!!"); return; } //validation passed $namepace_declaration = "namespace {$namepace_4_controller};"; } //read template controller and substitute __TEMPLTATE_CONTROLLER__ with given controller name \Slim3MvcTools\Functions\Str\underToStudly(dashesToStudly($controller_name_from_cli)) //substitute {{TEMPLTATE_CONTROLLER_VIEW_FOLDER}} with the view folder name \Slim3MvcTools\Functions\Str\toDashes($controller_name_from_cli) //write processed controller file to S3MVC_APP_ROOT_PATH.$ds.'src'.$ds.'controllers'.$ds //make the dir S3MVC_APP_ROOT_PATH.$ds.'src'.$ds.'views'.$ds.\Slim3MvcTools\Functions\Str\toDashes($controller_name_from_cli) //read template controller index view and substitute __TEMPLTATE_CONTROLLER__ with given controller name \Slim3MvcTools\Functions\Str\underToStudly(dashesToStudly($controller_name_from_cli)) //write processed controller file to S3MVC_APP_ROOT_PATH.$ds.'src'.$ds.'views'.$ds.\Slim3MvcTools\Functions\Str\toDashes($controller_name_from_cli) $template_controller_file = $templates_dir . 'controller-class-template.php.tpl'; $dest_controller_class_file_folder = $src_folder_path . 'controllers' . $ds; $dest_controller_class_file = $dest_controller_class_file_folder . "{$studly_controller_name}.php"; if (!file_exists($dest_controller_class_file_folder) && !mkdir($dest_controller_class_file_folder, 0775, true)) { printError("Failed to create `{$dest_controller_class_file_folder}`; the folder supposed to contain the controller named `{$studly_controller_name}`. Goodbye!!"); return; } $template_view_file = $templates_dir . 'index-view-template.php'; $dest_view_file_folder = $src_folder_path . 'views' . $ds . "{$dashed_controller_name}{$ds}"; $dest_view_file = "{$dest_view_file_folder}index.php"; if (!file_exists($dest_view_file_folder) && !mkdir($dest_view_file_folder, 0775, true)) { printError("Failed to create `{$dest_view_file_folder}`; the folder supposed to contain views for the controller named `{$studly_controller_name}`. Goodbye!!"); return; } if (file_exists($dest_controller_class_file)) { printError("Controller class `{$studly_controller_name}` already exists in `{$dest_controller_class_file}`. Goodbye!!"); return; } if (file_exists($dest_view_file)) { printError("View file `{$dest_view_file}` already exists for Controller class `{$studly_controller_name}`. Goodbye!!"); return; } printInfo("Creating Controller Class `{$studly_controller_name}` in `{$dest_controller_class_file}` ...."); //////////////////////////////////////////////////////////////////////////// $replaces = ['__CONTROLLER_2_EXTEND__' => $controller_2_extend, '__TEMPLTATE_CONTROLLER__' => $studly_controller_name, 'namespace __NAMESPACE_2_REPLACE__;' => $namepace_declaration, '{{TEMPLTATE_CONTROLLER_VIEW_FOLDER}}' => $dashed_controller_name, "'__login_success_redirect_controller__'" => "'{$dashed_controller_name}'"]; if (processTemplateFile($template_controller_file, $dest_controller_class_file, $replaces) === false) { printError("Failed transforming template controller `{$template_controller_file}` to `{$dest_controller_class_file}`. Goodbye!!"); } else { printInfo("Successfully created `{$dest_controller_class_file}` ...." . PHP_EOL); } printInfo("Creating index view for `{$studly_controller_name}::actionIndex()` in `{$dest_view_file}` ...."); $replaces['__TEMPLTATE_CONTROLLER__'] = rtrim($namepace_4_controller, '\\') . '\\' . $studly_controller_name; if (processTemplateFile($template_view_file, $dest_view_file, $replaces) === false) { printError("Failed creating index view for `{$studly_controller_name}::actionIndex()` in `{$dest_view_file}`."); printInfo("Deleting `{$dest_controller_class_file}` ...."); if (!unlink($dest_controller_class_file)) { printInfo("Failed to delete `{$dest_controller_class_file}`. Please delete it manually. Goodbye!!"); } else { printInfo("Goodbye!!"); } return; } else { printInfo("Successfully created `{$dest_view_file}` ...." . PHP_EOL); } printInfo("All done!!"); if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') { //test if composer is avaliable only if server OS on which this script is being run //is not windows if (isCommandAvailableOnOs('composer')) { passthru('composer dumpautoload'); } else { printInfo("Remember to run `composer dumpautoload` so that composer can pick up the newly created controller class `{$studly_controller_name}` in `{$dest_controller_class_file}`."); } } else { printInfo("Remember to run `composer dumpautoload` so that composer can pick up the newly created controller class `{$studly_controller_name}` in `{$dest_controller_class_file}`."); } //we are done } else { displayHelp(basename($argv[0])); } } ////////////////////////////////// ///END: COMMAND PROCESSING ////////////////////////////////// }
/** * * Executes a PHP file and returns its output as a string. This file is * supposed to contain the output markup (usually html) for the current * controller action method being executed. * * @param string $file_name name of the file (including extension eg. `read.php`) * containing valid php to be executed and returned as * string. * @param array $data an array of data to be passed to the view file. Each * key in this array is automatically converted to php * variables accessible in the view file. * Eg. passing ['content'=>'yabadabadoo'] to this method * will result in a variable named $content (with a * value of 'yabadabadoo') being available in the view * file (i.e. the file named $file_name). * @return string * * @throws \Slim3MvcTools\Controllers\Exceptions\IncorrectlySetPropertyException * */ public function renderView($file_name, array $data = []) { if (!$this->view_renderer instanceof \Rotexsoft\FileRenderer\Renderer) { try { $this->view_renderer = $this->getContainerItem('new_view_renderer'); } catch (ExpectedContainerItemMissingException $ex) { $msg = "ERROR: The `view_renderer` property of `" . get_class($this) . "`" . " must be set via a call to `" . get_class($this) . '::setViewRenderer(...)` ' . " before calling `" . get_class($this) . '::' . __FUNCTION__ . '(...)`.' . PHP_EOL; throw new IncorrectlySetPropertyException($msg); } } $parent_classes = []; $parent_class = get_parent_class($this); while ($parent_class !== __CLASS__ && !empty($parent_class)) { $parent_classes[] = (new \ReflectionClass($parent_class))->getShortName(); $parent_class = get_parent_class($parent_class); } //Try to prepend view folder for this controller. //It takes precedence over the view folder //for the base controller. $ds = DIRECTORY_SEPARATOR; $path_2_view_files = S3MVC_APP_ROOT_PATH . $ds . 'src' . $ds . 'views' . $ds; while ($parent_class = array_pop($parent_classes)) { $parent_class_folder = \Slim3MvcTools\Functions\Str\toDashes($parent_class); if (!$this->view_renderer->hasPath($path_2_view_files . $parent_class_folder) && file_exists($path_2_view_files . $parent_class_folder)) { $this->view_renderer->prependPath($path_2_view_files . $parent_class_folder); } } //finally add my view folder if (!$this->view_renderer->hasPath($path_2_view_files . $this->controller_name_from_uri) && file_exists($path_2_view_files . $this->controller_name_from_uri)) { $this->view_renderer->prependPath($path_2_view_files . $this->controller_name_from_uri); } return $this->view_renderer->renderToString($file_name, $data); }
//not found page. $resp = $controller_obj; } } return $resp; }; $s3mvc_controller_only_route_handler = function (\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, $args) use($app) { //NOTE: inside this function $this refers to the Slim app's container. // It is automatically bound to this closure by Slim 3 when any of // $app->map or $app->get or $app->post, etc is called. //No action was specified, so invoke the default action on specified //controller. $default_action = S3MVC_APP_DEFAULT_ACTION_NAME; //s3MVC_CreateController could return a Response object if $args['controller'] //doesn't match any existing controller class. $controller_object = s3MVC_CreateController($app, $args['controller'], \Slim3MvcTools\Functions\Str\toDashes($default_action), $request, $response); if ($controller_object instanceof \Slim3MvcTools\Controllers\BaseController && !method_exists($controller_object, $default_action)) { $controller_class_name = get_class($controller_object); //404 Not Found: Action method does not exist in the controller object. $this->get('logger')->notice("`" . __FILE__ . "` on line " . __LINE__ . ": The action method `{$default_action}` does not exist in class `{$controller_class_name}`."); $notFoundHandler = $this->get('notFoundHandler'); //invoke the not found handler return $notFoundHandler($request, $response); } //invoke default action $actn_res = $controller_object instanceof \Slim3MvcTools\Controllers\BaseController ? $controller_object->{$default_action}() : $controller_object; if (is_string($actn_res)) { //write the string in the response object as the response body $response->getBody()->write($actn_res); } elseif ($actn_res instanceof \Psr\Http\Message\ResponseInterface) { $response = $actn_res;