chore: 添加缺失的静态资源文件
添加多个前端界面所需的图片、字体、音频等静态资源文件,包括: - 管理员后台的图标、背景图、组件图片 - 移动端页面的商品图片、用户中心图片、活动图标 - 第三方库的示例图片和字体文件 - 浏览器兼容性配置文件 - 图标字体文件(eot、ttf、woff、woff2格式) 这些资源是前端界面正常显示所必需的,之前可能因版本控制忽略或遗漏而缺失。
This commit is contained in:
43
vendor/nette/php-generator/composer.json
vendored
Normal file
43
vendor/nette/php-generator/composer.json
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "nette/php-generator",
|
||||
"description": "🐘 Nette PHP Generator: generates neat PHP code for you. Supports new PHP 8.1 features.",
|
||||
"keywords": ["nette", "php", "code", "scaffolding"],
|
||||
"homepage": "https://nette.org",
|
||||
"license": ["BSD-3-Clause", "GPL-2.0-only", "GPL-3.0-only"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "David Grudl",
|
||||
"homepage": "https://davidgrudl.com"
|
||||
},
|
||||
{
|
||||
"name": "Nette Community",
|
||||
"homepage": "https://nette.org/contributors"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.2 <8.3",
|
||||
"nette/utils": "^3.1.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"nette/tester": "^2.4",
|
||||
"nikic/php-parser": "^4.13",
|
||||
"tracy/tracy": "^2.8",
|
||||
"phpstan/phpstan": "^0.12"
|
||||
},
|
||||
"suggest": {
|
||||
"nikic/php-parser": "to use ClassType::withBodiesFrom() & GlobalFunction::withBodyFrom()"
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": ["src/"]
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"scripts": {
|
||||
"phpstan": "phpstan analyse",
|
||||
"tester": "tester tests -s"
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.6-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
60
vendor/nette/php-generator/license.md
vendored
Normal file
60
vendor/nette/php-generator/license.md
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
Licenses
|
||||
========
|
||||
|
||||
Good news! You may use Nette Framework under the terms of either
|
||||
the New BSD License or the GNU General Public License (GPL) version 2 or 3.
|
||||
|
||||
The BSD License is recommended for most projects. It is easy to understand and it
|
||||
places almost no restrictions on what you can do with the framework. If the GPL
|
||||
fits better to your project, you can use the framework under this license.
|
||||
|
||||
You don't have to notify anyone which license you are using. You can freely
|
||||
use Nette Framework in commercial projects as long as the copyright header
|
||||
remains intact.
|
||||
|
||||
Please be advised that the name "Nette Framework" is a protected trademark and its
|
||||
usage has some limitations. So please do not use word "Nette" in the name of your
|
||||
project or top-level domain, and choose a name that stands on its own merits.
|
||||
If your stuff is good, it will not take long to establish a reputation for yourselves.
|
||||
|
||||
|
||||
New BSD License
|
||||
---------------
|
||||
|
||||
Copyright (c) 2004, 2014 David Grudl (https://davidgrudl.com)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of "Nette Framework" nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
This software is provided by the copyright holders and contributors "as is" and
|
||||
any express or implied warranties, including, but not limited to, the implied
|
||||
warranties of merchantability and fitness for a particular purpose are
|
||||
disclaimed. In no event shall the copyright owner or contributors be liable for
|
||||
any direct, indirect, incidental, special, exemplary, or consequential damages
|
||||
(including, but not limited to, procurement of substitute goods or services;
|
||||
loss of use, data, or profits; or business interruption) however caused and on
|
||||
any theory of liability, whether in contract, strict liability, or tort
|
||||
(including negligence or otherwise) arising in any way out of the use of this
|
||||
software, even if advised of the possibility of such damage.
|
||||
|
||||
|
||||
GNU General Public License
|
||||
--------------------------
|
||||
|
||||
GPL licenses are very very long, so instead of including them here we offer
|
||||
you URLs with full text:
|
||||
|
||||
- [GPL version 2](http://www.gnu.org/licenses/gpl-2.0.html)
|
||||
- [GPL version 3](http://www.gnu.org/licenses/gpl-3.0.html)
|
||||
14
vendor/nette/php-generator/ncs.php
vendored
Normal file
14
vendor/nette/php-generator/ncs.php
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Rules for Nette Coding Standard
|
||||
* https://github.com/nette/coding-standard
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
return [
|
||||
// constant NULL, FALSE in src/PhpGenerator/Type.php
|
||||
'constant_case' => false,
|
||||
'lowercase_static_reference' => false,
|
||||
];
|
||||
779
vendor/nette/php-generator/readme.md
vendored
Normal file
779
vendor/nette/php-generator/readme.md
vendored
Normal file
@@ -0,0 +1,779 @@
|
||||
Nette PHP Generator
|
||||
===================
|
||||
|
||||
[](https://packagist.org/packages/nette/php-generator)
|
||||
[](https://github.com/nette/php-generator/actions)
|
||||
[](https://coveralls.io/github/nette/php-generator?branch=master)
|
||||
[](https://github.com/nette/php-generator/releases)
|
||||
[](https://github.com/nette/php-generator/blob/master/license.md)
|
||||
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Do you need to generate PHP code of classes, functions, namespaces, etc.? This library with a friendly API will help you.
|
||||
|
||||
Documentation can be found on the [website](https://doc.nette.org/php-generator).
|
||||
|
||||
|
||||
[Support Me](https://github.com/sponsors/dg)
|
||||
--------------------------------------------
|
||||
|
||||
Do you like PHP Generator? Are you looking forward to the new features?
|
||||
|
||||
[](https://github.com/sponsors/dg)
|
||||
|
||||
Thank you!
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
```shell
|
||||
composer require nette/php-generator
|
||||
```
|
||||
|
||||
- PhpGenerator 3.6 is compatible with PHP 7.2 to 8.1
|
||||
- PhpGenerator 3.2 – 3.5 is compatible with PHP 7.1 to 8.0
|
||||
- PhpGenerator 3.1 is compatible with PHP 7.1 to 7.3
|
||||
- PhpGenerator 3.0 is compatible with PHP 7.0 to 7.3
|
||||
- PhpGenerator 2.6 is compatible with PHP 5.6 to 7.3
|
||||
|
||||
|
||||
|
||||
Classes
|
||||
-------
|
||||
|
||||
Let's start with a straightforward example of generating class using [ClassType](https://api.nette.org/php-generator/Nette/PhpGenerator/ClassType.html):
|
||||
|
||||
```php
|
||||
$class = new Nette\PhpGenerator\ClassType('Demo');
|
||||
|
||||
$class
|
||||
->setFinal()
|
||||
->setExtends(ParentClass::class)
|
||||
->addImplement(Countable::class)
|
||||
->addComment("Description of class.\nSecond line\n")
|
||||
->addComment('@property-read Nette\Forms\Form $form');
|
||||
|
||||
// to generate PHP code simply cast to string or use echo:
|
||||
echo $class;
|
||||
```
|
||||
|
||||
It will render this result:
|
||||
|
||||
```php
|
||||
/**
|
||||
* Description of class.
|
||||
* Second line
|
||||
*
|
||||
* @property-read Nette\Forms\Form $form
|
||||
*/
|
||||
final class Demo extends ParentClass implements Countable
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
We can also use a printer to generate the code, which, unlike `echo $class`, we will be able to further configure:
|
||||
|
||||
```php
|
||||
$printer = new Nette\PhpGenerator\Printer;
|
||||
echo $printer->printClass($class);
|
||||
```
|
||||
|
||||
We can add constants ([Constant](https://api.nette.org/php-generator/Nette/PhpGenerator/Constant.html)) and properties ([Property](https://api.nette.org/php-generator/Nette/PhpGenerator/Property.html)):
|
||||
|
||||
```php
|
||||
$class->addConstant('ID', 123)
|
||||
->setProtected() // constant visiblity
|
||||
->setFinal();
|
||||
|
||||
$class->addProperty('items', [1, 2, 3])
|
||||
->setPrivate() // or setVisibility('private')
|
||||
->setStatic()
|
||||
->addComment('@var int[]');
|
||||
|
||||
$class->addProperty('list')
|
||||
->setType('array')
|
||||
->setNullable()
|
||||
->setInitialized(); // prints '= null'
|
||||
```
|
||||
|
||||
It generates:
|
||||
|
||||
```php
|
||||
final protected const ID = 123;
|
||||
|
||||
/** @var int[] */
|
||||
private static $items = [1, 2, 3];
|
||||
|
||||
public ?array $list = null;
|
||||
```
|
||||
|
||||
And we can add methods with parameters:
|
||||
|
||||
```php
|
||||
$method = $class->addMethod('count')
|
||||
->addComment('Count it.')
|
||||
->addComment('@return int')
|
||||
->setFinal()
|
||||
->setProtected()
|
||||
->setReturnType('int') // method return type
|
||||
->setReturnNullable() // nullable return type
|
||||
->setBody('return count($items ?: $this->items);');
|
||||
|
||||
$method->addParameter('items', []) // $items = []
|
||||
->setReference() // &$items = []
|
||||
->setType('array'); // array &$items = []
|
||||
```
|
||||
|
||||
It results in:
|
||||
|
||||
```php
|
||||
/**
|
||||
* Count it.
|
||||
* @return int
|
||||
*/
|
||||
final protected function count(array &$items = []): ?int
|
||||
{
|
||||
return count($items ?: $this->items);
|
||||
}
|
||||
```
|
||||
|
||||
Promoted parameters introduced by PHP 8.0 can be passed to the constructor:
|
||||
|
||||
```php
|
||||
$method = $class->addMethod('__construct');
|
||||
$method->addPromotedParameter('name');
|
||||
$method->addPromotedParameter('args', [])
|
||||
->setPrivate();
|
||||
```
|
||||
|
||||
It results in:
|
||||
|
||||
```php
|
||||
public function __construct(
|
||||
public $name,
|
||||
private $args = [],
|
||||
) {
|
||||
}
|
||||
```
|
||||
|
||||
Readonly properties introduced by PHP 8.1 can be marked via `setReadOnly()`.
|
||||
|
||||
------
|
||||
|
||||
If the added property, constant, method or parameter already exist, it will be overwritten.
|
||||
|
||||
Members can be removed using `removeProperty()`, `removeConstant()`, `removeMethod()` or `removeParameter()`.
|
||||
|
||||
You can also add existing `Method`, `Property` or `Constant` objects to the class:
|
||||
|
||||
```php
|
||||
$method = new Nette\PhpGenerator\Method('getHandle');
|
||||
$property = new Nette\PhpGenerator\Property('handle');
|
||||
$const = new Nette\PhpGenerator\Constant('ROLE');
|
||||
|
||||
$class = (new Nette\PhpGenerator\ClassType('Demo'))
|
||||
->addMember($method)
|
||||
->addMember($property)
|
||||
->addMember($const);
|
||||
```
|
||||
|
||||
You can clone existing methods, properties and constants with a different name using `cloneWithName()`:
|
||||
|
||||
```php
|
||||
$methodCount = $class->getMethod('count');
|
||||
$methodRecount = $methodCount->cloneWithName('recount');
|
||||
$class->addMember($methodRecount);
|
||||
```
|
||||
|
||||
Types
|
||||
-----
|
||||
|
||||
Each type or union/intersection type can be passed as a string, you can also use predefined constants for native types:
|
||||
|
||||
```php
|
||||
use Nette\PhpGenerator\Type;
|
||||
|
||||
$member->setType('array'); // or Type::ARRAY;
|
||||
$member->setType('array|string'); // or Type::union('array', 'string')
|
||||
$member->setType('Foo&Bar'); // or Type::intersection(Foo::class, Bar::class)
|
||||
$member->setType(null); // removes type
|
||||
```
|
||||
|
||||
The same applies to the method `setReturnType()`.
|
||||
|
||||
|
||||
Tabs versus Spaces
|
||||
------------------
|
||||
|
||||
The generated code uses tabs for indentation. If you want to have the output compatible with PSR-2 or PSR-12, use `PsrPrinter`:
|
||||
|
||||
```php
|
||||
$class = new Nette\PhpGenerator\ClassType('Demo');
|
||||
// ...
|
||||
|
||||
$printer = new Nette\PhpGenerator\PsrPrinter;
|
||||
echo $printer->printClass($class); // 4 spaces indentation
|
||||
```
|
||||
|
||||
|
||||
Interface or Trait
|
||||
------------------
|
||||
|
||||
You can create interfaces and traits:
|
||||
|
||||
```php
|
||||
$interface = Nette\PhpGenerator\ClassType::interface('MyInterface');
|
||||
$trait = Nette\PhpGenerator\ClassType::trait('MyTrait');
|
||||
// in a similar way $class = Nette\PhpGenerator\ClassType::class('MyClass');
|
||||
```
|
||||
|
||||
Enums
|
||||
-----
|
||||
|
||||
You can easily create the enums that PHP 8.1 brings:
|
||||
|
||||
```php
|
||||
$enum = Nette\PhpGenerator\ClassType::enum('Suit');
|
||||
$enum->addCase('Clubs');
|
||||
$enum->addCase('Diamonds');
|
||||
$enum->addCase('Hearts');
|
||||
$enum->addCase('Spades');
|
||||
|
||||
echo $enum;
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```php
|
||||
enum Suit
|
||||
{
|
||||
case Clubs;
|
||||
case Diamonds;
|
||||
case Hearts;
|
||||
case Spades;
|
||||
}
|
||||
```
|
||||
|
||||
You can also define scalar equivalents for cases to create a backed enum:
|
||||
|
||||
```php
|
||||
$enum->addCase('Clubs', '♣');
|
||||
$enum->addCase('Diamonds', '♦');
|
||||
```
|
||||
|
||||
It is possible to add a comment or [attributes](#attributes) to each case using `addComment()` or `addAttribute()`.
|
||||
|
||||
|
||||
Literals
|
||||
--------
|
||||
|
||||
With `Literal` you can pass arbitrary PHP code to, for example, default property or parameter values etc:
|
||||
|
||||
```php
|
||||
use Nette\PhpGenerator\Literal;
|
||||
|
||||
$class = new Nette\PhpGenerator\ClassType('Demo');
|
||||
|
||||
$class->addProperty('foo', new Literal('Iterator::SELF_FIRST'));
|
||||
|
||||
$class->addMethod('bar')
|
||||
->addParameter('id', new Literal('1 + 2'));
|
||||
|
||||
echo $class;
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```php
|
||||
class Demo
|
||||
{
|
||||
public $foo = Iterator::SELF_FIRST;
|
||||
|
||||
public function bar($id = 1 + 2)
|
||||
{
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can also pass parameters to `Literal` and have it formatted into valid PHP code using [special placeholders](#method-and-function-body-generator):
|
||||
|
||||
```php
|
||||
new Literal('substr(?, ?)', [$a, $b]);
|
||||
// generates, for example: substr('hello', 5);
|
||||
```
|
||||
|
||||
|
||||
|
||||
Using Traits
|
||||
------------
|
||||
|
||||
```php
|
||||
$class = new Nette\PhpGenerator\ClassType('Demo');
|
||||
$class->addTrait('SmartObject');
|
||||
$class->addTrait('MyTrait', true)
|
||||
->addResolution('sayHello as protected')
|
||||
->addComment('@use MyTrait<Foo>');
|
||||
echo $class;
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```php
|
||||
class Demo
|
||||
{
|
||||
use SmartObject;
|
||||
/** @use MyTrait<Foo> */
|
||||
use MyTrait {
|
||||
sayHello as protected;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Anonymous Class
|
||||
---------------
|
||||
|
||||
Give `null` as the name and you have an anonymous class:
|
||||
|
||||
```php
|
||||
$class = new Nette\PhpGenerator\ClassType(null);
|
||||
$class->addMethod('__construct')
|
||||
->addParameter('foo');
|
||||
|
||||
echo '$obj = new class ($val) ' . $class . ';';
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```php
|
||||
$obj = new class ($val) {
|
||||
|
||||
public function __construct($foo)
|
||||
{
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
Global Function
|
||||
---------------
|
||||
|
||||
Code of functions will generate class [GlobalFunction](https://api.nette.org/php-generator/Nette/PhpGenerator/GlobalFunction.html):
|
||||
|
||||
```php
|
||||
$function = new Nette\PhpGenerator\GlobalFunction('foo');
|
||||
$function->setBody('return $a + $b;');
|
||||
$function->addParameter('a');
|
||||
$function->addParameter('b');
|
||||
echo $function;
|
||||
|
||||
// or use PsrPrinter for output compatible with PSR-2 / PSR-12
|
||||
// echo (new Nette\PhpGenerator\PsrPrinter)->printFunction($function);
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```php
|
||||
function foo($a, $b)
|
||||
{
|
||||
return $a + $b;
|
||||
}
|
||||
```
|
||||
|
||||
Closure
|
||||
-------
|
||||
|
||||
Code of closures will generate class [Closure](https://api.nette.org/php-generator/Nette/PhpGenerator/Closure.html):
|
||||
|
||||
```php
|
||||
$closure = new Nette\PhpGenerator\Closure;
|
||||
$closure->setBody('return $a + $b;');
|
||||
$closure->addParameter('a');
|
||||
$closure->addParameter('b');
|
||||
$closure->addUse('c')
|
||||
->setReference();
|
||||
echo $closure;
|
||||
|
||||
// or use PsrPrinter for output compatible with PSR-2 / PSR-12
|
||||
// echo (new Nette\PhpGenerator\PsrPrinter)->printClosure($closure);
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```php
|
||||
function ($a, $b) use (&$c) {
|
||||
return $a + $b;
|
||||
}
|
||||
```
|
||||
|
||||
Arrow Function
|
||||
--------------
|
||||
|
||||
You can also print closure as arrow function using printer:
|
||||
|
||||
```php
|
||||
$closure = new Nette\PhpGenerator\Closure;
|
||||
$closure->setBody('$a + $b');
|
||||
$closure->addParameter('a');
|
||||
$closure->addParameter('b');
|
||||
|
||||
// or use PsrPrinter for output compatible with PSR-2 / PSR-12
|
||||
echo (new Nette\PhpGenerator\Printer)->printArrowFunction($closure);
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```php
|
||||
fn($a, $b) => $a + $b
|
||||
```
|
||||
|
||||
Attributes
|
||||
----------
|
||||
|
||||
You can add PHP 8 attributes to all classes, methods, properties, constants, enum cases, functions, closures and parameters.
|
||||
|
||||
```php
|
||||
$class = new Nette\PhpGenerator\ClassType('Demo');
|
||||
$class->addAttribute('Deprecated');
|
||||
|
||||
$class->addProperty('list')
|
||||
->addAttribute('WithArguments', [1, 2]);
|
||||
|
||||
$method = $class->addMethod('count')
|
||||
->addAttribute('Foo\Cached', ['mode' => true]);
|
||||
|
||||
$method->addParameter('items')
|
||||
->addAttribute('Bar');
|
||||
|
||||
echo $class;
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```php
|
||||
#[Deprecated]
|
||||
class Demo
|
||||
{
|
||||
#[WithArguments(1, 2)]
|
||||
public $list;
|
||||
|
||||
|
||||
#[Foo\Cached(mode: true)]
|
||||
public function count(#[Bar] $items)
|
||||
{
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Method and Function Body Generator
|
||||
----------------------------------
|
||||
|
||||
The body can be passed to the `setBody()` method at once or sequentially (line by line) by repeatedly calling `addBody()`:
|
||||
|
||||
```php
|
||||
$function = new Nette\PhpGenerator\GlobalFunction('foo');
|
||||
$function->addBody('$a = rand(10, 20);');
|
||||
$function->addBody('return $a;');
|
||||
echo $function;
|
||||
```
|
||||
|
||||
Result
|
||||
|
||||
```php
|
||||
function foo()
|
||||
{
|
||||
$a = rand(10, 20);
|
||||
return $a;
|
||||
}
|
||||
```
|
||||
|
||||
You can use special placeholders for handy way to inject variables.
|
||||
|
||||
Simple placeholders `?`
|
||||
|
||||
```php
|
||||
$str = 'any string';
|
||||
$num = 3;
|
||||
$function = new Nette\PhpGenerator\GlobalFunction('foo');
|
||||
$function->addBody('return substr(?, ?);', [$str, $num]);
|
||||
echo $function;
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```php
|
||||
function foo()
|
||||
{
|
||||
return substr('any string', 3);
|
||||
}
|
||||
```
|
||||
|
||||
Variadic placeholder `...?`
|
||||
|
||||
```php
|
||||
$items = [1, 2, 3];
|
||||
$function = new Nette\PhpGenerator\GlobalFunction('foo');
|
||||
$function->setBody('myfunc(...?);', [$items]);
|
||||
echo $function;
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```php
|
||||
function foo()
|
||||
{
|
||||
myfunc(1, 2, 3);
|
||||
}
|
||||
```
|
||||
|
||||
You can also use PHP 8 named parameters using placeholder `...?:`
|
||||
|
||||
```php
|
||||
$items = ['foo' => 1, 'bar' => true];
|
||||
$function->setBody('myfunc(...?:);', [$items]);
|
||||
|
||||
// myfunc(foo: 1, bar: true);
|
||||
```
|
||||
|
||||
Escape placeholder using slash `\?`
|
||||
|
||||
```php
|
||||
$num = 3;
|
||||
$function = new Nette\PhpGenerator\GlobalFunction('foo');
|
||||
$function->addParameter('a');
|
||||
$function->addBody('return $a \? 10 : ?;', [$num]);
|
||||
echo $function;
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```php
|
||||
function foo($a)
|
||||
{
|
||||
return $a ? 10 : 3;
|
||||
}
|
||||
```
|
||||
|
||||
Namespace
|
||||
---------
|
||||
|
||||
Classes, traits, interfaces and enums (hereinafter classes) can be grouped into namespaces ([PhpNamespace](https://api.nette.org/php-generator/Nette/PhpGenerator/PhpNamespace.html)):
|
||||
|
||||
```php
|
||||
$namespace = new Nette\PhpGenerator\PhpNamespace('Foo');
|
||||
|
||||
// create new classes in the namespace
|
||||
$class = $namespace->addClass('Task');
|
||||
$interface = $namespace->addInterface('Countable');
|
||||
$trait = $namespace->addTrait('NameAware');
|
||||
|
||||
// or insert an existing class into the namespace
|
||||
$class = new Nette\PhpGenerator\ClassType('Task');
|
||||
$namespace->add($class);
|
||||
```
|
||||
|
||||
If the class already exists, it will be overwritten.
|
||||
|
||||
You can define use-statements:
|
||||
|
||||
```php
|
||||
// use Http\Request;
|
||||
$namespace->addUse(Http\Request::class);
|
||||
// use Http\Request as HttpReq;
|
||||
$namespace->addUse(Http\Request::class, 'HttpReq');
|
||||
// use function iter\range;
|
||||
$namespace->addUseFunction('iter\range');
|
||||
```
|
||||
|
||||
To simplify a fully qualified class, function or constant name according to the defined aliases, use the `simplifyName` method:
|
||||
|
||||
```php
|
||||
echo $namespace->simplifyName('Foo\Bar'); // 'Bar', because 'Foo' is current namespace
|
||||
echo $namespace->simplifyName('iter\range', $namespace::NameFunction); // 'range', because of the defined use-statement
|
||||
```
|
||||
|
||||
Conversely, you can convert a simplified class, function or constant name to a fully qualified one using the `resolveName` method:
|
||||
|
||||
```php
|
||||
echo $namespace->resolveName('Bar'); // 'Foo\Bar'
|
||||
echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range'
|
||||
```
|
||||
|
||||
Class Names Resolving
|
||||
---------------------
|
||||
|
||||
**When the class is part of the namespace, it is rendered slightly differently**: all types (ie. type hints, return types, parent class name,
|
||||
implemented interfaces, used traits and attributes) are automatically *resolved* (unless you turn it off, see below).
|
||||
It means that you have to **use full class names** in definitions and they will be replaced
|
||||
with aliases (according to the use-statements) or fully qualified names in the resulting code:
|
||||
|
||||
```php
|
||||
$namespace = new Nette\PhpGenerator\PhpNamespace('Foo');
|
||||
$namespace->addUse('Bar\AliasedClass');
|
||||
|
||||
$class = $namespace->addClass('Demo');
|
||||
$class->addImplement('Foo\A') // it will simplify to A
|
||||
->addTrait('Bar\AliasedClass'); // it will simplify to AliasedClass
|
||||
|
||||
$method = $class->addMethod('method');
|
||||
$method->addComment('@return ' . $namespace->simplifyType('Foo\D')); // in comments simplify manually
|
||||
$method->addParameter('arg')
|
||||
->setType('Bar\OtherClass'); // it will resolve to \Bar\OtherClass
|
||||
|
||||
echo $namespace;
|
||||
|
||||
// or use PsrPrinter for output compatible with PSR-2 / PSR-12
|
||||
// echo (new Nette\PhpGenerator\PsrPrinter)->printNamespace($namespace);
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```php
|
||||
namespace Foo;
|
||||
|
||||
use Bar\AliasedClass;
|
||||
|
||||
class Demo implements A
|
||||
{
|
||||
use AliasedClass;
|
||||
|
||||
/**
|
||||
* @return D
|
||||
*/
|
||||
public function method(\Bar\OtherClass $arg)
|
||||
{
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Auto-resolving can be turned off this way:
|
||||
|
||||
```php
|
||||
$printer = new Nette\PhpGenerator\Printer; // or PsrPrinter
|
||||
$printer->setTypeResolving(false);
|
||||
echo $printer->printNamespace($namespace);
|
||||
```
|
||||
|
||||
PHP Files
|
||||
---------
|
||||
|
||||
Classes, functions and namespaces can be grouped into PHP files represented by the class [PhpFile](https://api.nette.org/php-generator/Nette/PhpGenerator/PhpFile.html):
|
||||
|
||||
```php
|
||||
$file = new Nette\PhpGenerator\PhpFile;
|
||||
$file->addComment('This file is auto-generated.');
|
||||
$file->setStrictTypes(); // adds declare(strict_types=1)
|
||||
|
||||
$class = $file->addClass('Foo\A');
|
||||
$function = $file->addFunction('Foo\foo');
|
||||
|
||||
// or
|
||||
// $namespace = $file->addNamespace('Foo');
|
||||
// $class = $namespace->addClass('A');
|
||||
// $function = $namespace->addFunction('foo');
|
||||
|
||||
echo $file;
|
||||
|
||||
// or use PsrPrinter for output compatible with PSR-2 / PSR-12
|
||||
// echo (new Nette\PhpGenerator\PsrPrinter)->printFile($file);
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is auto-generated.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Foo;
|
||||
|
||||
class A
|
||||
{
|
||||
}
|
||||
|
||||
function foo()
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
Generate using Reflection
|
||||
-------------------------
|
||||
|
||||
Another common use case is to create class or function based on existing one:
|
||||
|
||||
```php
|
||||
$class = Nette\PhpGenerator\ClassType::from(PDO::class);
|
||||
|
||||
$function = Nette\PhpGenerator\GlobalFunction::from('trim');
|
||||
|
||||
$closure = Nette\PhpGenerator\Closure::from(
|
||||
function (stdClass $a, $b = null) {}
|
||||
);
|
||||
```
|
||||
|
||||
Function and method bodies are empty by default. If you want to load them as well, use this way
|
||||
(it requires `nikic/php-parser` to be installed):
|
||||
|
||||
```php
|
||||
$class = Nette\PhpGenerator\ClassType::withBodiesFrom(MyClass::class);
|
||||
|
||||
$function = Nette\PhpGenerator\GlobalFunction::withBodyFrom('dump');
|
||||
```
|
||||
|
||||
Load class from file
|
||||
--------------------
|
||||
|
||||
You can also load classes directly from a PHP file that is not already loaded or string of PHP code:
|
||||
|
||||
```php
|
||||
$class = Nette\PhpGenerator\ClassType::fromCode(<<<XX
|
||||
<?php
|
||||
|
||||
class Demo
|
||||
{
|
||||
public $foo;
|
||||
}
|
||||
XX);
|
||||
```
|
||||
|
||||
Loading the entire PHP file, which may contain multiple classes or even multiple namespaces:
|
||||
|
||||
```php
|
||||
$file = Nette\PhpGenerator\PhpFile::fromCode(file_get_contents('classes.php'));
|
||||
```
|
||||
|
||||
This requires `nikic/php-parser` to be installed.
|
||||
|
||||
|
||||
Variables Dumper
|
||||
----------------
|
||||
|
||||
The Dumper returns a parsable PHP string representation of a variable. Provides better and clearer output that native functon `var_export()`.
|
||||
|
||||
```php
|
||||
$dumper = new Nette\PhpGenerator\Dumper;
|
||||
|
||||
$var = ['a', 'b', 123];
|
||||
|
||||
echo $dumper->dump($var); // prints ['a', 'b', 123]
|
||||
```
|
||||
|
||||
Custom Printer
|
||||
--------------
|
||||
|
||||
Need to customize printer behavior? Create your own by inheriting the `Printer` class. You can reconfigure these variables:
|
||||
|
||||
```php
|
||||
class MyPrinter extends Nette\PhpGenerator\Printer
|
||||
{
|
||||
protected $indentation = "\t";
|
||||
protected $linesBetweenProperties = 0;
|
||||
protected $linesBetweenMethods = 1;
|
||||
protected $returnTypeColon = ': ';
|
||||
}
|
||||
```
|
||||
50
vendor/nette/php-generator/src/PhpGenerator/Attribute.php
vendored
Normal file
50
vendor/nette/php-generator/src/PhpGenerator/Attribute.php
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator;
|
||||
|
||||
use Nette;
|
||||
|
||||
|
||||
/**
|
||||
* PHP Attribute.
|
||||
*/
|
||||
final class Attribute
|
||||
{
|
||||
use Nette\SmartObject;
|
||||
|
||||
/** @var string */
|
||||
private $name;
|
||||
|
||||
/** @var array */
|
||||
private $args;
|
||||
|
||||
|
||||
public function __construct(string $name, array $args)
|
||||
{
|
||||
if (!Helpers::isNamespaceIdentifier($name)) {
|
||||
throw new Nette\InvalidArgumentException("Value '$name' is not valid attribute name.");
|
||||
}
|
||||
|
||||
$this->name = $name;
|
||||
$this->args = $args;
|
||||
}
|
||||
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
|
||||
public function getArguments(): array
|
||||
{
|
||||
return $this->args;
|
||||
}
|
||||
}
|
||||
676
vendor/nette/php-generator/src/PhpGenerator/ClassType.php
vendored
Normal file
676
vendor/nette/php-generator/src/PhpGenerator/ClassType.php
vendored
Normal file
@@ -0,0 +1,676 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator;
|
||||
|
||||
use Nette;
|
||||
|
||||
|
||||
/**
|
||||
* Class/Interface/Trait/Enum description.
|
||||
*
|
||||
* @property Method[] $methods
|
||||
* @property Property[] $properties
|
||||
*/
|
||||
final class ClassType
|
||||
{
|
||||
use Nette\SmartObject;
|
||||
use Traits\CommentAware;
|
||||
use Traits\AttributeAware;
|
||||
|
||||
public const
|
||||
TYPE_CLASS = 'class',
|
||||
TYPE_INTERFACE = 'interface',
|
||||
TYPE_TRAIT = 'trait',
|
||||
TYPE_ENUM = 'enum';
|
||||
|
||||
public const
|
||||
VisibilityPublic = 'public',
|
||||
VisibilityProtected = 'protected',
|
||||
VisibilityPrivate = 'private';
|
||||
|
||||
public const
|
||||
VISIBILITY_PUBLIC = self::VisibilityPublic,
|
||||
VISIBILITY_PROTECTED = self::VisibilityProtected,
|
||||
VISIBILITY_PRIVATE = self::VisibilityPrivate;
|
||||
|
||||
/** @var PhpNamespace|null */
|
||||
private $namespace;
|
||||
|
||||
/** @var string|null */
|
||||
private $name;
|
||||
|
||||
/** @var string class|interface|trait */
|
||||
private $type = self::TYPE_CLASS;
|
||||
|
||||
/** @var bool */
|
||||
private $final = false;
|
||||
|
||||
/** @var bool */
|
||||
private $abstract = false;
|
||||
|
||||
/** @var string|string[] */
|
||||
private $extends = [];
|
||||
|
||||
/** @var string[] */
|
||||
private $implements = [];
|
||||
|
||||
/** @var TraitUse[] */
|
||||
private $traits = [];
|
||||
|
||||
/** @var Constant[] name => Constant */
|
||||
private $consts = [];
|
||||
|
||||
/** @var Property[] name => Property */
|
||||
private $properties = [];
|
||||
|
||||
/** @var Method[] name => Method */
|
||||
private $methods = [];
|
||||
|
||||
/** @var EnumCase[] name => EnumCase */
|
||||
private $cases = [];
|
||||
|
||||
|
||||
public static function class(?string $name): self
|
||||
{
|
||||
return new self($name);
|
||||
}
|
||||
|
||||
|
||||
public static function interface(string $name): self
|
||||
{
|
||||
return (new self($name))->setType(self::TYPE_INTERFACE);
|
||||
}
|
||||
|
||||
|
||||
public static function trait(string $name): self
|
||||
{
|
||||
return (new self($name))->setType(self::TYPE_TRAIT);
|
||||
}
|
||||
|
||||
|
||||
public static function enum(string $name): self
|
||||
{
|
||||
return (new self($name))->setType(self::TYPE_ENUM);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string|object $class
|
||||
*/
|
||||
public static function from($class, bool $withBodies = false, bool $materializeTraits = true): self
|
||||
{
|
||||
return (new Factory)
|
||||
->fromClassReflection(new \ReflectionClass($class), $withBodies, $materializeTraits);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string|object $class
|
||||
*/
|
||||
public static function withBodiesFrom($class): self
|
||||
{
|
||||
return (new Factory)
|
||||
->fromClassReflection(new \ReflectionClass($class), true);
|
||||
}
|
||||
|
||||
|
||||
public static function fromCode(string $code): self
|
||||
{
|
||||
return (new Factory)
|
||||
->fromClassCode($code);
|
||||
}
|
||||
|
||||
|
||||
public function __construct(?string $name = null, ?PhpNamespace $namespace = null)
|
||||
{
|
||||
$this->setName($name);
|
||||
$this->namespace = $namespace;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
try {
|
||||
return (new Printer)->printClass($this, $this->namespace);
|
||||
} catch (\Throwable $e) {
|
||||
if (PHP_VERSION_ID >= 70400) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
trigger_error('Exception in ' . __METHOD__ . "(): {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}", E_USER_ERROR);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** @deprecated an object can be in multiple namespaces */
|
||||
public function getNamespace(): ?PhpNamespace
|
||||
{
|
||||
return $this->namespace;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setName(?string $name): self
|
||||
{
|
||||
if ($name !== null && (!Helpers::isIdentifier($name) || isset(Helpers::Keywords[strtolower($name)]))) {
|
||||
throw new Nette\InvalidArgumentException("Value '$name' is not valid class name.");
|
||||
}
|
||||
|
||||
$this->name = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function getName(): ?string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
|
||||
/** @deprecated */
|
||||
public function setClass(): self
|
||||
{
|
||||
$this->type = self::TYPE_CLASS;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function isClass(): bool
|
||||
{
|
||||
return $this->type === self::TYPE_CLASS;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setInterface(): self
|
||||
{
|
||||
$this->type = self::TYPE_INTERFACE;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function isInterface(): bool
|
||||
{
|
||||
return $this->type === self::TYPE_INTERFACE;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setTrait(): self
|
||||
{
|
||||
$this->type = self::TYPE_TRAIT;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function isTrait(): bool
|
||||
{
|
||||
return $this->type === self::TYPE_TRAIT;
|
||||
}
|
||||
|
||||
|
||||
public function isEnum(): bool
|
||||
{
|
||||
return $this->type === self::TYPE_ENUM;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setType(string $type): self
|
||||
{
|
||||
if (!in_array($type, [self::TYPE_CLASS, self::TYPE_INTERFACE, self::TYPE_TRAIT, self::TYPE_ENUM], true)) {
|
||||
throw new Nette\InvalidArgumentException('Argument must be class|interface|trait|enum.');
|
||||
}
|
||||
|
||||
$this->type = $type;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function getType(): string
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setFinal(bool $state = true): self
|
||||
{
|
||||
$this->final = $state;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function isFinal(): bool
|
||||
{
|
||||
return $this->final;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setAbstract(bool $state = true): self
|
||||
{
|
||||
$this->abstract = $state;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function isAbstract(): bool
|
||||
{
|
||||
return $this->abstract;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string|string[] $names
|
||||
* @return static
|
||||
*/
|
||||
public function setExtends($names): self
|
||||
{
|
||||
if (!is_string($names) && !is_array($names)) {
|
||||
throw new Nette\InvalidArgumentException('Argument must be string or string[].');
|
||||
}
|
||||
|
||||
$this->validateNames((array) $names);
|
||||
$this->extends = $names;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/** @return string|string[] */
|
||||
public function getExtends()
|
||||
{
|
||||
return $this->extends;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function addExtend(string $name): self
|
||||
{
|
||||
$this->validateNames([$name]);
|
||||
$this->extends = (array) $this->extends;
|
||||
$this->extends[] = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string[] $names
|
||||
* @return static
|
||||
*/
|
||||
public function setImplements(array $names): self
|
||||
{
|
||||
$this->validateNames($names);
|
||||
$this->implements = $names;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/** @return string[] */
|
||||
public function getImplements(): array
|
||||
{
|
||||
return $this->implements;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function addImplement(string $name): self
|
||||
{
|
||||
$this->validateNames([$name]);
|
||||
$this->implements[] = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function removeImplement(string $name): self
|
||||
{
|
||||
$this->implements = array_diff($this->implements, [$name]);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string[]|TraitUse[] $traits
|
||||
* @return static
|
||||
*/
|
||||
public function setTraits(array $traits): self
|
||||
{
|
||||
$this->traits = [];
|
||||
foreach ($traits as $trait) {
|
||||
if (!$trait instanceof TraitUse) {
|
||||
$trait = new TraitUse($trait);
|
||||
}
|
||||
|
||||
$this->traits[$trait->getName()] = $trait;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/** @return string[] */
|
||||
public function getTraits(): array
|
||||
{
|
||||
return array_keys($this->traits);
|
||||
}
|
||||
|
||||
|
||||
/** @internal */
|
||||
public function getTraitResolutions(): array
|
||||
{
|
||||
return $this->traits;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array|bool $resolutions
|
||||
* @return static|TraitUse
|
||||
*/
|
||||
public function addTrait(string $name, $resolutions = [])
|
||||
{
|
||||
$this->traits[$name] = $trait = new TraitUse($name);
|
||||
if ($resolutions === true) {
|
||||
return $trait;
|
||||
}
|
||||
|
||||
array_map(function ($item) use ($trait) {
|
||||
$trait->addResolution($item);
|
||||
}, $resolutions);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function removeTrait(string $name): self
|
||||
{
|
||||
unset($this->traits[$name]);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Method|Property|Constant|EnumCase|TraitUse $member
|
||||
* @return static
|
||||
*/
|
||||
public function addMember($member): self
|
||||
{
|
||||
if ($member instanceof Method) {
|
||||
if ($this->isInterface()) {
|
||||
$member->setBody(null);
|
||||
}
|
||||
|
||||
$this->methods[strtolower($member->getName())] = $member;
|
||||
|
||||
} elseif ($member instanceof Property) {
|
||||
$this->properties[$member->getName()] = $member;
|
||||
|
||||
} elseif ($member instanceof Constant) {
|
||||
$this->consts[$member->getName()] = $member;
|
||||
|
||||
} elseif ($member instanceof EnumCase) {
|
||||
$this->cases[$member->getName()] = $member;
|
||||
|
||||
} elseif ($member instanceof TraitUse) {
|
||||
$this->traits[$member->getName()] = $member;
|
||||
|
||||
} else {
|
||||
throw new Nette\InvalidArgumentException('Argument must be Method|Property|Constant|EnumCase|TraitUse.');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Constant[]|mixed[] $consts
|
||||
* @return static
|
||||
*/
|
||||
public function setConstants(array $consts): self
|
||||
{
|
||||
$this->consts = [];
|
||||
foreach ($consts as $k => $const) {
|
||||
if (!$const instanceof Constant) {
|
||||
$const = (new Constant($k))->setValue($const)->setPublic();
|
||||
}
|
||||
|
||||
$this->consts[$const->getName()] = $const;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/** @return Constant[] */
|
||||
public function getConstants(): array
|
||||
{
|
||||
return $this->consts;
|
||||
}
|
||||
|
||||
|
||||
public function addConstant(string $name, $value): Constant
|
||||
{
|
||||
return $this->consts[$name] = (new Constant($name))
|
||||
->setValue($value)
|
||||
->setPublic();
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function removeConstant(string $name): self
|
||||
{
|
||||
unset($this->consts[$name]);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets cases to enum
|
||||
* @param EnumCase[] $cases
|
||||
* @return static
|
||||
*/
|
||||
public function setCases(array $cases): self
|
||||
{
|
||||
(function (EnumCase ...$cases) {})(...array_values($cases));
|
||||
$this->cases = [];
|
||||
foreach ($cases as $case) {
|
||||
$this->cases[$case->getName()] = $case;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/** @return EnumCase[] */
|
||||
public function getCases(): array
|
||||
{
|
||||
return $this->cases;
|
||||
}
|
||||
|
||||
|
||||
/** Adds case to enum */
|
||||
public function addCase(string $name, $value = null): EnumCase
|
||||
{
|
||||
return $this->cases[$name] = (new EnumCase($name))
|
||||
->setValue($value);
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function removeCase(string $name): self
|
||||
{
|
||||
unset($this->cases[$name]);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Property[] $props
|
||||
* @return static
|
||||
*/
|
||||
public function setProperties(array $props): self
|
||||
{
|
||||
(function (Property ...$props) {})(...array_values($props));
|
||||
$this->properties = [];
|
||||
foreach ($props as $v) {
|
||||
$this->properties[$v->getName()] = $v;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/** @return Property[] */
|
||||
public function getProperties(): array
|
||||
{
|
||||
return $this->properties;
|
||||
}
|
||||
|
||||
|
||||
public function getProperty(string $name): Property
|
||||
{
|
||||
if (!isset($this->properties[$name])) {
|
||||
throw new Nette\InvalidArgumentException("Property '$name' not found.");
|
||||
}
|
||||
|
||||
return $this->properties[$name];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $name without $
|
||||
*/
|
||||
public function addProperty(string $name, $value = null): Property
|
||||
{
|
||||
return $this->properties[$name] = func_num_args() > 1
|
||||
? (new Property($name))->setValue($value)
|
||||
: new Property($name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $name without $
|
||||
* @return static
|
||||
*/
|
||||
public function removeProperty(string $name): self
|
||||
{
|
||||
unset($this->properties[$name]);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function hasProperty(string $name): bool
|
||||
{
|
||||
return isset($this->properties[$name]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Method[] $methods
|
||||
* @return static
|
||||
*/
|
||||
public function setMethods(array $methods): self
|
||||
{
|
||||
(function (Method ...$methods) {})(...array_values($methods));
|
||||
$this->methods = [];
|
||||
foreach ($methods as $m) {
|
||||
$this->methods[strtolower($m->getName())] = $m;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/** @return Method[] */
|
||||
public function getMethods(): array
|
||||
{
|
||||
$res = [];
|
||||
foreach ($this->methods as $m) {
|
||||
$res[$m->getName()] = $m;
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
public function getMethod(string $name): Method
|
||||
{
|
||||
$m = $this->methods[strtolower($name)] ?? null;
|
||||
if (!$m) {
|
||||
throw new Nette\InvalidArgumentException("Method '$name' not found.");
|
||||
}
|
||||
|
||||
return $m;
|
||||
}
|
||||
|
||||
|
||||
public function addMethod(string $name): Method
|
||||
{
|
||||
$method = new Method($name);
|
||||
if ($this->isInterface()) {
|
||||
$method->setBody(null);
|
||||
} else {
|
||||
$method->setPublic();
|
||||
}
|
||||
|
||||
return $this->methods[strtolower($name)] = $method;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function removeMethod(string $name): self
|
||||
{
|
||||
unset($this->methods[strtolower($name)]);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function hasMethod(string $name): bool
|
||||
{
|
||||
return isset($this->methods[strtolower($name)]);
|
||||
}
|
||||
|
||||
|
||||
/** @throws Nette\InvalidStateException */
|
||||
public function validate(): void
|
||||
{
|
||||
if ($this->isEnum() && ($this->abstract || $this->final || $this->extends || $this->properties)) {
|
||||
throw new Nette\InvalidStateException("Enum '$this->name' cannot be abstract or final or extends class or have properties.");
|
||||
|
||||
} elseif (!$this->name && ($this->abstract || $this->final)) {
|
||||
throw new Nette\InvalidStateException('Anonymous class cannot be abstract or final.');
|
||||
|
||||
} elseif ($this->abstract && $this->final) {
|
||||
throw new Nette\InvalidStateException("Class '$this->name' cannot be abstract and final at the same time.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function validateNames(array $names): void
|
||||
{
|
||||
foreach ($names as $name) {
|
||||
if (!Helpers::isNamespaceIdentifier($name, true)) {
|
||||
throw new Nette\InvalidArgumentException("Value '$name' is not valid class name.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function __clone()
|
||||
{
|
||||
$clone = function ($item) { return clone $item; };
|
||||
$this->traits = array_map($clone, $this->traits);
|
||||
$this->cases = array_map($clone, $this->cases);
|
||||
$this->consts = array_map($clone, $this->consts);
|
||||
$this->properties = array_map($clone, $this->properties);
|
||||
$this->methods = array_map($clone, $this->methods);
|
||||
}
|
||||
}
|
||||
73
vendor/nette/php-generator/src/PhpGenerator/Closure.php
vendored
Normal file
73
vendor/nette/php-generator/src/PhpGenerator/Closure.php
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator;
|
||||
|
||||
use Nette;
|
||||
|
||||
|
||||
/**
|
||||
* Closure.
|
||||
*
|
||||
* @property string $body
|
||||
*/
|
||||
final class Closure
|
||||
{
|
||||
use Nette\SmartObject;
|
||||
use Traits\FunctionLike;
|
||||
use Traits\AttributeAware;
|
||||
|
||||
/** @var Parameter[] */
|
||||
private $uses = [];
|
||||
|
||||
|
||||
public static function from(\Closure $closure): self
|
||||
{
|
||||
return (new Factory)->fromFunctionReflection(new \ReflectionFunction($closure));
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
try {
|
||||
return (new Printer)->printClosure($this);
|
||||
} catch (\Throwable $e) {
|
||||
if (PHP_VERSION_ID >= 70400) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
trigger_error('Exception in ' . __METHOD__ . "(): {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}", E_USER_ERROR);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Parameter[] $uses
|
||||
* @return static
|
||||
*/
|
||||
public function setUses(array $uses): self
|
||||
{
|
||||
(function (Parameter ...$uses) {})(...$uses);
|
||||
$this->uses = $uses;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function getUses(): array
|
||||
{
|
||||
return $this->uses;
|
||||
}
|
||||
|
||||
|
||||
public function addUse(string $name): Parameter
|
||||
{
|
||||
return $this->uses[] = new Parameter($name);
|
||||
}
|
||||
}
|
||||
59
vendor/nette/php-generator/src/PhpGenerator/Constant.php
vendored
Normal file
59
vendor/nette/php-generator/src/PhpGenerator/Constant.php
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator;
|
||||
|
||||
use Nette;
|
||||
|
||||
|
||||
/**
|
||||
* Class constant.
|
||||
*/
|
||||
final class Constant
|
||||
{
|
||||
use Nette\SmartObject;
|
||||
use Traits\NameAware;
|
||||
use Traits\VisibilityAware;
|
||||
use Traits\CommentAware;
|
||||
use Traits\AttributeAware;
|
||||
|
||||
/** @var mixed */
|
||||
private $value;
|
||||
|
||||
/** @var bool */
|
||||
private $final = false;
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setValue($val): self
|
||||
{
|
||||
$this->value = $val;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setFinal(bool $state = true): self
|
||||
{
|
||||
$this->final = $state;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function isFinal(): bool
|
||||
{
|
||||
return $this->final;
|
||||
}
|
||||
}
|
||||
277
vendor/nette/php-generator/src/PhpGenerator/Dumper.php
vendored
Normal file
277
vendor/nette/php-generator/src/PhpGenerator/Dumper.php
vendored
Normal file
@@ -0,0 +1,277 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator;
|
||||
|
||||
use Nette;
|
||||
|
||||
|
||||
/**
|
||||
* PHP code generator utils.
|
||||
*/
|
||||
final class Dumper
|
||||
{
|
||||
private const IndentLength = 4;
|
||||
|
||||
/** @var int */
|
||||
public $maxDepth = 50;
|
||||
|
||||
/** @var int */
|
||||
public $wrapLength = 120;
|
||||
|
||||
/** @var string */
|
||||
public $indentation = "\t";
|
||||
|
||||
|
||||
/**
|
||||
* Returns a PHP representation of a variable.
|
||||
*/
|
||||
public function dump($var, int $column = 0): string
|
||||
{
|
||||
return $this->dumpVar($var, [], 0, $column);
|
||||
}
|
||||
|
||||
|
||||
private function dumpVar(&$var, array $parents = [], int $level = 0, int $column = 0): string
|
||||
{
|
||||
if ($var === null) {
|
||||
return 'null';
|
||||
|
||||
} elseif (is_string($var)) {
|
||||
return $this->dumpString($var);
|
||||
|
||||
} elseif (is_array($var)) {
|
||||
return $this->dumpArray($var, $parents, $level, $column);
|
||||
|
||||
} elseif ($var instanceof Literal) {
|
||||
return $this->dumpLiteral($var, $level);
|
||||
|
||||
} elseif (is_object($var)) {
|
||||
return $this->dumpObject($var, $parents, $level);
|
||||
|
||||
} elseif (is_resource($var)) {
|
||||
throw new Nette\InvalidArgumentException('Cannot dump resource.');
|
||||
|
||||
} else {
|
||||
return var_export($var, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function dumpString(string $s): string
|
||||
{
|
||||
static $special = [
|
||||
"\r" => '\r',
|
||||
"\n" => '\n',
|
||||
"\t" => '\t',
|
||||
"\e" => '\e',
|
||||
'\\' => '\\\\',
|
||||
];
|
||||
|
||||
$utf8 = preg_match('##u', $s);
|
||||
$escaped = preg_replace_callback(
|
||||
$utf8 ? '#[\p{C}\\\\]#u' : '#[\x00-\x1F\x7F-\xFF\\\\]#',
|
||||
function ($m) use ($special) {
|
||||
return $special[$m[0]] ?? (strlen($m[0]) === 1
|
||||
? '\x' . str_pad(strtoupper(dechex(ord($m[0]))), 2, '0', STR_PAD_LEFT) . ''
|
||||
: '\u{' . strtoupper(ltrim(dechex(self::utf8Ord($m[0])), '0')) . '}');
|
||||
},
|
||||
$s
|
||||
);
|
||||
return $s === str_replace('\\\\', '\\', $escaped)
|
||||
? "'" . preg_replace('#\'|\\\\(?=[\'\\\\]|$)#D', '\\\\$0', $s) . "'"
|
||||
: '"' . addcslashes($escaped, '"$') . '"';
|
||||
}
|
||||
|
||||
|
||||
private static function utf8Ord(string $c): int
|
||||
{
|
||||
$ord0 = ord($c[0]);
|
||||
if ($ord0 < 0x80) {
|
||||
return $ord0;
|
||||
} elseif ($ord0 < 0xE0) {
|
||||
return ($ord0 << 6) + ord($c[1]) - 0x3080;
|
||||
} elseif ($ord0 < 0xF0) {
|
||||
return ($ord0 << 12) + (ord($c[1]) << 6) + ord($c[2]) - 0xE2080;
|
||||
} else {
|
||||
return ($ord0 << 18) + (ord($c[1]) << 12) + (ord($c[2]) << 6) + ord($c[3]) - 0x3C82080;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function dumpArray(array &$var, array $parents, int $level, int $column): string
|
||||
{
|
||||
if (empty($var)) {
|
||||
return '[]';
|
||||
|
||||
} elseif ($level > $this->maxDepth || in_array($var, $parents, true)) {
|
||||
throw new Nette\InvalidArgumentException('Nesting level too deep or recursive dependency.');
|
||||
}
|
||||
|
||||
$space = str_repeat($this->indentation, $level);
|
||||
$outInline = '';
|
||||
$outWrapped = "\n$space";
|
||||
$parents[] = $var;
|
||||
$counter = 0;
|
||||
$hideKeys = is_int(($tmp = array_keys($var))[0]) && $tmp === range($tmp[0], $tmp[0] + count($var) - 1);
|
||||
|
||||
foreach ($var as $k => &$v) {
|
||||
$keyPart = $hideKeys && $k === $counter
|
||||
? ''
|
||||
: $this->dumpVar($k) . ' => ';
|
||||
$counter = is_int($k) ? max($k + 1, $counter) : $counter;
|
||||
$outInline .= ($outInline === '' ? '' : ', ') . $keyPart;
|
||||
$outInline .= $this->dumpVar($v, $parents, 0, $column + strlen($outInline));
|
||||
$outWrapped .= $this->indentation
|
||||
. $keyPart
|
||||
. $this->dumpVar($v, $parents, $level + 1, strlen($keyPart))
|
||||
. ",\n$space";
|
||||
}
|
||||
|
||||
array_pop($parents);
|
||||
$wrap = strpos($outInline, "\n") !== false || $level * self::IndentLength + $column + strlen($outInline) + 3 > $this->wrapLength; // 3 = [],
|
||||
return '[' . ($wrap ? $outWrapped : $outInline) . ']';
|
||||
}
|
||||
|
||||
|
||||
private function dumpObject($var, array $parents, int $level): string
|
||||
{
|
||||
if ($var instanceof \Serializable) {
|
||||
return 'unserialize(' . $this->dumpString(serialize($var)) . ')';
|
||||
|
||||
} elseif ($var instanceof \UnitEnum) {
|
||||
return '\\' . get_class($var) . '::' . $var->name;
|
||||
|
||||
} elseif ($var instanceof \Closure) {
|
||||
$inner = Nette\Utils\Callback::unwrap($var);
|
||||
if (Nette\Utils\Callback::isStatic($inner)) {
|
||||
return PHP_VERSION_ID < 80100
|
||||
? '\Closure::fromCallable(' . $this->dump($inner) . ')'
|
||||
: implode('::', (array) $inner) . '(...)';
|
||||
}
|
||||
|
||||
throw new Nette\InvalidArgumentException('Cannot dump closure.');
|
||||
}
|
||||
|
||||
$class = get_class($var);
|
||||
if ((new \ReflectionObject($var))->isAnonymous()) {
|
||||
throw new Nette\InvalidArgumentException('Cannot dump anonymous class.');
|
||||
|
||||
} elseif (in_array($class, [\DateTime::class, \DateTimeImmutable::class], true)) {
|
||||
return $this->format("new \\$class(?, new \\DateTimeZone(?))", $var->format('Y-m-d H:i:s.u'), $var->getTimeZone()->getName());
|
||||
}
|
||||
|
||||
$arr = (array) $var;
|
||||
$space = str_repeat($this->indentation, $level);
|
||||
|
||||
if ($level > $this->maxDepth || in_array($var, $parents, true)) {
|
||||
throw new Nette\InvalidArgumentException('Nesting level too deep or recursive dependency.');
|
||||
}
|
||||
|
||||
$out = "\n";
|
||||
$parents[] = $var;
|
||||
if (method_exists($var, '__sleep')) {
|
||||
foreach ($var->__sleep() as $v) {
|
||||
$props[$v] = $props["\x00*\x00$v"] = $props["\x00$class\x00$v"] = true;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($arr as $k => &$v) {
|
||||
if (!isset($props) || isset($props[$k])) {
|
||||
$out .= $space . $this->indentation
|
||||
. ($keyPart = $this->dumpVar($k) . ' => ')
|
||||
. $this->dumpVar($v, $parents, $level + 1, strlen($keyPart))
|
||||
. ",\n";
|
||||
}
|
||||
}
|
||||
|
||||
array_pop($parents);
|
||||
$out .= $space;
|
||||
return $class === \stdClass::class
|
||||
? "(object) [$out]"
|
||||
: '\\' . self::class . "::createObject('$class', [$out])";
|
||||
}
|
||||
|
||||
|
||||
private function dumpLiteral(Literal $var, int $level): string
|
||||
{
|
||||
$s = $var->formatWith($this);
|
||||
$s = Nette\Utils\Strings::indent(trim($s), $level, $this->indentation);
|
||||
return ltrim($s, $this->indentation);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates PHP statement. Supports placeholders: ? \? $? ->? ::? ...? ...?: ?*
|
||||
*/
|
||||
public function format(string $statement, ...$args): string
|
||||
{
|
||||
$tokens = preg_split('#(\.\.\.\?:?|\$\?|->\?|::\?|\\\\\?|\?\*|\?(?!\w))#', $statement, -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||
$res = '';
|
||||
foreach ($tokens as $n => $token) {
|
||||
if ($n % 2 === 0) {
|
||||
$res .= $token;
|
||||
} elseif ($token === '\?') {
|
||||
$res .= '?';
|
||||
} elseif (!$args) {
|
||||
throw new Nette\InvalidArgumentException('Insufficient number of arguments.');
|
||||
} elseif ($token === '?') {
|
||||
$res .= $this->dump(array_shift($args), strlen($res) - strrpos($res, "\n"));
|
||||
} elseif ($token === '...?' || $token === '...?:' || $token === '?*') {
|
||||
$arg = array_shift($args);
|
||||
if (!is_array($arg)) {
|
||||
throw new Nette\InvalidArgumentException('Argument must be an array.');
|
||||
}
|
||||
|
||||
$res .= $this->dumpArguments($arg, strlen($res) - strrpos($res, "\n"), $token === '...?:');
|
||||
|
||||
} else { // $ -> ::
|
||||
$arg = array_shift($args);
|
||||
if ($arg instanceof Literal || !Helpers::isIdentifier($arg)) {
|
||||
$arg = '{' . $this->dumpVar($arg) . '}';
|
||||
}
|
||||
|
||||
$res .= substr($token, 0, -1) . $arg;
|
||||
}
|
||||
}
|
||||
|
||||
if ($args) {
|
||||
throw new Nette\InvalidArgumentException('Insufficient number of placeholders.');
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
private function dumpArguments(array &$var, int $column, bool $named): string
|
||||
{
|
||||
$outInline = $outWrapped = '';
|
||||
|
||||
foreach ($var as $k => &$v) {
|
||||
$k = !$named || is_int($k) ? '' : $k . ': ';
|
||||
$outInline .= $outInline === '' ? '' : ', ';
|
||||
$outInline .= $k . $this->dumpVar($v, [$var], 0, $column + strlen($outInline));
|
||||
$outWrapped .= ($outWrapped === '' ? '' : ',') . "\n"
|
||||
. $this->indentation . $k . $this->dumpVar($v, [$var], 1);
|
||||
}
|
||||
|
||||
return count($var) > 1 && (strpos($outInline, "\n") !== false || $column + strlen($outInline) > $this->wrapLength)
|
||||
? $outWrapped . "\n"
|
||||
: $outInline;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public static function createObject(string $class, array $props): object
|
||||
{
|
||||
return unserialize('O' . substr(serialize($class), 1, -1) . substr(serialize($props), 1));
|
||||
}
|
||||
}
|
||||
41
vendor/nette/php-generator/src/PhpGenerator/EnumCase.php
vendored
Normal file
41
vendor/nette/php-generator/src/PhpGenerator/EnumCase.php
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator;
|
||||
|
||||
use Nette;
|
||||
|
||||
|
||||
/**
|
||||
* Enum case.
|
||||
*/
|
||||
final class EnumCase
|
||||
{
|
||||
use Nette\SmartObject;
|
||||
use Traits\NameAware;
|
||||
use Traits\CommentAware;
|
||||
use Traits\AttributeAware;
|
||||
|
||||
/** @var string|int|null */
|
||||
private $value;
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setValue($val): self
|
||||
{
|
||||
$this->value = $val;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
}
|
||||
444
vendor/nette/php-generator/src/PhpGenerator/Extractor.php
vendored
Normal file
444
vendor/nette/php-generator/src/PhpGenerator/Extractor.php
vendored
Normal file
@@ -0,0 +1,444 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator;
|
||||
|
||||
use Nette;
|
||||
use PhpParser;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\NodeFinder;
|
||||
use PhpParser\ParserFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Extracts information from PHP code.
|
||||
* @internal
|
||||
*/
|
||||
final class Extractor
|
||||
{
|
||||
use Nette\SmartObject;
|
||||
|
||||
private $code;
|
||||
private $statements;
|
||||
private $printer;
|
||||
|
||||
|
||||
public function __construct(string $code)
|
||||
{
|
||||
if (!class_exists(ParserFactory::class)) {
|
||||
throw new Nette\NotSupportedException("PHP-Parser is required to load method bodies, install package 'nikic/php-parser' 4.7 or newer.");
|
||||
}
|
||||
|
||||
$this->printer = new PhpParser\PrettyPrinter\Standard;
|
||||
$this->parseCode($code);
|
||||
}
|
||||
|
||||
|
||||
private function parseCode(string $code): void
|
||||
{
|
||||
if (substr($code, 0, 5) !== '<?php') {
|
||||
throw new Nette\InvalidStateException('The input string is not a PHP code.');
|
||||
}
|
||||
|
||||
$this->code = str_replace("\r\n", "\n", $code);
|
||||
$lexer = new PhpParser\Lexer\Emulative(['usedAttributes' => ['startFilePos', 'endFilePos', 'comments']]);
|
||||
$parser = (new ParserFactory)->create(ParserFactory::ONLY_PHP7, $lexer);
|
||||
$stmts = $parser->parse($this->code);
|
||||
|
||||
$traverser = new PhpParser\NodeTraverser;
|
||||
$traverser->addVisitor(new PhpParser\NodeVisitor\ParentConnectingVisitor);
|
||||
$traverser->addVisitor(new PhpParser\NodeVisitor\NameResolver(null, ['preserveOriginalNames' => true]));
|
||||
$this->statements = $traverser->traverse($stmts);
|
||||
}
|
||||
|
||||
|
||||
public function extractMethodBodies(string $className): array
|
||||
{
|
||||
$nodeFinder = new NodeFinder;
|
||||
$classNode = $nodeFinder->findFirst($this->statements, function (Node $node) use ($className) {
|
||||
return $node instanceof Node\Stmt\ClassLike && $node->namespacedName->toString() === $className;
|
||||
});
|
||||
|
||||
$res = [];
|
||||
foreach ($nodeFinder->findInstanceOf($classNode, Node\Stmt\ClassMethod::class) as $methodNode) {
|
||||
/** @var Node\Stmt\ClassMethod $methodNode */
|
||||
if ($methodNode->stmts) {
|
||||
$res[$methodNode->name->toString()] = $this->getReformattedContents($methodNode->stmts, 2);
|
||||
}
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
public function extractFunctionBody(string $name): ?string
|
||||
{
|
||||
/** @var Node\Stmt\Function_ $functionNode */
|
||||
$functionNode = (new NodeFinder)->findFirst($this->statements, function (Node $node) use ($name) {
|
||||
return $node instanceof Node\Stmt\Function_ && $node->namespacedName->toString() === $name;
|
||||
});
|
||||
|
||||
return $this->getReformattedContents($functionNode->stmts, 1);
|
||||
}
|
||||
|
||||
|
||||
/** @param Node[] $statements */
|
||||
private function getReformattedContents(array $statements, int $level): string
|
||||
{
|
||||
$body = $this->getNodeContents(...$statements);
|
||||
$body = $this->performReplacements($body, $this->prepareReplacements($statements));
|
||||
return Helpers::unindent($body, $level);
|
||||
}
|
||||
|
||||
|
||||
private function prepareReplacements(array $statements): array
|
||||
{
|
||||
$start = $this->getNodeStartPos($statements[0]);
|
||||
$replacements = [];
|
||||
(new NodeFinder)->find($statements, function (Node $node) use (&$replacements, $start) {
|
||||
if ($node instanceof Node\Name\FullyQualified) {
|
||||
if ($node->getAttribute('originalName') instanceof Node\Name) {
|
||||
$of = $node->getAttribute('parent') instanceof Node\Expr\ConstFetch
|
||||
? PhpNamespace::NameConstant
|
||||
: ($node->getAttribute('parent') instanceof Node\Expr\FuncCall ? PhpNamespace::NameFunction : PhpNamespace::NameNormal);
|
||||
$replacements[] = [
|
||||
$node->getStartFilePos() - $start,
|
||||
$node->getEndFilePos() - $start,
|
||||
Helpers::tagName($node->toCodeString(), $of),
|
||||
];
|
||||
}
|
||||
} elseif ($node instanceof Node\Scalar\String_ || $node instanceof Node\Scalar\EncapsedStringPart) {
|
||||
// multi-line strings => singleline
|
||||
$token = $this->getNodeContents($node);
|
||||
if (strpos($token, "\n") !== false) {
|
||||
$quote = $node instanceof Node\Scalar\String_ ? '"' : '';
|
||||
$replacements[] = [
|
||||
$node->getStartFilePos() - $start,
|
||||
$node->getEndFilePos() - $start,
|
||||
$quote . addcslashes($node->value, "\x00..\x1F") . $quote,
|
||||
];
|
||||
}
|
||||
} elseif ($node instanceof Node\Scalar\Encapsed) {
|
||||
// HEREDOC => "string"
|
||||
if ($node->getAttribute('kind') === Node\Scalar\String_::KIND_HEREDOC) {
|
||||
$replacements[] = [
|
||||
$node->getStartFilePos() - $start,
|
||||
$node->parts[0]->getStartFilePos() - $start - 1,
|
||||
'"',
|
||||
];
|
||||
$replacements[] = [
|
||||
end($node->parts)->getEndFilePos() - $start + 1,
|
||||
$node->getEndFilePos() - $start,
|
||||
'"',
|
||||
];
|
||||
}
|
||||
}
|
||||
});
|
||||
return $replacements;
|
||||
}
|
||||
|
||||
|
||||
private function performReplacements(string $s, array $replacements): string
|
||||
{
|
||||
usort($replacements, function ($a, $b) { // sort by position in file
|
||||
return $b[0] <=> $a[0];
|
||||
});
|
||||
|
||||
foreach ($replacements as [$start, $end, $replacement]) {
|
||||
$s = substr_replace($s, $replacement, $start, $end - $start + 1);
|
||||
}
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
|
||||
public function extractAll(): PhpFile
|
||||
{
|
||||
$phpFile = new PhpFile;
|
||||
$namespace = '';
|
||||
$visitor = new class extends PhpParser\NodeVisitorAbstract {
|
||||
public $callback;
|
||||
|
||||
|
||||
public function enterNode(Node $node)
|
||||
{
|
||||
return ($this->callback)($node);
|
||||
}
|
||||
};
|
||||
|
||||
$visitor->callback = function (Node $node) use (&$class, &$namespace, $phpFile) {
|
||||
if ($node instanceof Node\Stmt\DeclareDeclare && $node->key->name === 'strict_types') {
|
||||
$phpFile->setStrictTypes((bool) $node->value->value);
|
||||
} elseif ($node instanceof Node\Stmt\Namespace_) {
|
||||
$namespace = $node->name ? $node->name->toString() : '';
|
||||
} elseif ($node instanceof Node\Stmt\Use_) {
|
||||
$this->addUseToNamespace($node, $phpFile->addNamespace($namespace));
|
||||
} elseif ($node instanceof Node\Stmt\Class_) {
|
||||
if (!$node->name) {
|
||||
return PhpParser\NodeTraverser::DONT_TRAVERSE_CHILDREN;
|
||||
}
|
||||
|
||||
$class = $this->addClassToFile($phpFile, $node);
|
||||
} elseif ($node instanceof Node\Stmt\Interface_) {
|
||||
$class = $this->addInterfaceToFile($phpFile, $node);
|
||||
} elseif ($node instanceof Node\Stmt\Trait_) {
|
||||
$class = $this->addTraitToFile($phpFile, $node);
|
||||
} elseif ($node instanceof Node\Stmt\Enum_) {
|
||||
$class = $this->addEnumToFile($phpFile, $node);
|
||||
} elseif ($node instanceof Node\Stmt\Function_) {
|
||||
$this->addFunctionToFile($phpFile, $node);
|
||||
} elseif ($node instanceof Node\Stmt\TraitUse) {
|
||||
$this->addTraitToClass($class, $node);
|
||||
} elseif ($node instanceof Node\Stmt\Property) {
|
||||
$this->addPropertyToClass($class, $node);
|
||||
} elseif ($node instanceof Node\Stmt\ClassMethod) {
|
||||
$this->addMethodToClass($class, $node);
|
||||
} elseif ($node instanceof Node\Stmt\ClassConst) {
|
||||
$this->addConstantToClass($class, $node);
|
||||
} elseif ($node instanceof Node\Stmt\EnumCase) {
|
||||
$this->addEnumCaseToClass($class, $node);
|
||||
}
|
||||
|
||||
if ($node instanceof Node\FunctionLike) {
|
||||
return PhpParser\NodeTraverser::DONT_TRAVERSE_CHILDREN;
|
||||
}
|
||||
};
|
||||
|
||||
if ($this->statements) {
|
||||
$this->addCommentAndAttributes($phpFile, $this->statements[0]);
|
||||
}
|
||||
|
||||
$traverser = new PhpParser\NodeTraverser;
|
||||
$traverser->addVisitor($visitor);
|
||||
$traverser->traverse($this->statements);
|
||||
return $phpFile;
|
||||
}
|
||||
|
||||
|
||||
private function addUseToNamespace(Node\Stmt\Use_ $node, PhpNamespace $namespace): void
|
||||
{
|
||||
$of = [
|
||||
$node::TYPE_NORMAL => PhpNamespace::NameNormal,
|
||||
$node::TYPE_FUNCTION => PhpNamespace::NameFunction,
|
||||
$node::TYPE_CONSTANT => PhpNamespace::NameConstant,
|
||||
][$node->type];
|
||||
foreach ($node->uses as $use) {
|
||||
$namespace->addUse($use->name->toString(), $use->alias ? $use->alias->toString() : null, $of);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function addClassToFile(PhpFile $phpFile, Node\Stmt\Class_ $node): ClassType
|
||||
{
|
||||
$class = $phpFile->addClass($node->namespacedName->toString());
|
||||
if ($node->extends) {
|
||||
$class->setExtends($node->extends->toString());
|
||||
}
|
||||
|
||||
foreach ($node->implements as $item) {
|
||||
$class->addImplement($item->toString());
|
||||
}
|
||||
|
||||
$class->setFinal($node->isFinal());
|
||||
$class->setAbstract($node->isAbstract());
|
||||
$this->addCommentAndAttributes($class, $node);
|
||||
return $class;
|
||||
}
|
||||
|
||||
|
||||
private function addInterfaceToFile(PhpFile $phpFile, Node\Stmt\Interface_ $node): ClassType
|
||||
{
|
||||
$class = $phpFile->addInterface($node->namespacedName->toString());
|
||||
foreach ($node->extends as $item) {
|
||||
$class->addExtend($item->toString());
|
||||
}
|
||||
|
||||
$this->addCommentAndAttributes($class, $node);
|
||||
return $class;
|
||||
}
|
||||
|
||||
|
||||
private function addTraitToFile(PhpFile $phpFile, Node\Stmt\Trait_ $node): ClassType
|
||||
{
|
||||
$class = $phpFile->addTrait($node->namespacedName->toString());
|
||||
$this->addCommentAndAttributes($class, $node);
|
||||
return $class;
|
||||
}
|
||||
|
||||
|
||||
private function addEnumToFile(PhpFile $phpFile, Node\Stmt\Enum_ $node): ClassType
|
||||
{
|
||||
$class = $phpFile->addEnum($node->namespacedName->toString());
|
||||
foreach ($node->implements as $item) {
|
||||
$class->addImplement($item->toString());
|
||||
}
|
||||
|
||||
$this->addCommentAndAttributes($class, $node);
|
||||
return $class;
|
||||
}
|
||||
|
||||
|
||||
private function addFunctionToFile(PhpFile $phpFile, Node\Stmt\Function_ $node): void
|
||||
{
|
||||
$function = $phpFile->addFunction($node->namespacedName->toString());
|
||||
$this->setupFunction($function, $node);
|
||||
}
|
||||
|
||||
|
||||
private function addTraitToClass(ClassType $class, Node\Stmt\TraitUse $node): void
|
||||
{
|
||||
foreach ($node->traits as $item) {
|
||||
$trait = $class->addTrait($item->toString(), true);
|
||||
}
|
||||
|
||||
foreach ($node->adaptations as $item) {
|
||||
$trait->addResolution(trim($this->toPhp($item), ';'));
|
||||
}
|
||||
|
||||
$this->addCommentAndAttributes($trait, $node);
|
||||
}
|
||||
|
||||
|
||||
private function addPropertyToClass(ClassType $class, Node\Stmt\Property $node): void
|
||||
{
|
||||
foreach ($node->props as $item) {
|
||||
$prop = $class->addProperty($item->name->toString());
|
||||
$prop->setStatic($node->isStatic());
|
||||
$prop->setVisibility($this->toVisibility($node->flags));
|
||||
$prop->setType($node->type ? $this->toPhp($node->type) : null);
|
||||
if ($item->default) {
|
||||
$prop->setValue(new Literal($this->getReformattedContents([$item->default], 1)));
|
||||
}
|
||||
|
||||
$prop->setReadOnly(method_exists($node, 'isReadonly') && $node->isReadonly());
|
||||
$this->addCommentAndAttributes($prop, $node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function addMethodToClass(ClassType $class, Node\Stmt\ClassMethod $node): void
|
||||
{
|
||||
$method = $class->addMethod($node->name->toString());
|
||||
$method->setAbstract($node->isAbstract());
|
||||
$method->setFinal($node->isFinal());
|
||||
$method->setStatic($node->isStatic());
|
||||
$method->setVisibility($this->toVisibility($node->flags));
|
||||
$this->setupFunction($method, $node);
|
||||
}
|
||||
|
||||
|
||||
private function addConstantToClass(ClassType $class, Node\Stmt\ClassConst $node): void
|
||||
{
|
||||
foreach ($node->consts as $item) {
|
||||
$value = $this->getReformattedContents([$item->value], 1);
|
||||
$const = $class->addConstant($item->name->toString(), new Literal($value));
|
||||
$const->setVisibility($this->toVisibility($node->flags));
|
||||
$const->setFinal(method_exists($node, 'isFinal') && $node->isFinal());
|
||||
$this->addCommentAndAttributes($const, $node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function addEnumCaseToClass(ClassType $class, Node\Stmt\EnumCase $node)
|
||||
{
|
||||
$case = $class->addCase($node->name->toString(), $node->expr ? $node->expr->value : null);
|
||||
$this->addCommentAndAttributes($case, $node);
|
||||
}
|
||||
|
||||
|
||||
private function addCommentAndAttributes($element, Node $node): void
|
||||
{
|
||||
if ($node->getDocComment()) {
|
||||
$comment = $node->getDocComment()->getReformattedText();
|
||||
$comment = Helpers::unformatDocComment($comment);
|
||||
$element->setComment($comment);
|
||||
$node->setDocComment(new PhpParser\Comment\Doc(''));
|
||||
}
|
||||
|
||||
foreach ($node->attrGroups ?? [] as $group) {
|
||||
foreach ($group->attrs as $attribute) {
|
||||
$args = [];
|
||||
foreach ($attribute->args as $arg) {
|
||||
$value = new Literal($this->getReformattedContents([$arg->value], 0));
|
||||
if ($arg->name) {
|
||||
$args[$arg->name->toString()] = $value;
|
||||
} else {
|
||||
$args[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$element->addAttribute($attribute->name->toString(), $args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param GlobalFunction|Method $function
|
||||
*/
|
||||
private function setupFunction($function, Node\FunctionLike $node): void
|
||||
{
|
||||
$function->setReturnReference($node->returnsByRef());
|
||||
$function->setReturnType($node->getReturnType() ? $this->toPhp($node->getReturnType()) : null);
|
||||
foreach ($node->getParams() as $item) {
|
||||
$visibility = $this->toVisibility($item->flags);
|
||||
$isReadonly = (bool) ($item->flags & Node\Stmt\Class_::MODIFIER_READONLY);
|
||||
$param = $visibility
|
||||
? ($function->addPromotedParameter($item->var->name))->setVisibility($visibility)->setReadonly($isReadonly)
|
||||
: $function->addParameter($item->var->name);
|
||||
$param->setType($item->type ? $this->toPhp($item->type) : null);
|
||||
$param->setReference($item->byRef);
|
||||
$function->setVariadic($item->variadic);
|
||||
if ($item->default) {
|
||||
$param->setDefaultValue(new Literal($this->getReformattedContents([$item->default], 2)));
|
||||
}
|
||||
|
||||
$this->addCommentAndAttributes($param, $item);
|
||||
}
|
||||
|
||||
$this->addCommentAndAttributes($function, $node);
|
||||
if ($node->getStmts()) {
|
||||
$function->setBody($this->getReformattedContents($node->getStmts(), 2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function toVisibility(int $flags): ?string
|
||||
{
|
||||
if ($flags & Node\Stmt\Class_::MODIFIER_PUBLIC) {
|
||||
return ClassType::VisibilityPublic;
|
||||
} elseif ($flags & Node\Stmt\Class_::MODIFIER_PROTECTED) {
|
||||
return ClassType::VisibilityProtected;
|
||||
} elseif ($flags & Node\Stmt\Class_::MODIFIER_PRIVATE) {
|
||||
return ClassType::VisibilityPrivate;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private function toPhp($value): string
|
||||
{
|
||||
return $this->printer->prettyPrint([$value]);
|
||||
}
|
||||
|
||||
|
||||
private function getNodeContents(Node ...$nodes): string
|
||||
{
|
||||
$start = $this->getNodeStartPos($nodes[0]);
|
||||
return substr($this->code, $start, end($nodes)->getEndFilePos() - $start + 1);
|
||||
}
|
||||
|
||||
|
||||
private function getNodeStartPos(Node $node): int
|
||||
{
|
||||
return ($comments = $node->getComments())
|
||||
? $comments[0]->getStartFilePos()
|
||||
: $node->getStartFilePos();
|
||||
}
|
||||
}
|
||||
368
vendor/nette/php-generator/src/PhpGenerator/Factory.php
vendored
Normal file
368
vendor/nette/php-generator/src/PhpGenerator/Factory.php
vendored
Normal file
@@ -0,0 +1,368 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator;
|
||||
|
||||
use Nette;
|
||||
use Nette\Utils\Reflection;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a representation based on reflection.
|
||||
*/
|
||||
final class Factory
|
||||
{
|
||||
use Nette\SmartObject;
|
||||
|
||||
private $bodyCache = [];
|
||||
private $extractorCache = [];
|
||||
|
||||
|
||||
public function fromClassReflection(
|
||||
\ReflectionClass $from,
|
||||
bool $withBodies = false,
|
||||
bool $materializeTraits = true
|
||||
): ClassType {
|
||||
if ($withBodies && $from->isAnonymous()) {
|
||||
throw new Nette\NotSupportedException('The $withBodies parameter cannot be used for anonymous functions.');
|
||||
}
|
||||
|
||||
$class = $from->isAnonymous()
|
||||
? new ClassType
|
||||
: new ClassType($from->getShortName(), new PhpNamespace($from->getNamespaceName()));
|
||||
|
||||
if (PHP_VERSION_ID >= 80100 && $from->isEnum()) {
|
||||
$class->setType($class::TYPE_ENUM);
|
||||
$from = new \ReflectionEnum($from->getName());
|
||||
$enumIface = $from->isBacked() ? \BackedEnum::class : \UnitEnum::class;
|
||||
} else {
|
||||
$class->setType($from->isInterface() ? $class::TYPE_INTERFACE : ($from->isTrait() ? $class::TYPE_TRAIT : $class::TYPE_CLASS));
|
||||
$class->setFinal($from->isFinal() && $class->isClass());
|
||||
$class->setAbstract($from->isAbstract() && $class->isClass());
|
||||
$enumIface = null;
|
||||
}
|
||||
|
||||
$ifaces = $from->getInterfaceNames();
|
||||
foreach ($ifaces as $iface) {
|
||||
$ifaces = array_filter($ifaces, function (string $item) use ($iface): bool {
|
||||
return !is_subclass_of($iface, $item);
|
||||
});
|
||||
}
|
||||
|
||||
if ($from->isInterface()) {
|
||||
$class->setExtends($ifaces);
|
||||
} else {
|
||||
$ifaces = array_diff($ifaces, [$enumIface]);
|
||||
$class->setImplements($ifaces);
|
||||
}
|
||||
|
||||
$class->setComment(Helpers::unformatDocComment((string) $from->getDocComment()));
|
||||
$class->setAttributes($this->getAttributes($from));
|
||||
if ($from->getParentClass()) {
|
||||
$class->setExtends($from->getParentClass()->name);
|
||||
$class->setImplements(array_diff($class->getImplements(), $from->getParentClass()->getInterfaceNames()));
|
||||
}
|
||||
|
||||
$props = [];
|
||||
foreach ($from->getProperties() as $prop) {
|
||||
$declaringClass = $materializeTraits
|
||||
? $prop->getDeclaringClass()
|
||||
: Reflection::getPropertyDeclaringClass($prop);
|
||||
|
||||
if ($prop->isDefault()
|
||||
&& $declaringClass->name === $from->name
|
||||
&& (PHP_VERSION_ID < 80000 || !$prop->isPromoted())
|
||||
&& !$class->isEnum()
|
||||
) {
|
||||
$props[] = $this->fromPropertyReflection($prop);
|
||||
}
|
||||
}
|
||||
|
||||
$class->setProperties($props);
|
||||
|
||||
$methods = $resolutions = [];
|
||||
foreach ($from->getMethods() as $method) {
|
||||
$realMethod = Reflection::getMethodDeclaringMethod($method);
|
||||
$declaringClass = ($materializeTraits ? $method : $realMethod)->getDeclaringClass();
|
||||
|
||||
if (
|
||||
$declaringClass->name === $from->name
|
||||
&& (!$enumIface || !method_exists($enumIface, $method->name))
|
||||
) {
|
||||
$methods[] = $m = $this->fromMethodReflection($method);
|
||||
if ($withBodies) {
|
||||
$realMethodClass = $realMethod->getDeclaringClass();
|
||||
$bodies = &$this->bodyCache[$realMethodClass->name];
|
||||
$bodies = $bodies ?? $this->getExtractor($realMethodClass)->extractMethodBodies($realMethodClass->name);
|
||||
if (isset($bodies[$realMethod->name])) {
|
||||
$m->setBody($bodies[$realMethod->name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$modifier = $realMethod->getModifiers() !== $method->getModifiers()
|
||||
? ' ' . $this->getVisibility($method)
|
||||
: null;
|
||||
$alias = $realMethod->name !== $method->name ? ' ' . $method->name : '';
|
||||
if ($modifier || $alias) {
|
||||
$resolutions[] = $realMethod->name . ' as' . $modifier . $alias;
|
||||
}
|
||||
}
|
||||
|
||||
$class->setMethods($methods);
|
||||
|
||||
if (!$materializeTraits) {
|
||||
foreach ($from->getTraitNames() as $trait) {
|
||||
$class->addTrait($trait, $resolutions);
|
||||
$resolutions = [];
|
||||
}
|
||||
}
|
||||
|
||||
$consts = $cases = [];
|
||||
foreach ($from->getReflectionConstants() as $const) {
|
||||
if ($class->isEnum() && $from->hasCase($const->name)) {
|
||||
$cases[] = $this->fromCaseReflection($const);
|
||||
} elseif ($const->getDeclaringClass()->name === $from->name) {
|
||||
$consts[] = $this->fromConstantReflection($const);
|
||||
}
|
||||
}
|
||||
|
||||
$class->setConstants($consts);
|
||||
$class->setCases($cases);
|
||||
|
||||
return $class;
|
||||
}
|
||||
|
||||
|
||||
public function fromMethodReflection(\ReflectionMethod $from): Method
|
||||
{
|
||||
$method = new Method($from->name);
|
||||
$method->setParameters(array_map([$this, 'fromParameterReflection'], $from->getParameters()));
|
||||
$method->setStatic($from->isStatic());
|
||||
$isInterface = $from->getDeclaringClass()->isInterface();
|
||||
$method->setVisibility($isInterface ? null : $this->getVisibility($from));
|
||||
$method->setFinal($from->isFinal());
|
||||
$method->setAbstract($from->isAbstract() && !$isInterface);
|
||||
$method->setBody($from->isAbstract() ? null : '');
|
||||
$method->setReturnReference($from->returnsReference());
|
||||
$method->setVariadic($from->isVariadic());
|
||||
$method->setComment(Helpers::unformatDocComment((string) $from->getDocComment()));
|
||||
$method->setAttributes($this->getAttributes($from));
|
||||
if ($from->getReturnType() instanceof \ReflectionNamedType) {
|
||||
$method->setReturnType($from->getReturnType()->getName());
|
||||
$method->setReturnNullable($from->getReturnType()->allowsNull());
|
||||
} elseif (
|
||||
$from->getReturnType() instanceof \ReflectionUnionType
|
||||
|| $from->getReturnType() instanceof \ReflectionIntersectionType
|
||||
) {
|
||||
$method->setReturnType((string) $from->getReturnType());
|
||||
}
|
||||
|
||||
return $method;
|
||||
}
|
||||
|
||||
|
||||
/** @return GlobalFunction|Closure */
|
||||
public function fromFunctionReflection(\ReflectionFunction $from, bool $withBody = false)
|
||||
{
|
||||
$function = $from->isClosure() ? new Closure : new GlobalFunction($from->name);
|
||||
$function->setParameters(array_map([$this, 'fromParameterReflection'], $from->getParameters()));
|
||||
$function->setReturnReference($from->returnsReference());
|
||||
$function->setVariadic($from->isVariadic());
|
||||
if (!$from->isClosure()) {
|
||||
$function->setComment(Helpers::unformatDocComment((string) $from->getDocComment()));
|
||||
}
|
||||
|
||||
$function->setAttributes($this->getAttributes($from));
|
||||
if ($from->getReturnType() instanceof \ReflectionNamedType) {
|
||||
$function->setReturnType($from->getReturnType()->getName());
|
||||
$function->setReturnNullable($from->getReturnType()->allowsNull());
|
||||
} elseif (
|
||||
$from->getReturnType() instanceof \ReflectionUnionType
|
||||
|| $from->getReturnType() instanceof \ReflectionIntersectionType
|
||||
) {
|
||||
$function->setReturnType((string) $from->getReturnType());
|
||||
}
|
||||
|
||||
if ($withBody) {
|
||||
if ($from->isClosure()) {
|
||||
throw new Nette\NotSupportedException('The $withBody parameter cannot be used for closures.');
|
||||
}
|
||||
|
||||
$function->setBody($this->getExtractor($from)->extractFunctionBody($from->name));
|
||||
}
|
||||
|
||||
return $function;
|
||||
}
|
||||
|
||||
|
||||
/** @return Method|GlobalFunction|Closure */
|
||||
public function fromCallable(callable $from)
|
||||
{
|
||||
$ref = Nette\Utils\Callback::toReflection($from);
|
||||
return $ref instanceof \ReflectionMethod
|
||||
? $this->fromMethodReflection($ref)
|
||||
: $this->fromFunctionReflection($ref);
|
||||
}
|
||||
|
||||
|
||||
public function fromParameterReflection(\ReflectionParameter $from): Parameter
|
||||
{
|
||||
$param = PHP_VERSION_ID >= 80000 && $from->isPromoted()
|
||||
? new PromotedParameter($from->name)
|
||||
: new Parameter($from->name);
|
||||
$param->setReference($from->isPassedByReference());
|
||||
if ($from->getType() instanceof \ReflectionNamedType) {
|
||||
$param->setType($from->getType()->getName());
|
||||
$param->setNullable($from->getType()->allowsNull());
|
||||
} elseif (
|
||||
$from->getType() instanceof \ReflectionUnionType
|
||||
|| $from->getType() instanceof \ReflectionIntersectionType
|
||||
) {
|
||||
$param->setType((string) $from->getType());
|
||||
}
|
||||
|
||||
if ($from->isDefaultValueAvailable()) {
|
||||
if ($from->isDefaultValueConstant()) {
|
||||
$parts = explode('::', $from->getDefaultValueConstantName());
|
||||
if (count($parts) > 1) {
|
||||
$parts[0] = Helpers::tagName($parts[0]);
|
||||
}
|
||||
|
||||
$param->setDefaultValue(new Literal(implode('::', $parts)));
|
||||
} elseif (is_object($from->getDefaultValue())) {
|
||||
$param->setDefaultValue($this->fromObject($from->getDefaultValue()));
|
||||
} else {
|
||||
$param->setDefaultValue($from->getDefaultValue());
|
||||
}
|
||||
|
||||
$param->setNullable($param->isNullable() && $param->getDefaultValue() !== null);
|
||||
}
|
||||
|
||||
$param->setAttributes($this->getAttributes($from));
|
||||
return $param;
|
||||
}
|
||||
|
||||
|
||||
public function fromConstantReflection(\ReflectionClassConstant $from): Constant
|
||||
{
|
||||
$const = new Constant($from->name);
|
||||
$const->setValue($from->getValue());
|
||||
$const->setVisibility($this->getVisibility($from));
|
||||
$const->setFinal(PHP_VERSION_ID >= 80100 ? $from->isFinal() : false);
|
||||
$const->setComment(Helpers::unformatDocComment((string) $from->getDocComment()));
|
||||
$const->setAttributes($this->getAttributes($from));
|
||||
return $const;
|
||||
}
|
||||
|
||||
|
||||
public function fromCaseReflection(\ReflectionClassConstant $from): EnumCase
|
||||
{
|
||||
$const = new EnumCase($from->name);
|
||||
$const->setValue($from->getValue()->value ?? null);
|
||||
$const->setComment(Helpers::unformatDocComment((string) $from->getDocComment()));
|
||||
$const->setAttributes($this->getAttributes($from));
|
||||
return $const;
|
||||
}
|
||||
|
||||
|
||||
public function fromPropertyReflection(\ReflectionProperty $from): Property
|
||||
{
|
||||
$defaults = $from->getDeclaringClass()->getDefaultProperties();
|
||||
$prop = new Property($from->name);
|
||||
$prop->setValue($defaults[$prop->getName()] ?? null);
|
||||
$prop->setStatic($from->isStatic());
|
||||
$prop->setVisibility($this->getVisibility($from));
|
||||
if (PHP_VERSION_ID >= 70400) {
|
||||
if ($from->getType() instanceof \ReflectionNamedType) {
|
||||
$prop->setType($from->getType()->getName());
|
||||
$prop->setNullable($from->getType()->allowsNull());
|
||||
} elseif (
|
||||
$from->getType() instanceof \ReflectionUnionType
|
||||
|| $from->getType() instanceof \ReflectionIntersectionType
|
||||
) {
|
||||
$prop->setType((string) $from->getType());
|
||||
}
|
||||
|
||||
$prop->setInitialized($from->hasType() && array_key_exists($prop->getName(), $defaults));
|
||||
$prop->setReadOnly(PHP_VERSION_ID >= 80100 ? $from->isReadOnly() : false);
|
||||
} else {
|
||||
$prop->setInitialized(false);
|
||||
}
|
||||
|
||||
$prop->setComment(Helpers::unformatDocComment((string) $from->getDocComment()));
|
||||
$prop->setAttributes($this->getAttributes($from));
|
||||
return $prop;
|
||||
}
|
||||
|
||||
|
||||
public function fromObject(object $obj): Literal
|
||||
{
|
||||
return new Literal('new \\' . get_class($obj) . '(/* unknown */)');
|
||||
}
|
||||
|
||||
|
||||
public function fromClassCode(string $code): ClassType
|
||||
{
|
||||
$classes = $this->fromCode($code)->getClasses();
|
||||
if (!$classes) {
|
||||
throw new Nette\InvalidStateException('The code does not contain any class.');
|
||||
}
|
||||
|
||||
return reset($classes);
|
||||
}
|
||||
|
||||
|
||||
public function fromCode(string $code): PhpFile
|
||||
{
|
||||
$reader = new Extractor($code);
|
||||
return $reader->extractAll();
|
||||
}
|
||||
|
||||
|
||||
private function getAttributes($from): array
|
||||
{
|
||||
if (PHP_VERSION_ID < 80000) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return array_map(function ($attr) {
|
||||
$args = $attr->getArguments();
|
||||
foreach ($args as &$arg) {
|
||||
if (is_object($arg)) {
|
||||
$arg = $this->fromObject($arg);
|
||||
}
|
||||
}
|
||||
|
||||
return new Attribute($attr->getName(), $args);
|
||||
}, $from->getAttributes());
|
||||
}
|
||||
|
||||
|
||||
private function getVisibility($from): string
|
||||
{
|
||||
return $from->isPrivate()
|
||||
? ClassType::VisibilityPrivate
|
||||
: ($from->isProtected() ? ClassType::VisibilityProtected : ClassType::VisibilityPublic);
|
||||
}
|
||||
|
||||
|
||||
private function getExtractor($from): Extractor
|
||||
{
|
||||
$file = $from->getFileName();
|
||||
$cache = &$this->extractorCache[$file];
|
||||
if ($cache !== null) {
|
||||
return $cache;
|
||||
} elseif (!$file) {
|
||||
throw new Nette\InvalidStateException("Source code of $from->name not found.");
|
||||
}
|
||||
|
||||
return new Extractor(file_get_contents($file));
|
||||
}
|
||||
}
|
||||
53
vendor/nette/php-generator/src/PhpGenerator/GlobalFunction.php
vendored
Normal file
53
vendor/nette/php-generator/src/PhpGenerator/GlobalFunction.php
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator;
|
||||
|
||||
use Nette;
|
||||
|
||||
|
||||
/**
|
||||
* Global function.
|
||||
*
|
||||
* @property string $body
|
||||
*/
|
||||
final class GlobalFunction
|
||||
{
|
||||
use Nette\SmartObject;
|
||||
use Traits\FunctionLike;
|
||||
use Traits\NameAware;
|
||||
use Traits\CommentAware;
|
||||
use Traits\AttributeAware;
|
||||
|
||||
public static function from(string $function, bool $withBody = false): self
|
||||
{
|
||||
return (new Factory)->fromFunctionReflection(new \ReflectionFunction($function), $withBody);
|
||||
}
|
||||
|
||||
|
||||
public static function withBodyFrom(string $function): self
|
||||
{
|
||||
return (new Factory)->fromFunctionReflection(new \ReflectionFunction($function), true);
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
try {
|
||||
return (new Printer)->printFunction($this);
|
||||
} catch (\Throwable $e) {
|
||||
if (PHP_VERSION_ID >= 70400) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
trigger_error('Exception in ' . __METHOD__ . "(): {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}", E_USER_ERROR);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
184
vendor/nette/php-generator/src/PhpGenerator/Helpers.php
vendored
Normal file
184
vendor/nette/php-generator/src/PhpGenerator/Helpers.php
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator;
|
||||
|
||||
use Nette;
|
||||
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class Helpers
|
||||
{
|
||||
use Nette\StaticClass;
|
||||
|
||||
public const ReIdentifier = '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*';
|
||||
|
||||
public const Keywords = [
|
||||
// built-in types
|
||||
'string' => 1, 'int' => 1, 'float' => 1, 'bool' => 1, 'array' => 1, 'object' => 1,
|
||||
'callable' => 1, 'iterable' => 1, 'void' => 1, 'null' => 1, 'mixed' => 1, 'false' => 1,
|
||||
'never' => 1,
|
||||
|
||||
// class keywords
|
||||
'self' => 1, 'parent' => 1, 'static' => 1,
|
||||
|
||||
// PHP keywords
|
||||
'include' => 1, 'include_once' => 1, 'eval' => 1, 'require' => 1, 'require_once' => 1, 'or' => 1, 'xor' => 1,
|
||||
'and' => 1, 'instanceof' => 1, 'new' => 1, 'clone' => 1, 'exit' => 1, 'if' => 1, 'elseif' => 1, 'else' => 1,
|
||||
'endif' => 1, 'echo' => 1, 'do' => 1, 'while' => 1, 'endwhile' => 1, 'for' => 1, 'endfor' => 1, 'foreach' => 1,
|
||||
'endforeach' => 1, 'declare' => 1, 'enddeclare' => 1, 'as' => 1, 'try' => 1, 'catch' => 1, 'finally' => 1,
|
||||
'throw' => 1, 'use' => 1, 'insteadof' => 1, 'global' => 1, 'var' => 1, 'unset' => 1, 'isset' => 1, 'empty' => 1,
|
||||
'continue' => 1, 'goto' => 1, 'function' => 1, 'const' => 1, 'return' => 1, 'print' => 1, 'yield' => 1, 'list' => 1,
|
||||
'switch' => 1, 'endswitch' => 1, 'case' => 1, 'default' => 1, 'break' => 1,
|
||||
'extends' => 1, 'implements' => 1, 'namespace' => 1, 'trait' => 1, 'interface' => 1, 'class' => 1, '__CLASS__' => 1,
|
||||
'__TRAIT__' => 1, '__FUNCTION__' => 1, '__METHOD__' => 1, '__LINE__' => 1, '__FILE__' => 1, '__DIR__' => 1,
|
||||
'__NAMESPACE__' => 1, 'fn' => 1, 'match' => 1, 'enum' => 1, 'abstract' => 1, 'final' => 1,
|
||||
'private' => 1, 'protected' => 1, 'public' => 1, 'readonly' => 1,
|
||||
|
||||
// additional reserved class names
|
||||
'true' => 1,
|
||||
];
|
||||
|
||||
/** @deprecated */
|
||||
public const
|
||||
PHP_IDENT = self::ReIdentifier,
|
||||
KEYWORDS = self::Keywords;
|
||||
|
||||
|
||||
/** @deprecated use (new Nette\PhpGenerator\Dumper)->dump() */
|
||||
public static function dump($var): string
|
||||
{
|
||||
return (new Dumper)->dump($var);
|
||||
}
|
||||
|
||||
|
||||
/** @deprecated use (new Nette\PhpGenerator\Dumper)->format() */
|
||||
public static function format(string $statement, ...$args): string
|
||||
{
|
||||
return (new Dumper)->format($statement, ...$args);
|
||||
}
|
||||
|
||||
|
||||
/** @deprecated use (new Nette\PhpGenerator\Dumper)->format() */
|
||||
public static function formatArgs(string $statement, array $args): string
|
||||
{
|
||||
return (new Dumper)->format($statement, ...$args);
|
||||
}
|
||||
|
||||
|
||||
public static function formatDocComment(string $content): string
|
||||
{
|
||||
$s = trim($content);
|
||||
$s = str_replace('*/', '* /', $s);
|
||||
if ($s === '') {
|
||||
return '';
|
||||
} elseif (strpos($content, "\n") === false) {
|
||||
return "/** $s */\n";
|
||||
} else {
|
||||
return str_replace("\n", "\n * ", "/**\n$s") . "\n */\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function tagName(string $name, string $of = PhpNamespace::NameNormal): string
|
||||
{
|
||||
return isset(self::Keywords[strtolower($name)])
|
||||
? $name
|
||||
: "/*($of*/$name";
|
||||
}
|
||||
|
||||
|
||||
public static function simplifyTaggedNames(string $code, ?PhpNamespace $namespace): string
|
||||
{
|
||||
return preg_replace_callback('~/\*\(([ncf])\*/([\w\x7f-\xff\\\\]++)~', function ($m) use ($namespace) {
|
||||
[, $of, $name] = $m;
|
||||
return $namespace
|
||||
? $namespace->simplifyType($name, $of)
|
||||
: $name;
|
||||
}, $code);
|
||||
}
|
||||
|
||||
|
||||
public static function unformatDocComment(string $comment): string
|
||||
{
|
||||
return preg_replace('#^\s*\* ?#m', '', trim(trim(trim($comment), '/*')));
|
||||
}
|
||||
|
||||
|
||||
public static function unindent(string $s, int $level = 1): string
|
||||
{
|
||||
return $level
|
||||
? preg_replace('#^(\t| {4}){1,' . $level . '}#m', '', $s)
|
||||
: $s;
|
||||
}
|
||||
|
||||
|
||||
public static function isIdentifier($value): bool
|
||||
{
|
||||
return is_string($value) && preg_match('#^' . self::ReIdentifier . '$#D', $value);
|
||||
}
|
||||
|
||||
|
||||
public static function isNamespaceIdentifier($value, bool $allowLeadingSlash = false): bool
|
||||
{
|
||||
$re = '#^' . ($allowLeadingSlash ? '\\\\?' : '') . self::ReIdentifier . '(\\\\' . self::ReIdentifier . ')*$#D';
|
||||
return is_string($value) && preg_match($re, $value);
|
||||
}
|
||||
|
||||
|
||||
public static function extractNamespace(string $name): string
|
||||
{
|
||||
return ($pos = strrpos($name, '\\')) ? substr($name, 0, $pos) : '';
|
||||
}
|
||||
|
||||
|
||||
public static function extractShortName(string $name): string
|
||||
{
|
||||
return ($pos = strrpos($name, '\\')) === false
|
||||
? $name
|
||||
: substr($name, $pos + 1);
|
||||
}
|
||||
|
||||
|
||||
public static function tabsToSpaces(string $s, int $count = 4): string
|
||||
{
|
||||
return str_replace("\t", str_repeat(' ', $count), $s);
|
||||
}
|
||||
|
||||
|
||||
/** @internal */
|
||||
public static function createObject(string $class, array $props): object
|
||||
{
|
||||
return Dumper::createObject($class, $props);
|
||||
}
|
||||
|
||||
|
||||
public static function validateType(?string $type, bool &$nullable): ?string
|
||||
{
|
||||
if ($type === '' || $type === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!preg_match('#(?:
|
||||
\?[\w\\\\]+|
|
||||
[\w\\\\]+ (?: (&[\w\\\\]+)* | (\|[\w\\\\]+)* )
|
||||
)()$#xAD', $type)) {
|
||||
throw new Nette\InvalidArgumentException("Value '$type' is not valid type.");
|
||||
}
|
||||
|
||||
if ($type[0] === '?') {
|
||||
$nullable = true;
|
||||
return substr($type, 1);
|
||||
}
|
||||
|
||||
return $type;
|
||||
}
|
||||
}
|
||||
45
vendor/nette/php-generator/src/PhpGenerator/Literal.php
vendored
Normal file
45
vendor/nette/php-generator/src/PhpGenerator/Literal.php
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator;
|
||||
|
||||
|
||||
/**
|
||||
* PHP literal value.
|
||||
*/
|
||||
class Literal
|
||||
{
|
||||
/** @var string */
|
||||
private $value;
|
||||
|
||||
/** @var ?array */
|
||||
private $args;
|
||||
|
||||
|
||||
public function __construct(string $value, ?array $args = null)
|
||||
{
|
||||
$this->value = $value;
|
||||
$this->args = $args;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->formatWith(new Dumper);
|
||||
}
|
||||
|
||||
|
||||
/** @internal */
|
||||
public function formatWith(Dumper $dumper): string
|
||||
{
|
||||
return $this->args === null
|
||||
? $this->value
|
||||
: $dumper->format($this->value, ...$this->args);
|
||||
}
|
||||
}
|
||||
145
vendor/nette/php-generator/src/PhpGenerator/Method.php
vendored
Normal file
145
vendor/nette/php-generator/src/PhpGenerator/Method.php
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator;
|
||||
|
||||
use Nette;
|
||||
|
||||
|
||||
/**
|
||||
* Class method.
|
||||
*
|
||||
* @property string|null $body
|
||||
*/
|
||||
final class Method
|
||||
{
|
||||
use Nette\SmartObject;
|
||||
use Traits\FunctionLike;
|
||||
use Traits\NameAware;
|
||||
use Traits\VisibilityAware;
|
||||
use Traits\CommentAware;
|
||||
use Traits\AttributeAware;
|
||||
|
||||
/** @var string|null */
|
||||
private $body = '';
|
||||
|
||||
/** @var bool */
|
||||
private $static = false;
|
||||
|
||||
/** @var bool */
|
||||
private $final = false;
|
||||
|
||||
/** @var bool */
|
||||
private $abstract = false;
|
||||
|
||||
|
||||
/**
|
||||
* @param string|array $method
|
||||
*/
|
||||
public static function from($method): self
|
||||
{
|
||||
return (new Factory)->fromMethodReflection(Nette\Utils\Callback::toReflection($method));
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
try {
|
||||
return (new Printer)->printMethod($this);
|
||||
} catch (\Throwable $e) {
|
||||
if (PHP_VERSION_ID >= 70400) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
trigger_error('Exception in ' . __METHOD__ . "(): {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}", E_USER_ERROR);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setBody(?string $code, ?array $args = null): self
|
||||
{
|
||||
$this->body = $args === null || $code === null
|
||||
? $code
|
||||
: (new Dumper)->format($code, ...$args);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function getBody(): ?string
|
||||
{
|
||||
return $this->body;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setStatic(bool $state = true): self
|
||||
{
|
||||
$this->static = $state;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function isStatic(): bool
|
||||
{
|
||||
return $this->static;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setFinal(bool $state = true): self
|
||||
{
|
||||
$this->final = $state;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function isFinal(): bool
|
||||
{
|
||||
return $this->final;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setAbstract(bool $state = true): self
|
||||
{
|
||||
$this->abstract = $state;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function isAbstract(): bool
|
||||
{
|
||||
return $this->abstract;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $name without $
|
||||
*/
|
||||
public function addPromotedParameter(string $name, $defaultValue = null): PromotedParameter
|
||||
{
|
||||
$param = new PromotedParameter($name);
|
||||
if (func_num_args() > 1) {
|
||||
$param->setDefaultValue($defaultValue);
|
||||
}
|
||||
|
||||
return $this->parameters[$name] = $param;
|
||||
}
|
||||
|
||||
|
||||
/** @throws Nette\InvalidStateException */
|
||||
public function validate(): void
|
||||
{
|
||||
if ($this->abstract && ($this->final || $this->visibility === ClassType::VisibilityPrivate)) {
|
||||
throw new Nette\InvalidStateException("Method $this->name() cannot be abstract and final or private at the same time.");
|
||||
}
|
||||
}
|
||||
}
|
||||
140
vendor/nette/php-generator/src/PhpGenerator/Parameter.php
vendored
Normal file
140
vendor/nette/php-generator/src/PhpGenerator/Parameter.php
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator;
|
||||
|
||||
use Nette;
|
||||
use Nette\Utils\Type;
|
||||
|
||||
|
||||
/**
|
||||
* Function/Method parameter description.
|
||||
*
|
||||
* @property mixed $defaultValue
|
||||
*/
|
||||
class Parameter
|
||||
{
|
||||
use Nette\SmartObject;
|
||||
use Traits\NameAware;
|
||||
use Traits\AttributeAware;
|
||||
|
||||
/** @var bool */
|
||||
private $reference = false;
|
||||
|
||||
/** @var string|null */
|
||||
private $type;
|
||||
|
||||
/** @var bool */
|
||||
private $nullable = false;
|
||||
|
||||
/** @var bool */
|
||||
private $hasDefaultValue = false;
|
||||
|
||||
/** @var mixed */
|
||||
private $defaultValue;
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setReference(bool $state = true): self
|
||||
{
|
||||
$this->reference = $state;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function isReference(): bool
|
||||
{
|
||||
return $this->reference;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setType(?string $type): self
|
||||
{
|
||||
$this->type = Helpers::validateType($type, $this->nullable);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Type|string|null
|
||||
*/
|
||||
public function getType(bool $asObject = false)
|
||||
{
|
||||
return $asObject && $this->type
|
||||
? Type::fromString($this->type)
|
||||
: $this->type;
|
||||
}
|
||||
|
||||
|
||||
/** @deprecated use setType() */
|
||||
public function setTypeHint(?string $type): self
|
||||
{
|
||||
return $this->setType($type);
|
||||
}
|
||||
|
||||
|
||||
/** @deprecated use getType() */
|
||||
public function getTypeHint(): ?string
|
||||
{
|
||||
return $this->getType();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated just use setDefaultValue()
|
||||
* @return static
|
||||
*/
|
||||
public function setOptional(bool $state = true): self
|
||||
{
|
||||
trigger_error(__METHOD__ . '() is deprecated, use setDefaultValue()', E_USER_DEPRECATED);
|
||||
$this->hasDefaultValue = $state;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setNullable(bool $state = true): self
|
||||
{
|
||||
$this->nullable = $state;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function isNullable(): bool
|
||||
{
|
||||
return $this->nullable;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setDefaultValue($val): self
|
||||
{
|
||||
$this->defaultValue = $val;
|
||||
$this->hasDefaultValue = true;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function getDefaultValue()
|
||||
{
|
||||
return $this->defaultValue;
|
||||
}
|
||||
|
||||
|
||||
public function hasDefaultValue(): bool
|
||||
{
|
||||
return $this->hasDefaultValue;
|
||||
}
|
||||
|
||||
|
||||
public function validate(): void
|
||||
{
|
||||
}
|
||||
}
|
||||
184
vendor/nette/php-generator/src/PhpGenerator/PhpFile.php
vendored
Normal file
184
vendor/nette/php-generator/src/PhpGenerator/PhpFile.php
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator;
|
||||
|
||||
use Nette;
|
||||
|
||||
|
||||
/**
|
||||
* Instance of PHP file.
|
||||
*
|
||||
* Generates:
|
||||
* - opening tag (<?php)
|
||||
* - doc comments
|
||||
* - one or more namespaces
|
||||
*/
|
||||
final class PhpFile
|
||||
{
|
||||
use Nette\SmartObject;
|
||||
use Traits\CommentAware;
|
||||
|
||||
/** @var PhpNamespace[] */
|
||||
private $namespaces = [];
|
||||
|
||||
/** @var bool */
|
||||
private $strictTypes = false;
|
||||
|
||||
|
||||
public static function fromCode(string $code): self
|
||||
{
|
||||
return (new Factory)->fromCode($code);
|
||||
}
|
||||
|
||||
|
||||
public function addClass(string $name): ClassType
|
||||
{
|
||||
return $this
|
||||
->addNamespace(Helpers::extractNamespace($name))
|
||||
->addClass(Helpers::extractShortName($name));
|
||||
}
|
||||
|
||||
|
||||
public function addInterface(string $name): ClassType
|
||||
{
|
||||
return $this
|
||||
->addNamespace(Helpers::extractNamespace($name))
|
||||
->addInterface(Helpers::extractShortName($name));
|
||||
}
|
||||
|
||||
|
||||
public function addTrait(string $name): ClassType
|
||||
{
|
||||
return $this
|
||||
->addNamespace(Helpers::extractNamespace($name))
|
||||
->addTrait(Helpers::extractShortName($name));
|
||||
}
|
||||
|
||||
|
||||
public function addEnum(string $name): ClassType
|
||||
{
|
||||
return $this
|
||||
->addNamespace(Helpers::extractNamespace($name))
|
||||
->addEnum(Helpers::extractShortName($name));
|
||||
}
|
||||
|
||||
|
||||
/** @param string|PhpNamespace $namespace */
|
||||
public function addNamespace($namespace): PhpNamespace
|
||||
{
|
||||
if ($namespace instanceof PhpNamespace) {
|
||||
$res = $this->namespaces[$namespace->getName()] = $namespace;
|
||||
|
||||
} elseif (is_string($namespace)) {
|
||||
$res = $this->namespaces[$namespace] = $this->namespaces[$namespace] ?? new PhpNamespace($namespace);
|
||||
|
||||
} else {
|
||||
throw new Nette\InvalidArgumentException('Argument must be string|PhpNamespace.');
|
||||
}
|
||||
|
||||
foreach ($this->namespaces as $namespace) {
|
||||
$namespace->setBracketedSyntax(count($this->namespaces) > 1 && isset($this->namespaces['']));
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
public function addFunction(string $name): GlobalFunction
|
||||
{
|
||||
return $this
|
||||
->addNamespace(Helpers::extractNamespace($name))
|
||||
->addFunction(Helpers::extractShortName($name));
|
||||
}
|
||||
|
||||
|
||||
/** @return PhpNamespace[] */
|
||||
public function getNamespaces(): array
|
||||
{
|
||||
return $this->namespaces;
|
||||
}
|
||||
|
||||
|
||||
/** @return ClassType[] */
|
||||
public function getClasses(): array
|
||||
{
|
||||
$classes = [];
|
||||
foreach ($this->namespaces as $n => $namespace) {
|
||||
$n .= $n ? '\\' : '';
|
||||
foreach ($namespace->getClasses() as $c => $class) {
|
||||
$classes[$n . $c] = $class;
|
||||
}
|
||||
}
|
||||
|
||||
return $classes;
|
||||
}
|
||||
|
||||
|
||||
/** @return GlobalFunction[] */
|
||||
public function getFunctions(): array
|
||||
{
|
||||
$functions = [];
|
||||
foreach ($this->namespaces as $n => $namespace) {
|
||||
$n .= $n ? '\\' : '';
|
||||
foreach ($namespace->getFunctions() as $f => $function) {
|
||||
$functions[$n . $f] = $function;
|
||||
}
|
||||
}
|
||||
|
||||
return $functions;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function addUse(string $name, ?string $alias = null, string $of = PhpNamespace::NameNormal): self
|
||||
{
|
||||
$this->addNamespace('')->addUse($name, $alias, $of);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds declare(strict_types=1) to output.
|
||||
* @return static
|
||||
*/
|
||||
public function setStrictTypes(bool $on = true): self
|
||||
{
|
||||
$this->strictTypes = $on;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function hasStrictTypes(): bool
|
||||
{
|
||||
return $this->strictTypes;
|
||||
}
|
||||
|
||||
|
||||
/** @deprecated use hasStrictTypes() */
|
||||
public function getStrictTypes(): bool
|
||||
{
|
||||
return $this->strictTypes;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
try {
|
||||
return (new Printer)->printFile($this);
|
||||
} catch (\Throwable $e) {
|
||||
if (PHP_VERSION_ID >= 70400) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
trigger_error('Exception in ' . __METHOD__ . "(): {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}", E_USER_ERROR);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
15
vendor/nette/php-generator/src/PhpGenerator/PhpLiteral.php
vendored
Normal file
15
vendor/nette/php-generator/src/PhpGenerator/PhpLiteral.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator;
|
||||
|
||||
|
||||
class PhpLiteral extends Literal
|
||||
{
|
||||
}
|
||||
367
vendor/nette/php-generator/src/PhpGenerator/PhpNamespace.php
vendored
Normal file
367
vendor/nette/php-generator/src/PhpGenerator/PhpNamespace.php
vendored
Normal file
@@ -0,0 +1,367 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator;
|
||||
|
||||
use Nette;
|
||||
use Nette\InvalidStateException;
|
||||
|
||||
|
||||
/**
|
||||
* Namespaced part of a PHP file.
|
||||
*
|
||||
* Generates:
|
||||
* - namespace statement
|
||||
* - variable amount of use statements
|
||||
* - one or more class declarations
|
||||
*/
|
||||
final class PhpNamespace
|
||||
{
|
||||
use Nette\SmartObject;
|
||||
|
||||
public const
|
||||
NameNormal = 'n',
|
||||
NameFunction = 'f',
|
||||
NameConstant = 'c';
|
||||
|
||||
public const
|
||||
NAME_NORMAL = self::NameNormal,
|
||||
NAME_FUNCTION = self::NameFunction,
|
||||
NAME_CONSTANT = self::NameConstant;
|
||||
|
||||
/** @var string */
|
||||
private $name;
|
||||
|
||||
/** @var bool */
|
||||
private $bracketedSyntax = false;
|
||||
|
||||
/** @var string[][] */
|
||||
private $aliases = [
|
||||
self::NameNormal => [],
|
||||
self::NameFunction => [],
|
||||
self::NameConstant => [],
|
||||
];
|
||||
|
||||
/** @var ClassType[] */
|
||||
private $classes = [];
|
||||
|
||||
/** @var GlobalFunction[] */
|
||||
private $functions = [];
|
||||
|
||||
|
||||
public function __construct(string $name)
|
||||
{
|
||||
if ($name !== '' && !Helpers::isNamespaceIdentifier($name)) {
|
||||
throw new Nette\InvalidArgumentException("Value '$name' is not valid name.");
|
||||
}
|
||||
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return static
|
||||
* @internal
|
||||
*/
|
||||
public function setBracketedSyntax(bool $state = true): self
|
||||
{
|
||||
$this->bracketedSyntax = $state;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function hasBracketedSyntax(): bool
|
||||
{
|
||||
return $this->bracketedSyntax;
|
||||
}
|
||||
|
||||
|
||||
/** @deprecated use hasBracketedSyntax() */
|
||||
public function getBracketedSyntax(): bool
|
||||
{
|
||||
return $this->bracketedSyntax;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws InvalidStateException
|
||||
* @return static
|
||||
*/
|
||||
public function addUse(string $name, ?string $alias = null, string $of = self::NameNormal): self
|
||||
{
|
||||
if (
|
||||
!Helpers::isNamespaceIdentifier($name, true)
|
||||
|| (Helpers::isIdentifier($name) && isset(Helpers::Keywords[strtolower($name)]))
|
||||
) {
|
||||
throw new Nette\InvalidArgumentException("Value '$name' is not valid class/function/constant name.");
|
||||
|
||||
} elseif ($alias && (!Helpers::isIdentifier($alias) || isset(Helpers::Keywords[strtolower($alias)]))) {
|
||||
throw new Nette\InvalidArgumentException("Value '$alias' is not valid alias.");
|
||||
}
|
||||
|
||||
$name = ltrim($name, '\\');
|
||||
$aliases = array_change_key_case($this->aliases[$of]);
|
||||
$used = [self::NameNormal => $this->classes, self::NameFunction => $this->functions, self::NameConstant => []][$of];
|
||||
|
||||
if ($alias === null) {
|
||||
$base = Helpers::extractShortName($name);
|
||||
$counter = null;
|
||||
do {
|
||||
$alias = $base . $counter;
|
||||
$lower = strtolower($alias);
|
||||
$counter++;
|
||||
} while ((isset($aliases[$lower]) && strcasecmp($aliases[$lower], $name) !== 0) || isset($used[$lower]));
|
||||
} else {
|
||||
$lower = strtolower($alias);
|
||||
if (isset($aliases[$lower]) && strcasecmp($aliases[$lower], $name) !== 0) {
|
||||
throw new InvalidStateException(
|
||||
"Alias '$alias' used already for '{$aliases[$lower]}', cannot use for '$name'."
|
||||
);
|
||||
} elseif (isset($used[$lower])) {
|
||||
throw new Nette\InvalidStateException("Name '$alias' used already for '$this->name\\{$used[$lower]->getName()}'.");
|
||||
}
|
||||
}
|
||||
|
||||
$this->aliases[$of][$alias] = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function removeUse(string $name, string $of = self::NameNormal): void
|
||||
{
|
||||
foreach ($this->aliases[$of] as $alias => $item) {
|
||||
if (strcasecmp($item, $name) === 0) {
|
||||
unset($this->aliases[$of][$alias]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function addUseFunction(string $name, ?string $alias = null): self
|
||||
{
|
||||
return $this->addUse($name, $alias, self::NameFunction);
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function addUseConstant(string $name, ?string $alias = null): self
|
||||
{
|
||||
return $this->addUse($name, $alias, self::NameConstant);
|
||||
}
|
||||
|
||||
|
||||
/** @return string[] */
|
||||
public function getUses(string $of = self::NameNormal): array
|
||||
{
|
||||
asort($this->aliases[$of]);
|
||||
return array_filter(
|
||||
$this->aliases[$of],
|
||||
function ($name, $alias) { return strcasecmp(($this->name ? $this->name . '\\' : '') . $alias, $name); },
|
||||
ARRAY_FILTER_USE_BOTH
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/** @deprecated use simplifyName() */
|
||||
public function unresolveName(string $name): string
|
||||
{
|
||||
return $this->simplifyName($name);
|
||||
}
|
||||
|
||||
|
||||
public function resolveName(string $name, string $of = self::NameNormal): string
|
||||
{
|
||||
if (isset(Helpers::Keywords[strtolower($name)]) || $name === '') {
|
||||
return $name;
|
||||
} elseif ($name[0] === '\\') {
|
||||
return substr($name, 1);
|
||||
}
|
||||
|
||||
$aliases = array_change_key_case($this->aliases[$of]);
|
||||
if ($of !== self::NameNormal) {
|
||||
return $aliases[strtolower($name)]
|
||||
?? $this->resolveName(Helpers::extractNamespace($name) . '\\') . Helpers::extractShortName($name);
|
||||
}
|
||||
|
||||
$parts = explode('\\', $name, 2);
|
||||
return ($res = $aliases[strtolower($parts[0])] ?? null)
|
||||
? $res . (isset($parts[1]) ? '\\' . $parts[1] : '')
|
||||
: $this->name . ($this->name ? '\\' : '') . $name;
|
||||
}
|
||||
|
||||
|
||||
public function simplifyType(string $type, string $of = self::NameNormal): string
|
||||
{
|
||||
return preg_replace_callback('~[\w\x7f-\xff\\\\]+~', function ($m) use ($of) { return $this->simplifyName($m[0], $of); }, $type);
|
||||
}
|
||||
|
||||
|
||||
public function simplifyName(string $name, string $of = self::NameNormal): string
|
||||
{
|
||||
if (isset(Helpers::Keywords[strtolower($name)]) || $name === '') {
|
||||
return $name;
|
||||
}
|
||||
|
||||
$name = ltrim($name, '\\');
|
||||
|
||||
if ($of !== self::NameNormal) {
|
||||
foreach ($this->aliases[$of] as $alias => $original) {
|
||||
if (strcasecmp($original, $name) === 0) {
|
||||
return $alias;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->simplifyName(Helpers::extractNamespace($name) . '\\') . Helpers::extractShortName($name);
|
||||
}
|
||||
|
||||
$shortest = null;
|
||||
$relative = self::startsWith($name, $this->name . '\\')
|
||||
? substr($name, strlen($this->name) + 1)
|
||||
: null;
|
||||
|
||||
foreach ($this->aliases[$of] as $alias => $original) {
|
||||
if ($relative && self::startsWith($relative . '\\', $alias . '\\')) {
|
||||
$relative = null;
|
||||
}
|
||||
|
||||
if (self::startsWith($name . '\\', $original . '\\')) {
|
||||
$short = $alias . substr($name, strlen($original));
|
||||
if (!isset($shortest) || strlen($shortest) > strlen($short)) {
|
||||
$shortest = $short;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($shortest, $relative) && strlen($shortest) < strlen($relative)) {
|
||||
return $shortest;
|
||||
}
|
||||
|
||||
return $relative ?? $shortest ?? ($this->name ? '\\' : '') . $name;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function add(ClassType $class): self
|
||||
{
|
||||
$name = $class->getName();
|
||||
if ($name === null) {
|
||||
throw new Nette\InvalidArgumentException('Class does not have a name.');
|
||||
}
|
||||
|
||||
$lower = strtolower($name);
|
||||
if ($orig = array_change_key_case($this->aliases[self::NameNormal])[$lower] ?? null) {
|
||||
throw new Nette\InvalidStateException("Name '$name' used already as alias for $orig.");
|
||||
}
|
||||
|
||||
$this->classes[$lower] = $class;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function addClass(string $name): ClassType
|
||||
{
|
||||
$this->add($class = new ClassType($name, $this));
|
||||
return $class;
|
||||
}
|
||||
|
||||
|
||||
public function addInterface(string $name): ClassType
|
||||
{
|
||||
return $this->addClass($name)->setType(ClassType::TYPE_INTERFACE);
|
||||
}
|
||||
|
||||
|
||||
public function addTrait(string $name): ClassType
|
||||
{
|
||||
return $this->addClass($name)->setType(ClassType::TYPE_TRAIT);
|
||||
}
|
||||
|
||||
|
||||
public function addEnum(string $name): ClassType
|
||||
{
|
||||
return $this->addClass($name)->setType(ClassType::TYPE_ENUM);
|
||||
}
|
||||
|
||||
|
||||
public function removeClass(string $name): self
|
||||
{
|
||||
unset($this->classes[strtolower($name)]);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function addFunction(string $name): GlobalFunction
|
||||
{
|
||||
$lower = strtolower($name);
|
||||
if ($orig = array_change_key_case($this->aliases[self::NameFunction])[$lower] ?? null) {
|
||||
throw new Nette\InvalidStateException("Name '$name' used already as alias for $orig.");
|
||||
}
|
||||
|
||||
return $this->functions[$lower] = new GlobalFunction($name);
|
||||
}
|
||||
|
||||
|
||||
public function removeFunction(string $name): self
|
||||
{
|
||||
unset($this->functions[strtolower($name)]);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/** @return ClassType[] */
|
||||
public function getClasses(): array
|
||||
{
|
||||
$res = [];
|
||||
foreach ($this->classes as $class) {
|
||||
$res[$class->getName()] = $class;
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
/** @return GlobalFunction[] */
|
||||
public function getFunctions(): array
|
||||
{
|
||||
$res = [];
|
||||
foreach ($this->functions as $fn) {
|
||||
$res[$fn->getName()] = $fn;
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
private static function startsWith(string $a, string $b): bool
|
||||
{
|
||||
return strncasecmp($a, $b, strlen($b)) === 0;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
try {
|
||||
return (new Printer)->printNamespace($this);
|
||||
} catch (\Throwable $e) {
|
||||
if (PHP_VERSION_ID >= 70400) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
trigger_error('Exception in ' . __METHOD__ . "(): {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}", E_USER_ERROR);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
424
vendor/nette/php-generator/src/PhpGenerator/Printer.php
vendored
Normal file
424
vendor/nette/php-generator/src/PhpGenerator/Printer.php
vendored
Normal file
@@ -0,0 +1,424 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator;
|
||||
|
||||
use Nette;
|
||||
use Nette\Utils\Strings;
|
||||
|
||||
|
||||
/**
|
||||
* Generates PHP code.
|
||||
*/
|
||||
class Printer
|
||||
{
|
||||
use Nette\SmartObject;
|
||||
|
||||
/** @var int */
|
||||
public $wrapLength = 120;
|
||||
|
||||
/** @var string */
|
||||
protected $indentation = "\t";
|
||||
|
||||
/** @var int */
|
||||
protected $linesBetweenProperties = 0;
|
||||
|
||||
/** @var int */
|
||||
protected $linesBetweenMethods = 2;
|
||||
|
||||
/** @var string */
|
||||
protected $returnTypeColon = ': ';
|
||||
|
||||
/** @var ?PhpNamespace */
|
||||
protected $namespace;
|
||||
|
||||
/** @var ?Dumper */
|
||||
protected $dumper;
|
||||
|
||||
/** @var bool */
|
||||
private $resolveTypes = true;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->dumper = new Dumper;
|
||||
}
|
||||
|
||||
|
||||
public function printFunction(GlobalFunction $function, ?PhpNamespace $namespace = null): string
|
||||
{
|
||||
$this->namespace = $this->resolveTypes ? $namespace : null;
|
||||
$line = 'function '
|
||||
. ($function->getReturnReference() ? '&' : '')
|
||||
. $function->getName();
|
||||
$returnType = $this->printReturnType($function);
|
||||
$body = Helpers::simplifyTaggedNames($function->getBody(), $this->namespace);
|
||||
|
||||
return Helpers::formatDocComment($function->getComment() . "\n")
|
||||
. $this->printAttributes($function->getAttributes())
|
||||
. $line
|
||||
. $this->printParameters($function, strlen($line) + strlen($returnType) + 2) // 2 = parentheses
|
||||
. $returnType
|
||||
. "\n{\n" . $this->indent(ltrim(rtrim($body) . "\n")) . "}\n";
|
||||
}
|
||||
|
||||
|
||||
public function printClosure(Closure $closure, ?PhpNamespace $namespace = null): string
|
||||
{
|
||||
$this->namespace = $this->resolveTypes ? $namespace : null;
|
||||
$uses = [];
|
||||
foreach ($closure->getUses() as $param) {
|
||||
$uses[] = ($param->isReference() ? '&' : '') . '$' . $param->getName();
|
||||
}
|
||||
|
||||
$useStr = strlen($tmp = implode(', ', $uses)) > $this->wrapLength && count($uses) > 1
|
||||
? "\n" . $this->indentation . implode(",\n" . $this->indentation, $uses) . "\n"
|
||||
: $tmp;
|
||||
$body = Helpers::simplifyTaggedNames($closure->getBody(), $this->namespace);
|
||||
|
||||
return $this->printAttributes($closure->getAttributes(), true)
|
||||
. 'function '
|
||||
. ($closure->getReturnReference() ? '&' : '')
|
||||
. $this->printParameters($closure)
|
||||
. ($uses ? " use ($useStr)" : '')
|
||||
. $this->printReturnType($closure)
|
||||
. " {\n" . $this->indent(ltrim(rtrim($body) . "\n")) . '}';
|
||||
}
|
||||
|
||||
|
||||
public function printArrowFunction(Closure $closure, ?PhpNamespace $namespace = null): string
|
||||
{
|
||||
$this->namespace = $this->resolveTypes ? $namespace : null;
|
||||
foreach ($closure->getUses() as $use) {
|
||||
if ($use->isReference()) {
|
||||
throw new Nette\InvalidArgumentException('Arrow function cannot bind variables by-reference.');
|
||||
}
|
||||
}
|
||||
|
||||
$body = Helpers::simplifyTaggedNames($closure->getBody(), $this->namespace);
|
||||
|
||||
return $this->printAttributes($closure->getAttributes())
|
||||
. 'fn'
|
||||
. ($closure->getReturnReference() ? '&' : '')
|
||||
. $this->printParameters($closure)
|
||||
. $this->printReturnType($closure)
|
||||
. ' => ' . trim($body) . ';';
|
||||
}
|
||||
|
||||
|
||||
public function printMethod(Method $method, ?PhpNamespace $namespace = null): string
|
||||
{
|
||||
$this->namespace = $this->resolveTypes ? $namespace : null;
|
||||
$method->validate();
|
||||
$line = ($method->isAbstract() ? 'abstract ' : '')
|
||||
. ($method->isFinal() ? 'final ' : '')
|
||||
. ($method->getVisibility() ? $method->getVisibility() . ' ' : '')
|
||||
. ($method->isStatic() ? 'static ' : '')
|
||||
. 'function '
|
||||
. ($method->getReturnReference() ? '&' : '')
|
||||
. $method->getName();
|
||||
$returnType = $this->printReturnType($method);
|
||||
$params = $this->printParameters($method, strlen($line) + strlen($returnType) + strlen($this->indentation) + 2);
|
||||
$body = Helpers::simplifyTaggedNames((string) $method->getBody(), $this->namespace);
|
||||
|
||||
return Helpers::formatDocComment($method->getComment() . "\n")
|
||||
. $this->printAttributes($method->getAttributes())
|
||||
. $line
|
||||
. $params
|
||||
. $returnType
|
||||
. ($method->isAbstract() || $method->getBody() === null
|
||||
? ";\n"
|
||||
: (strpos($params, "\n") === false ? "\n" : ' ')
|
||||
. "{\n"
|
||||
. $this->indent(ltrim(rtrim($body) . "\n"))
|
||||
. "}\n");
|
||||
}
|
||||
|
||||
|
||||
public function printClass(ClassType $class, ?PhpNamespace $namespace = null): string
|
||||
{
|
||||
$this->namespace = $this->resolveTypes ? $namespace : null;
|
||||
$class->validate();
|
||||
$resolver = $this->namespace
|
||||
? [$namespace, 'simplifyType']
|
||||
: function ($s) { return $s; };
|
||||
|
||||
$traits = [];
|
||||
foreach ($class->getTraitResolutions() as $trait) {
|
||||
$resolutions = $trait->getResolutions();
|
||||
$traits[] = Helpers::formatDocComment((string) $trait->getComment())
|
||||
. 'use ' . $resolver($trait->getName())
|
||||
. ($resolutions
|
||||
? " {\n" . $this->indentation . implode(";\n" . $this->indentation, $resolutions) . ";\n}\n"
|
||||
: ";\n");
|
||||
}
|
||||
|
||||
$cases = [];
|
||||
foreach ($class->getCases() as $case) {
|
||||
$cases[] = Helpers::formatDocComment((string) $case->getComment())
|
||||
. $this->printAttributes($case->getAttributes())
|
||||
. 'case ' . $case->getName()
|
||||
. ($case->getValue() === null ? '' : ' = ' . $this->dump($case->getValue()))
|
||||
. ";\n";
|
||||
}
|
||||
|
||||
$enumType = isset($case) && $case->getValue() !== null
|
||||
? $this->returnTypeColon . Type::getType($case->getValue())
|
||||
: '';
|
||||
|
||||
$consts = [];
|
||||
foreach ($class->getConstants() as $const) {
|
||||
$def = ($const->isFinal() ? 'final ' : '')
|
||||
. ($const->getVisibility() ? $const->getVisibility() . ' ' : '')
|
||||
. 'const ' . $const->getName() . ' = ';
|
||||
|
||||
$consts[] = Helpers::formatDocComment((string) $const->getComment())
|
||||
. $this->printAttributes($const->getAttributes())
|
||||
. $def
|
||||
. $this->dump($const->getValue(), strlen($def)) . ";\n";
|
||||
}
|
||||
|
||||
$properties = [];
|
||||
foreach ($class->getProperties() as $property) {
|
||||
$property->validate();
|
||||
$type = $property->getType();
|
||||
$def = (($property->getVisibility() ?: 'public')
|
||||
. ($property->isStatic() ? ' static' : '')
|
||||
. ($property->isReadOnly() && $type ? ' readonly' : '')
|
||||
. ' '
|
||||
. ltrim($this->printType($type, $property->isNullable()) . ' ')
|
||||
. '$' . $property->getName());
|
||||
|
||||
$properties[] = Helpers::formatDocComment((string) $property->getComment())
|
||||
. $this->printAttributes($property->getAttributes())
|
||||
. $def
|
||||
. ($property->getValue() === null && !$property->isInitialized()
|
||||
? ''
|
||||
: ' = ' . $this->dump($property->getValue(), strlen($def) + 3)) // 3 = ' = '
|
||||
. ";\n";
|
||||
}
|
||||
|
||||
$methods = [];
|
||||
foreach ($class->getMethods() as $method) {
|
||||
$methods[] = $this->printMethod($method, $namespace);
|
||||
}
|
||||
|
||||
$members = array_filter([
|
||||
implode('', $traits),
|
||||
$this->joinProperties($cases),
|
||||
$this->joinProperties($consts),
|
||||
$this->joinProperties($properties),
|
||||
($methods && $properties ? str_repeat("\n", $this->linesBetweenMethods - 1) : '')
|
||||
. implode(str_repeat("\n", $this->linesBetweenMethods), $methods),
|
||||
]);
|
||||
|
||||
return Strings::normalize(
|
||||
Helpers::formatDocComment($class->getComment() . "\n")
|
||||
. $this->printAttributes($class->getAttributes())
|
||||
. ($class->isAbstract() ? 'abstract ' : '')
|
||||
. ($class->isFinal() ? 'final ' : '')
|
||||
. ($class->getName() ? $class->getType() . ' ' . $class->getName() . $enumType . ' ' : '')
|
||||
. ($class->getExtends() ? 'extends ' . implode(', ', array_map($resolver, (array) $class->getExtends())) . ' ' : '')
|
||||
. ($class->getImplements() ? 'implements ' . implode(', ', array_map($resolver, $class->getImplements())) . ' ' : '')
|
||||
. ($class->getName() ? "\n" : '') . "{\n"
|
||||
. ($members ? $this->indent(implode("\n", $members)) : '')
|
||||
. '}'
|
||||
) . ($class->getName() ? "\n" : '');
|
||||
}
|
||||
|
||||
|
||||
public function printNamespace(PhpNamespace $namespace): string
|
||||
{
|
||||
$this->namespace = $this->resolveTypes ? $namespace : null;
|
||||
$name = $namespace->getName();
|
||||
$uses = $this->printUses($namespace)
|
||||
. $this->printUses($namespace, PhpNamespace::NameFunction)
|
||||
. $this->printUses($namespace, PhpNamespace::NameConstant);
|
||||
|
||||
$items = [];
|
||||
foreach ($namespace->getClasses() as $class) {
|
||||
$items[] = $this->printClass($class, $namespace);
|
||||
}
|
||||
|
||||
foreach ($namespace->getFunctions() as $function) {
|
||||
$items[] = $this->printFunction($function, $namespace);
|
||||
}
|
||||
|
||||
$body = ($uses ? $uses . "\n" : '')
|
||||
. implode("\n", $items);
|
||||
|
||||
if ($namespace->hasBracketedSyntax()) {
|
||||
return 'namespace' . ($name ? " $name" : '') . "\n{\n"
|
||||
. $this->indent($body)
|
||||
. "}\n";
|
||||
|
||||
} else {
|
||||
return ($name ? "namespace $name;\n\n" : '')
|
||||
. $body;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function printFile(PhpFile $file): string
|
||||
{
|
||||
$namespaces = [];
|
||||
foreach ($file->getNamespaces() as $namespace) {
|
||||
$namespaces[] = $this->printNamespace($namespace);
|
||||
}
|
||||
|
||||
return Strings::normalize(
|
||||
"<?php\n"
|
||||
. ($file->getComment() ? "\n" . Helpers::formatDocComment($file->getComment() . "\n") : '')
|
||||
. "\n"
|
||||
. ($file->hasStrictTypes() ? "declare(strict_types=1);\n\n" : '')
|
||||
. implode("\n\n", $namespaces)
|
||||
) . "\n";
|
||||
}
|
||||
|
||||
|
||||
protected function printUses(PhpNamespace $namespace, string $of = PhpNamespace::NameNormal): string
|
||||
{
|
||||
$prefix = [
|
||||
PhpNamespace::NameNormal => '',
|
||||
PhpNamespace::NameFunction => 'function ',
|
||||
PhpNamespace::NameConstant => 'const ',
|
||||
][$of];
|
||||
$name = $namespace->getName();
|
||||
$uses = [];
|
||||
foreach ($namespace->getUses($of) as $alias => $original) {
|
||||
$uses[] = Helpers::extractShortName($original) === $alias
|
||||
? "use $prefix$original;\n"
|
||||
: "use $prefix$original as $alias;\n";
|
||||
}
|
||||
|
||||
return implode('', $uses);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Closure|GlobalFunction|Method $function
|
||||
*/
|
||||
protected function printParameters($function, int $column = 0): string
|
||||
{
|
||||
$params = [];
|
||||
$list = $function->getParameters();
|
||||
$special = false;
|
||||
|
||||
foreach ($list as $param) {
|
||||
$param->validate();
|
||||
$variadic = $function->isVariadic() && $param === end($list);
|
||||
$type = $param->getType();
|
||||
$promoted = $param instanceof PromotedParameter ? $param : null;
|
||||
$params[] =
|
||||
($promoted ? Helpers::formatDocComment((string) $promoted->getComment()) : '')
|
||||
. ($attrs = $this->printAttributes($param->getAttributes(), true))
|
||||
. ($promoted ?
|
||||
($promoted->getVisibility() ?: 'public')
|
||||
. ($promoted->isReadOnly() && $type ? ' readonly' : '')
|
||||
. ' ' : '')
|
||||
. ltrim($this->printType($type, $param->isNullable()) . ' ')
|
||||
. ($param->isReference() ? '&' : '')
|
||||
. ($variadic ? '...' : '')
|
||||
. '$' . $param->getName()
|
||||
. ($param->hasDefaultValue() && !$variadic ? ' = ' . $this->dump($param->getDefaultValue()) : '');
|
||||
|
||||
$special = $special || $promoted || $attrs;
|
||||
}
|
||||
|
||||
$line = implode(', ', $params);
|
||||
|
||||
return count($params) > 1 && ($special || strlen($line) + $column > $this->wrapLength)
|
||||
? "(\n" . $this->indent(implode(",\n", $params)) . ($special ? ',' : '') . "\n)"
|
||||
: "($line)";
|
||||
}
|
||||
|
||||
|
||||
protected function printType(?string $type, bool $nullable): string
|
||||
{
|
||||
if ($type === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($this->namespace) {
|
||||
$type = $this->namespace->simplifyType($type);
|
||||
}
|
||||
|
||||
if ($nullable && strcasecmp($type, 'mixed')) {
|
||||
$type = strpos($type, '|') === false
|
||||
? '?' . $type
|
||||
: $type . '|null';
|
||||
}
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Closure|GlobalFunction|Method $function
|
||||
*/
|
||||
private function printReturnType($function): string
|
||||
{
|
||||
return ($tmp = $this->printType($function->getReturnType(), $function->isReturnNullable()))
|
||||
? $this->returnTypeColon . $tmp
|
||||
: '';
|
||||
}
|
||||
|
||||
|
||||
private function printAttributes(array $attrs, bool $inline = false): string
|
||||
{
|
||||
if (!$attrs) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$this->dumper->indentation = $this->indentation;
|
||||
$items = [];
|
||||
foreach ($attrs as $attr) {
|
||||
$args = $this->dumper->format('...?:', $attr->getArguments());
|
||||
$args = Helpers::simplifyTaggedNames($args, $this->namespace);
|
||||
$items[] = $this->printType($attr->getName(), false) . ($args ? "($args)" : '');
|
||||
}
|
||||
|
||||
return $inline
|
||||
? '#[' . implode(', ', $items) . '] '
|
||||
: '#[' . implode("]\n#[", $items) . "]\n";
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setTypeResolving(bool $state = true): self
|
||||
{
|
||||
$this->resolveTypes = $state;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
protected function indent(string $s): string
|
||||
{
|
||||
$s = str_replace("\t", $this->indentation, $s);
|
||||
return Strings::indent($s, 1, $this->indentation);
|
||||
}
|
||||
|
||||
|
||||
protected function dump($var, int $column = 0): string
|
||||
{
|
||||
$this->dumper->indentation = $this->indentation;
|
||||
$this->dumper->wrapLength = $this->wrapLength;
|
||||
$s = $this->dumper->dump($var, $column);
|
||||
$s = Helpers::simplifyTaggedNames($s, $this->namespace);
|
||||
return $s;
|
||||
}
|
||||
|
||||
|
||||
private function joinProperties(array $props): string
|
||||
{
|
||||
return $this->linesBetweenProperties
|
||||
? implode(str_repeat("\n", $this->linesBetweenProperties), $props)
|
||||
: preg_replace('#^(\w.*\n)\n(?=\w.*;)#m', '$1', implode("\n", $props));
|
||||
}
|
||||
}
|
||||
48
vendor/nette/php-generator/src/PhpGenerator/PromotedParameter.php
vendored
Normal file
48
vendor/nette/php-generator/src/PhpGenerator/PromotedParameter.php
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator;
|
||||
|
||||
use Nette;
|
||||
|
||||
|
||||
/**
|
||||
* Promoted parameter in constructor.
|
||||
*/
|
||||
final class PromotedParameter extends Parameter
|
||||
{
|
||||
use Traits\VisibilityAware;
|
||||
use Traits\CommentAware;
|
||||
|
||||
/** @var bool */
|
||||
private $readOnly = false;
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setReadOnly(bool $state = true): self
|
||||
{
|
||||
$this->readOnly = $state;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function isReadOnly(): bool
|
||||
{
|
||||
return $this->readOnly;
|
||||
}
|
||||
|
||||
|
||||
/** @throws Nette\InvalidStateException */
|
||||
public function validate(): void
|
||||
{
|
||||
if ($this->readOnly && !$this->getType()) {
|
||||
throw new Nette\InvalidStateException("Property \${$this->getName()}: Read-only properties are only supported on typed property.");
|
||||
}
|
||||
}
|
||||
}
|
||||
145
vendor/nette/php-generator/src/PhpGenerator/Property.php
vendored
Normal file
145
vendor/nette/php-generator/src/PhpGenerator/Property.php
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator;
|
||||
|
||||
use Nette;
|
||||
use Nette\Utils\Type;
|
||||
|
||||
|
||||
/**
|
||||
* Class property description.
|
||||
*
|
||||
* @property mixed $value
|
||||
*/
|
||||
final class Property
|
||||
{
|
||||
use Nette\SmartObject;
|
||||
use Traits\NameAware;
|
||||
use Traits\VisibilityAware;
|
||||
use Traits\CommentAware;
|
||||
use Traits\AttributeAware;
|
||||
|
||||
/** @var mixed */
|
||||
private $value;
|
||||
|
||||
/** @var bool */
|
||||
private $static = false;
|
||||
|
||||
/** @var string|null */
|
||||
private $type;
|
||||
|
||||
/** @var bool */
|
||||
private $nullable = false;
|
||||
|
||||
/** @var bool */
|
||||
private $initialized = false;
|
||||
|
||||
/** @var bool */
|
||||
private $readOnly = false;
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setValue($val): self
|
||||
{
|
||||
$this->value = $val;
|
||||
$this->initialized = true;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function &getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setStatic(bool $state = true): self
|
||||
{
|
||||
$this->static = $state;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function isStatic(): bool
|
||||
{
|
||||
return $this->static;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setType(?string $type): self
|
||||
{
|
||||
$this->type = Helpers::validateType($type, $this->nullable);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Type|string|null
|
||||
*/
|
||||
public function getType(bool $asObject = false)
|
||||
{
|
||||
return $asObject && $this->type
|
||||
? Type::fromString($this->type)
|
||||
: $this->type;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setNullable(bool $state = true): self
|
||||
{
|
||||
$this->nullable = $state;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function isNullable(): bool
|
||||
{
|
||||
return $this->nullable;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setInitialized(bool $state = true): self
|
||||
{
|
||||
$this->initialized = $state;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function isInitialized(): bool
|
||||
{
|
||||
return $this->initialized || $this->value !== null;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setReadOnly(bool $state = true): self
|
||||
{
|
||||
$this->readOnly = $state;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function isReadOnly(): bool
|
||||
{
|
||||
return $this->readOnly;
|
||||
}
|
||||
|
||||
|
||||
/** @throws Nette\InvalidStateException */
|
||||
public function validate(): void
|
||||
{
|
||||
if ($this->readOnly && !$this->type) {
|
||||
throw new Nette\InvalidStateException("Property \$$this->name: Read-only properties are only supported on typed property.");
|
||||
}
|
||||
}
|
||||
}
|
||||
23
vendor/nette/php-generator/src/PhpGenerator/PsrPrinter.php
vendored
Normal file
23
vendor/nette/php-generator/src/PhpGenerator/PsrPrinter.php
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator;
|
||||
|
||||
|
||||
/**
|
||||
* Generates PHP code compatible with PSR-2 and PSR-12.
|
||||
*/
|
||||
final class PsrPrinter extends Printer
|
||||
{
|
||||
/** @var string */
|
||||
protected $indentation = ' ';
|
||||
|
||||
/** @var int */
|
||||
protected $linesBetweenMethods = 1;
|
||||
}
|
||||
49
vendor/nette/php-generator/src/PhpGenerator/TraitUse.php
vendored
Normal file
49
vendor/nette/php-generator/src/PhpGenerator/TraitUse.php
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator;
|
||||
|
||||
use Nette;
|
||||
|
||||
|
||||
/**
|
||||
* use Trait
|
||||
*/
|
||||
final class TraitUse
|
||||
{
|
||||
use Nette\SmartObject;
|
||||
use Traits\NameAware;
|
||||
use Traits\CommentAware;
|
||||
|
||||
/** @var array */
|
||||
private $resolutions = [];
|
||||
|
||||
|
||||
public function __construct(string $name)
|
||||
{
|
||||
if (!Nette\PhpGenerator\Helpers::isNamespaceIdentifier($name, true)) {
|
||||
throw new Nette\InvalidArgumentException("Value '$name' is not valid trait name.");
|
||||
}
|
||||
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
|
||||
public function addResolution(string $resolution): self
|
||||
{
|
||||
$this->resolutions[] = $resolution;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function getResolutions(): array
|
||||
{
|
||||
return $this->resolutions;
|
||||
}
|
||||
}
|
||||
49
vendor/nette/php-generator/src/PhpGenerator/Traits/AttributeAware.php
vendored
Normal file
49
vendor/nette/php-generator/src/PhpGenerator/Traits/AttributeAware.php
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator\Traits;
|
||||
|
||||
use Nette\PhpGenerator\Attribute;
|
||||
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
trait AttributeAware
|
||||
{
|
||||
/** @var Attribute[] */
|
||||
private $attributes = [];
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function addAttribute(string $name, array $args = []): self
|
||||
{
|
||||
$this->attributes[] = new Attribute($name, $args);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Attribute[] $attrs
|
||||
* @return static
|
||||
*/
|
||||
public function setAttributes(array $attrs): self
|
||||
{
|
||||
(function (Attribute ...$attrs) {})(...$attrs);
|
||||
$this->attributes = $attrs;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/** @return Attribute[] */
|
||||
public function getAttributes(): array
|
||||
{
|
||||
return $this->attributes;
|
||||
}
|
||||
}
|
||||
42
vendor/nette/php-generator/src/PhpGenerator/Traits/CommentAware.php
vendored
Normal file
42
vendor/nette/php-generator/src/PhpGenerator/Traits/CommentAware.php
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator\Traits;
|
||||
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
trait CommentAware
|
||||
{
|
||||
/** @var string|null */
|
||||
private $comment;
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setComment(?string $val): self
|
||||
{
|
||||
$this->comment = $val;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function getComment(): ?string
|
||||
{
|
||||
return $this->comment;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function addComment(string $val): self
|
||||
{
|
||||
$this->comment .= $this->comment ? "\n$val" : $val;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
188
vendor/nette/php-generator/src/PhpGenerator/Traits/FunctionLike.php
vendored
Normal file
188
vendor/nette/php-generator/src/PhpGenerator/Traits/FunctionLike.php
vendored
Normal file
@@ -0,0 +1,188 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator\Traits;
|
||||
|
||||
use Nette;
|
||||
use Nette\PhpGenerator\Dumper;
|
||||
use Nette\PhpGenerator\Parameter;
|
||||
use Nette\Utils\Type;
|
||||
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
trait FunctionLike
|
||||
{
|
||||
/** @var string */
|
||||
private $body = '';
|
||||
|
||||
/** @var Parameter[] */
|
||||
private $parameters = [];
|
||||
|
||||
/** @var bool */
|
||||
private $variadic = false;
|
||||
|
||||
/** @var string|null */
|
||||
private $returnType;
|
||||
|
||||
/** @var bool */
|
||||
private $returnReference = false;
|
||||
|
||||
/** @var bool */
|
||||
private $returnNullable = false;
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setBody(string $code, ?array $args = null): self
|
||||
{
|
||||
$this->body = $args === null
|
||||
? $code
|
||||
: (new Dumper)->format($code, ...$args);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function getBody(): string
|
||||
{
|
||||
return $this->body;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function addBody(string $code, ?array $args = null): self
|
||||
{
|
||||
$this->body .= ($args === null ? $code : (new Dumper)->format($code, ...$args)) . "\n";
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Parameter[] $val
|
||||
* @return static
|
||||
*/
|
||||
public function setParameters(array $val): self
|
||||
{
|
||||
(function (Parameter ...$val) {})(...array_values($val));
|
||||
$this->parameters = [];
|
||||
foreach ($val as $v) {
|
||||
$this->parameters[$v->getName()] = $v;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/** @return Parameter[] */
|
||||
public function getParameters(): array
|
||||
{
|
||||
return $this->parameters;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $name without $
|
||||
*/
|
||||
public function addParameter(string $name, $defaultValue = null): Parameter
|
||||
{
|
||||
$param = new Parameter($name);
|
||||
if (func_num_args() > 1) {
|
||||
$param->setDefaultValue($defaultValue);
|
||||
}
|
||||
|
||||
return $this->parameters[$name] = $param;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $name without $
|
||||
* @return static
|
||||
*/
|
||||
public function removeParameter(string $name): self
|
||||
{
|
||||
unset($this->parameters[$name]);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setVariadic(bool $state = true): self
|
||||
{
|
||||
$this->variadic = $state;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function isVariadic(): bool
|
||||
{
|
||||
return $this->variadic;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setReturnType(?string $type): self
|
||||
{
|
||||
$this->returnType = Nette\PhpGenerator\Helpers::validateType($type, $this->returnNullable);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Type|string|null
|
||||
*/
|
||||
public function getReturnType(bool $asObject = false)
|
||||
{
|
||||
return $asObject && $this->returnType
|
||||
? Type::fromString($this->returnType)
|
||||
: $this->returnType;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setReturnReference(bool $state = true): self
|
||||
{
|
||||
$this->returnReference = $state;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function getReturnReference(): bool
|
||||
{
|
||||
return $this->returnReference;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setReturnNullable(bool $state = true): self
|
||||
{
|
||||
$this->returnNullable = $state;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function isReturnNullable(): bool
|
||||
{
|
||||
return $this->returnNullable;
|
||||
}
|
||||
|
||||
|
||||
/** @deprecated use isReturnNullable() */
|
||||
public function getReturnNullable(): bool
|
||||
{
|
||||
return $this->returnNullable;
|
||||
}
|
||||
|
||||
|
||||
/** @deprecated */
|
||||
public function setNamespace(?Nette\PhpGenerator\PhpNamespace $val = null): self
|
||||
{
|
||||
trigger_error(__METHOD__ . '() is deprecated', E_USER_DEPRECATED);
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
50
vendor/nette/php-generator/src/PhpGenerator/Traits/NameAware.php
vendored
Normal file
50
vendor/nette/php-generator/src/PhpGenerator/Traits/NameAware.php
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator\Traits;
|
||||
|
||||
use Nette;
|
||||
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
trait NameAware
|
||||
{
|
||||
/** @var string */
|
||||
private $name;
|
||||
|
||||
|
||||
public function __construct(string $name)
|
||||
{
|
||||
if (!Nette\PhpGenerator\Helpers::isIdentifier($name)) {
|
||||
throw new Nette\InvalidArgumentException("Value '$name' is not valid name.");
|
||||
}
|
||||
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns clone with a different name.
|
||||
* @return static
|
||||
*/
|
||||
public function cloneWithName(string $name): self
|
||||
{
|
||||
$dolly = clone $this;
|
||||
$dolly->__construct($name);
|
||||
return $dolly;
|
||||
}
|
||||
}
|
||||
86
vendor/nette/php-generator/src/PhpGenerator/Traits/VisibilityAware.php
vendored
Normal file
86
vendor/nette/php-generator/src/PhpGenerator/Traits/VisibilityAware.php
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator\Traits;
|
||||
|
||||
use Nette;
|
||||
use Nette\PhpGenerator\ClassType;
|
||||
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
trait VisibilityAware
|
||||
{
|
||||
/** @var string|null public|protected|private */
|
||||
private $visibility;
|
||||
|
||||
|
||||
/**
|
||||
* @param string|null $val public|protected|private
|
||||
* @return static
|
||||
*/
|
||||
public function setVisibility(?string $val): self
|
||||
{
|
||||
if (!in_array($val, [ClassType::VisibilityPublic, ClassType::VisibilityProtected, ClassType::VisibilityPrivate, null], true)) {
|
||||
throw new Nette\InvalidArgumentException('Argument must be public|protected|private.');
|
||||
}
|
||||
|
||||
$this->visibility = $val;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function getVisibility(): ?string
|
||||
{
|
||||
return $this->visibility;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setPublic(): self
|
||||
{
|
||||
$this->visibility = ClassType::VisibilityPublic;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function isPublic(): bool
|
||||
{
|
||||
return $this->visibility === ClassType::VisibilityPublic || $this->visibility === null;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setProtected(): self
|
||||
{
|
||||
$this->visibility = ClassType::VisibilityProtected;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function isProtected(): bool
|
||||
{
|
||||
return $this->visibility === ClassType::VisibilityProtected;
|
||||
}
|
||||
|
||||
|
||||
/** @return static */
|
||||
public function setPrivate(): self
|
||||
{
|
||||
$this->visibility = ClassType::VisibilityPrivate;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function isPrivate(): bool
|
||||
{
|
||||
return $this->visibility === ClassType::VisibilityPrivate;
|
||||
}
|
||||
}
|
||||
92
vendor/nette/php-generator/src/PhpGenerator/Type.php
vendored
Normal file
92
vendor/nette/php-generator/src/PhpGenerator/Type.php
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Nette\PhpGenerator;
|
||||
|
||||
|
||||
/**
|
||||
* PHP return, property and parameter types.
|
||||
*/
|
||||
class Type
|
||||
{
|
||||
public const
|
||||
String = 'string',
|
||||
Int = 'int',
|
||||
Float = 'float',
|
||||
Bool = 'bool',
|
||||
Array = 'array',
|
||||
Object = 'object',
|
||||
Callable = 'callable',
|
||||
Iterable = 'iterable',
|
||||
Void = 'void',
|
||||
Never = 'never',
|
||||
Mixed = 'mixed',
|
||||
False = 'false',
|
||||
Null = 'null',
|
||||
Self = 'self',
|
||||
Parent = 'parent',
|
||||
Static = 'static';
|
||||
|
||||
/** @deprecated */
|
||||
public const
|
||||
STRING = self::String,
|
||||
INT = self::Int,
|
||||
FLOAT = self::Float,
|
||||
BOOL = self::Bool,
|
||||
ARRAY = self::Array,
|
||||
OBJECT = self::Object,
|
||||
CALLABLE = self::Callable,
|
||||
ITERABLE = self::Iterable,
|
||||
VOID = self::Void,
|
||||
NEVER = self::Never,
|
||||
MIXED = self::Mixed,
|
||||
FALSE = self::False,
|
||||
NULL = self::Null,
|
||||
SELF = self::Self,
|
||||
PARENT = self::Parent,
|
||||
STATIC = self::Static;
|
||||
|
||||
|
||||
public static function nullable(string $type, bool $state = true): string
|
||||
{
|
||||
return ($state ? '?' : '') . ltrim($type, '?');
|
||||
}
|
||||
|
||||
|
||||
public static function union(string ...$types): string
|
||||
{
|
||||
return implode('|', $types);
|
||||
}
|
||||
|
||||
|
||||
public static function intersection(string ...$types): string
|
||||
{
|
||||
return implode('&', $types);
|
||||
}
|
||||
|
||||
|
||||
public static function getType($value): ?string
|
||||
{
|
||||
if (is_object($value)) {
|
||||
return get_class($value);
|
||||
} elseif (is_int($value)) {
|
||||
return self::INT;
|
||||
} elseif (is_float($value)) {
|
||||
return self::FLOAT;
|
||||
} elseif (is_string($value)) {
|
||||
return self::STRING;
|
||||
} elseif (is_bool($value)) {
|
||||
return self::BOOL;
|
||||
} elseif (is_array($value)) {
|
||||
return self::ARRAY;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user