├── .gitignore ├── phpunit.xml ├── composer.json ├── LICENSE.md ├── README.md └── src └── RoutesPublisherCommand.php /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | composer.phar 3 | composer.lock 4 | .DS_Store -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | ./tests/ 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "themsaid/laravel-routes-publisher", 3 | "description": "A command to replace deprecated Route::controller with explicit routes.", 4 | "keywords": ["laravel", "routes"], 5 | "homepage": "https://github.com/themsaid/laravel-routes-publisher", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "Mohamed Said", 10 | "email": "theMohamedSaid@gmail.com" 11 | } 12 | ], 13 | "require": { 14 | "php": ">=5.5.9", 15 | "illuminate/support": "^5.2" 16 | }, 17 | "autoload": { 18 | "psr-4": { 19 | "Themsaid\\RoutesPublisher\\": "src" 20 | } 21 | }, 22 | "extra": { 23 | "laravel": { 24 | "providers": [ 25 | "Themsaid\\RoutesPublisher\\RoutesPublisherCommand" 26 | ] 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Mohamed Said 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 13 | > all 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 21 | > THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel Routes Publisher 2 | 3 | A command to replace deprecated `Route::controller()` and `Route::controllers()` with explicit routes. 4 | 5 | ![what it does](http://s17.postimg.org/x5q8vfrfz/Screen_Shot_2016_03_23_at_12_36_34_PM.png) 6 | 7 | In laravel 5.3 implicit controller routes will be removed from the framework, the functionality will likely be extracted into a separate 8 | package, however if you'd like to make the move and start using explicit routes this package will help you. 9 | 10 | # Installation 11 | 12 | #### Step 1: 13 | 14 | ``` 15 | composer require themsaid/laravel-routes-publisher 16 | ``` 17 | 18 | #### Step 2: 19 | 20 | Include the following command in your `$commands` attribute of `app/Console/Kernel.php`: 21 | 22 | ``` 23 | \Themsaid\RoutesPublisher\RoutesPublisherCommand::class 24 | ``` 25 | 26 | # Usage 27 | 28 | Run the following command: 29 | 30 | ``` 31 | php artisan themsaid:publishRoutes 32 | ``` 33 | 34 | After the command is done, two new files will be generated in your `app/Http` directory: 35 | 36 | ``` 37 | routes.php.generated 38 | routes.php.backup 39 | ``` 40 | 41 | Replace the content of your `routes.php` file with that of `routes.php.generated`, knowing that if anything went wrong a backup 42 | of your original `routes.php`'s content will be available in `routes.php.backup`. 43 | 44 | #### This package assumes the following: 45 | 46 | - Your `routes.php` doesn't contain any PHP syntax errors. 47 | - Your `routes.php` file is located in `app\Http\routes.php` with the exact name. 48 | - Your `routes.php` files doesn't include any other file using `include` or `require`. 49 | - Your Application namespace is correctly registered in the psr-4 section of `composer.json`. 50 | 51 | # Problems? 52 | I tried hard to cover different syntax and file formatting in this package, however if you found any problems while using the 53 | package please [open a new issue](https://github.com/themsaid/laravel-routes-publisher/issues/new). -------------------------------------------------------------------------------- /src/RoutesPublisherCommand.php: -------------------------------------------------------------------------------- 1 | controllersNamespace = $application->getNamespace().$this->controllersNamespace; 52 | } 53 | 54 | /** 55 | * Execute the console command. 56 | * 57 | * @return mixed 58 | */ 59 | public function handle() 60 | { 61 | $exactFileContent = file_get_contents(base_path($this->routesFilePath)); 62 | 63 | $preparedFileContent = $this->prepareFileContent($exactFileContent); 64 | 65 | $output = ''; 66 | 67 | foreach (explode("\n", $preparedFileContent) as $line) { 68 | $preparedLine = $this->prepareLine($line); 69 | 70 | if (preg_match('/controller(?:[^s\(]*)\(([^,]*),([^,)]*)/', $preparedLine, $matches)) { 71 | if (count($matches) != 3) { 72 | $this->error($preparedLine.' Looks weird, unable to parse it.'); 73 | } 74 | 75 | preg_match('/^( *)/', $line, $spaces); 76 | 77 | $output .= $this->extractController(trim($matches[1], '\''), trim($matches[2], '\''), $spaces[1]); 78 | } elseif (preg_match('/controllers(?:[^\(]*)\((.*)\)/', $preparedLine, $matches)) { 79 | preg_match('/^( *)/', $line, $spaces); 80 | 81 | $output .= $this->extractControllers($matches[1], $spaces[1]); 82 | } else { 83 | $output .= $line."\n"; 84 | } 85 | } 86 | 87 | file_put_contents(base_path($this->routesFilePath . '.generated'), $output); 88 | 89 | file_put_contents(base_path($this->routesFilePath . '.backup'), $preparedFileContent); 90 | 91 | $this->info('Done! Generated file was published in "'.base_path($this->routesFilePath . '.generated').'"'); 92 | 93 | $this->info('Also a backup of '. basename('$this->routesFilePath') .' was published in "'.base_path($this->routesFilePath . '.backup').'"'); 94 | } 95 | 96 | /** 97 | * Prepare file content for parsing. 98 | * 99 | * @param string $fileContent 100 | * 101 | * @return string 102 | */ 103 | private function prepareFileContent($fileContent) 104 | { 105 | // Remove 1 line comments 106 | $fileContent = preg_replace("#(.*)//(.*)#", " ", $fileContent); 107 | 108 | // Remove multi-line comments 109 | $fileContent = preg_replace("#/\*(.*)\*?/#", "", $fileContent); 110 | 111 | // Remove all new line characters 112 | $fileContent = preg_replace("/\n*/", "", $fileContent); 113 | 114 | // Add 2 new line characters after [\'"]([^\'"]*)[\'"]/', $arrayString, $matches); 150 | 151 | $routes = ''; 152 | 153 | foreach (array_combine($matches[1], $matches[2]) as $path => $controller) { 154 | $routes .= $this->extractController($path, $controller, $initialSpace); 155 | } 156 | 157 | return $routes; 158 | } 159 | 160 | /** 161 | * Extract routes from a given controller 162 | * 163 | * @param string $path 164 | * @param string $controller 165 | * 166 | * @param string $initialSpace 167 | * 168 | * @return string 169 | */ 170 | private function extractController($path, $controller, $initialSpace = '') 171 | { 172 | $class = new ReflectionClass($this->controllersNamespace.'\\'.$controller); 173 | 174 | $methods = $class->getMethods(ReflectionMethod::IS_PUBLIC); 175 | 176 | $routables = array_filter($methods, function ($method) { 177 | return 178 | $method->class != 'Illuminate\Routing\Controller' && 179 | Str::startsWith($method->name, ['any', 'get', 'post', 'put', 'delete', 'patch']); 180 | }); 181 | 182 | $routes = "\n$initialSpace// $controller\n"; 183 | 184 | foreach ($routables as $routable) { 185 | $routes .= $initialSpace.$this->createRoute($routable, $path, $controller); 186 | } 187 | 188 | return $routes; 189 | } 190 | 191 | /** 192 | * @param ReflectionMethod $routable 193 | * @param string $path 194 | * @param string $controller 195 | * 196 | * @return string 197 | */ 198 | private function createRoute(ReflectionMethod $routable, $path, $controller) 199 | { 200 | $verb = $this->getVerb($routable->name); 201 | 202 | $uri = $this->getUri($routable, $path); 203 | 204 | return 'Route::'."$verb('$uri', '$controller@{$routable->name}');\n"; 205 | } 206 | 207 | /** 208 | * Get the verb of the route from name. 209 | * 210 | * @param string $name 211 | * 212 | * @return string 213 | */ 214 | public function getVerb($name) 215 | { 216 | return head(explode('_', Str::snake($name))); 217 | } 218 | 219 | /** 220 | * Determine the URI from the given method name. 221 | * 222 | * @param ReflectionMethod $routable 223 | * @param string $path 224 | * 225 | * @return string 226 | */ 227 | public function getUri(ReflectionMethod $routable, $path) 228 | { 229 | $uri = 230 | $path 231 | .'/' 232 | .implode('-', array_slice(explode('_', Str::snake($routable->name)), 1)) 233 | .'/' 234 | .$this->getWildcards($routable); 235 | 236 | $uri = str_replace('//', '/', $uri); 237 | 238 | $uri = rtrim($uri, '/'); 239 | 240 | if (Str::endsWith($uri, 'index')) { 241 | $uri = Str::replaceLast('index', '', $uri); 242 | } 243 | 244 | return $uri; 245 | } 246 | 247 | /** 248 | * Get the wildcards string for the route URI. 249 | * 250 | * @param ReflectionMethod $routable 251 | * 252 | * @return string 253 | */ 254 | private function getWildcards(ReflectionMethod $routable) 255 | { 256 | $output = ''; 257 | 258 | foreach ($routable->getParameters() as $parameter) { 259 | if ($parameter->hasType()) { 260 | continue; 261 | } 262 | 263 | $wildCard = Str::snake($parameter->getName()).($parameter->isDefaultValueAvailable() ? '?' : ''); 264 | 265 | $output .= '{'.$wildCard.'}/'; 266 | } 267 | 268 | return $output; 269 | } 270 | } 271 | --------------------------------------------------------------------------------