├── .gitignore ├── LICENSE ├── README.md ├── composer.json ├── config └── ide-macros.php └── src ├── Console └── MacrosCommand.php └── IdeMacrosServiceProvider.php /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /composer.lock 3 | /vendor 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 tutorigo 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > [!WARNING] 2 | > This repository is archived because I'm unable to maintain it, as I'm not a web developer anymore and forgot most of this stuff. 3 | > 4 | > Please use an existing fork, or create your own with your changes. 5 | > 6 | > Sorry about this, have fun working on whatever you're currently building :) 7 | 8 | # Laravel IDE Macros 9 | 10 | It is advised to be used with [Laravel IDE Helper](https://github.com/barryvdh/laravel-ide-helper), which generates helper files for your IDE, so it'll be able to highlight and understand some Laravel-specific syntax. 11 | This package provides an additional IDE helper file for Laravel macros with the syntax you are already used to in Laravel IDE Helper. 12 | 13 | ## Installation 14 | Just require it in your Composer file, and you are good to go: 15 | ``` 16 | "tutorigo/laravel-ide-macros": "*" 17 | ``` 18 | If you are using Laravel 5.4 or lower, you must register the `IdeMacrosServiceProvider` manually. 19 | 20 | ## Configuration 21 | Run the following command to publish the configuration file to `config/ide-macros.php`: 22 | ``` 23 | php artisan vendor:publish --provider="Tutorigo\LaravelMacroHelper\IdeMacrosServiceProvider" 24 | ``` 25 | 26 | ## Usage 27 | 28 | ### Generate helper file 29 | Run the following command to generate the macro IDE helpers: 30 | ``` 31 | php artisan ide-helper:macros 32 | ``` 33 | 34 | ### Use of non-static macros 35 | Macros can be both static (ie. `Route::sth()`) and non-static (ie. `Request::route()->sth()`). To distinct the two, use the `@instantiated` tag in the PHPDoc of macros, which depend on `$this`, for example: 36 | ``` 37 | /** 38 | * Gets the amount of route parameters 39 | * 40 | * @return array 41 | * @instantiated 42 | */ 43 | \Illuminate\Routing\Route::macro('parameterCount', function () { 44 | /** @var \Illuminate\Routing\Route $this */ 45 | return count($this->parameters); 46 | }); 47 | ``` 48 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tutorigo/laravel-ide-macros", 3 | "description": "Generating a helper file for IDEs to support Laravel's macros.", 4 | "keywords": [ 5 | "laravel", 6 | "autocomplete", 7 | "ide", 8 | "macros", 9 | "helper", 10 | "phpstorm", 11 | "netbeans", 12 | "sublime", 13 | "codeintel", 14 | "phpdoc" 15 | ], 16 | "license": "MIT", 17 | "authors": [ 18 | { 19 | "name": "Kristóf Morva", 20 | "email": "kristof92@gmail.com" 21 | } 22 | ], 23 | "require": { 24 | "php": ">=7.0", 25 | "laravel/framework": "^5.0|^6.0|^7.0|^8.0|^9.0|^10.0" 26 | }, 27 | "autoload": { 28 | "psr-4": { 29 | "Tutorigo\\LaravelMacroHelper\\": "src/" 30 | } 31 | }, 32 | "extra": { 33 | "laravel": { 34 | "providers": [ 35 | "Tutorigo\\LaravelMacroHelper\\IdeMacrosServiceProvider" 36 | ] 37 | } 38 | }, 39 | "config": { 40 | "preferred-install": "dist" 41 | }, 42 | "minimum-stability": "dev", 43 | "prefer-stable": true 44 | } 45 | -------------------------------------------------------------------------------- /config/ide-macros.php: -------------------------------------------------------------------------------- 1 | '_ide_macros.php', 15 | 16 | /* 17 | |-------------------------------------------------------------------------- 18 | | Macroable Custom Classes 19 | |-------------------------------------------------------------------------- 20 | | 21 | | List here all your classes with FQDN, which are using the Macroable trait. 22 | | 23 | */ 24 | 25 | 'classes' => [ 26 | // 27 | ], 28 | 29 | ]; 30 | -------------------------------------------------------------------------------- /src/Console/MacrosCommand.php: -------------------------------------------------------------------------------- 1 | classes, config('ide-macros.classes', [])); 65 | 66 | $fileName = $this->option('filename') ?: config('ide-macros.filename'); 67 | $this->file = fopen(base_path($fileName), 'w'); 68 | $this->writeLine("hasProperty($propertyName)) { 78 | $propertyName = 'globalMacros'; 79 | if (!$reflection->hasProperty($propertyName)) { 80 | continue; 81 | } 82 | } 83 | 84 | $property = $reflection->getProperty($propertyName); 85 | $property->setAccessible(true); 86 | $macros = $property->getValue(); 87 | 88 | if (!$macros) { 89 | continue; 90 | } 91 | 92 | $this->generateNamespace($reflection->getNamespaceName(), function () use ($macros, $reflection) { 93 | $this->generateClass($reflection->getShortName(), function () use ($macros) { 94 | foreach ($macros as $name => $macro) { 95 | if (is_array($macro)) { 96 | list($class, $method) = $macro; 97 | $function = new \ReflectionMethod(is_object($class) ? get_class($class) : $class, $method); 98 | } else if ($macro instanceof \Closure) { 99 | $function = new \ReflectionFunction($macro); 100 | } else { 101 | $function = new \ReflectionMethod(is_object($macro) ? get_class($macro) : $class, '__invoke'); 102 | } 103 | 104 | if ($comment = $function->getDocComment()) { 105 | $this->writeLine($comment, $this->indent); 106 | 107 | if (strpos($comment, '@instantiated') !== false) { 108 | $this->generateFunction($name, $function->getParameters(), "public", $function->getReturnType()); 109 | continue; 110 | } 111 | } 112 | 113 | $this->generateFunction($name, $function->getParameters(), "public static", $function->getReturnType()); 114 | } 115 | }); 116 | }); 117 | } 118 | 119 | fclose($this->file); 120 | 121 | $this->line("$fileName has been successfully generated.", 'info'); 122 | } 123 | 124 | /** 125 | * @param string $name 126 | * @param null|Callable $callback 127 | */ 128 | protected function generateNamespace($name, $callback = null) 129 | { 130 | $this->writeLine("\nnamespace " . $name . " {", $this->indent); 131 | 132 | if ($callback) { 133 | $this->indent++; 134 | $callback(); 135 | $this->indent--; 136 | } 137 | 138 | $this->writeLine("}", $this->indent); 139 | } 140 | 141 | /** 142 | * @param string $name 143 | * @param null|Callable $callback 144 | */ 145 | protected function generateClass($name, $callback = null) 146 | { 147 | $this->writeLine("class " . $name . " {", $this->indent); 148 | 149 | if ($callback) { 150 | $this->indent++; 151 | $callback(); 152 | $this->indent--; 153 | } 154 | 155 | $this->writeLine("}", $this->indent); 156 | } 157 | 158 | /** 159 | * @param string $name 160 | * @param \ReflectionParameter[] $parameters 161 | * @param string $type 162 | * @param null|string $returnType 163 | * @param null|Callable $callback 164 | * @throws \ReflectionException 165 | */ 166 | protected function generateFunction($name, $parameters, $type = '', $returnType = null, $callback = null) 167 | { 168 | $this->write(($type ? "$type " : '') . "function $name(", $this->indent); 169 | 170 | $index = 0; 171 | foreach ($parameters as $parameter) { 172 | if ($index) { 173 | $this->write(", "); 174 | } 175 | 176 | if ($parameter->isVariadic()) { 177 | $this->write('...'); 178 | } 179 | 180 | if ($parameter->hasType()) { 181 | if (version_compare(PHP_VERSION, '7.1', '<')) { 182 | $this->write($parameter->getType() . " "); 183 | } else { 184 | $paramType = $parameter->getType(); 185 | if ($paramType instanceof \ReflectionNamedType) { 186 | if ($paramType->allowsNull()) { 187 | $this->write("?"); 188 | } 189 | $this->write($paramType->getName() . " "); 190 | } 191 | } 192 | } 193 | 194 | $this->write("$" . $parameter->getName()); 195 | if ($parameter->isOptional() && !$parameter->isVariadic()) { 196 | $this->write(" = " . var_export($parameter->getDefaultValue(), true)); 197 | } 198 | 199 | $index++; 200 | } 201 | 202 | $this->write(")"); 203 | if (version_compare(PHP_VERSION, '7.1', '<')) { 204 | if ($returnType) { 205 | if (class_exists($returnType)) { 206 | $this->write(": \\$returnType"); 207 | } else { 208 | $this->write(": $returnType"); 209 | } 210 | } 211 | } elseif ($returnType instanceof \ReflectionNamedType) { 212 | $this->write(": "); 213 | if ($returnType->allowsNull()) { 214 | $this->write("?"); 215 | } 216 | if (class_exists($returnType->getName())) { 217 | $this->write("\\"); 218 | } 219 | $this->write($returnType->getName()); 220 | } 221 | $this->writeLine(" {"); 222 | 223 | if ($callback) { 224 | $callback(); 225 | } 226 | 227 | $this->writeLine(); 228 | $this->writeLine("}", $this->indent); 229 | } 230 | 231 | protected function write($string, $indent = 0) 232 | { 233 | fwrite($this->file, str_repeat(' ', $indent) . $string); 234 | } 235 | 236 | protected function writeLine($line = '', $indent = 0) 237 | { 238 | $this->write($line . PHP_EOL, $indent); 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /src/IdeMacrosServiceProvider.php: -------------------------------------------------------------------------------- 1 | publishes([ 17 | __DIR__ . '/../config/ide-macros.php' => config_path('ide-macros.php'), 18 | ]); 19 | 20 | if ($this->app->runningInConsole()) { 21 | $this->commands([ 22 | Console\MacrosCommand::class, 23 | ]); 24 | } 25 | } 26 | 27 | /** 28 | * Register bindings in the container. 29 | * 30 | * @return void 31 | */ 32 | public function register() 33 | { 34 | $this->mergeConfigFrom(__DIR__ . '/../config/ide-macros.php', 'ide-macros'); 35 | } 36 | } 37 | --------------------------------------------------------------------------------