- Replace direct string concatenation with formatCppLineComment method - Add proper line wrapping for multi-line comments in generated code - Apply consistent comment formatting across function calls, expressions and method calls - Introduce formatCppLineComment helper to handle comment formatting logic - Update all comment generation points to use the new standardized approach - Add test cases for ThinkPHP cookie, environment and service patterns - Add test case for trait method return by reference functionalitypull/16/head
parent
be5e553bf7
commit
441091fbc5
5 changed files with 415 additions and 7 deletions
@ -0,0 +1,39 @@ |
||||
--TEST-- |
||||
Return value by trait (method) |
||||
--FILE-- |
||||
<?php |
||||
Trait T1 |
||||
{ |
||||
public function &getRefValue() |
||||
{ |
||||
return $this->value; |
||||
} |
||||
} |
||||
|
||||
class Test |
||||
{ |
||||
use T1; |
||||
|
||||
private $value = 1; |
||||
|
||||
public function getValue() |
||||
{ |
||||
return $this->value; |
||||
} |
||||
} |
||||
|
||||
function main() |
||||
{ |
||||
$test = new Test; |
||||
var_dump($test->getValue()); |
||||
var_dump($refValue = &$test->getRefValue()); |
||||
$refValue = 2; |
||||
var_dump($test->getValue()); |
||||
var_dump($test->getRefValue()); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
int(1) |
||||
int(1) |
||||
int(2) |
||||
int(2) |
||||
@ -0,0 +1,66 @@ |
||||
--TEST-- |
||||
ThinkPHP App pattern: array_filter with dynamic instanceof service lookup |
||||
--FILE-- |
||||
<?php |
||||
|
||||
class ThinkServiceBase |
||||
{ |
||||
} |
||||
|
||||
class ThinkLoggerService extends ThinkServiceBase |
||||
{ |
||||
} |
||||
|
||||
class ThinkCacheService extends ThinkServiceBase |
||||
{ |
||||
} |
||||
|
||||
class ThinkAppServiceLike |
||||
{ |
||||
private array $services = []; |
||||
|
||||
public function register(object $service): void |
||||
{ |
||||
$this->services[] = $service; |
||||
} |
||||
|
||||
public function getService(object|string $service): ?object |
||||
{ |
||||
$name = is_string($service) ? $service : $service::class; |
||||
return array_values(array_filter($this->services, function ($value) use ($name) { |
||||
return $value instanceof $name; |
||||
}, ARRAY_FILTER_USE_BOTH))[0] ?? null; |
||||
} |
||||
|
||||
public function boot(): array |
||||
{ |
||||
$booted = []; |
||||
array_walk($this->services, function ($service) use (&$booted) { |
||||
$booted[] = $service::class; |
||||
}); |
||||
return $booted; |
||||
} |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
$app = new ThinkAppServiceLike(); |
||||
$app->register(new ThinkLoggerService()); |
||||
$app->register(new ThinkCacheService()); |
||||
|
||||
var_dump($app->getService(ThinkCacheService::class)::class); |
||||
var_dump($app->getService(new ThinkLoggerService())::class); |
||||
var_dump($app->getService(DateTimeImmutable::class)); |
||||
var_dump($app->boot()); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
string(17) "ThinkCacheService" |
||||
string(18) "ThinkLoggerService" |
||||
NULL |
||||
array(2) { |
||||
[0]=> |
||||
string(18) "ThinkLoggerService" |
||||
[1]=> |
||||
string(17) "ThinkCacheService" |
||||
} |
||||
@ -0,0 +1,147 @@ |
||||
--TEST-- |
||||
ThinkPHP Cookie pattern: option normalization, destructuring and trailing call args |
||||
--FILE-- |
||||
<?php |
||||
|
||||
class ThinkCookieRequestLike |
||||
{ |
||||
public array $cookie = []; |
||||
|
||||
public function setCookie(string $name, mixed $value): void |
||||
{ |
||||
$this->cookie[$name] = $value; |
||||
} |
||||
} |
||||
|
||||
class ThinkCookieLike |
||||
{ |
||||
private array $config = [ |
||||
'expire' => 0, |
||||
'path' => '/', |
||||
'domain' => '', |
||||
'secure' => false, |
||||
'httponly' => false, |
||||
'samesite' => '', |
||||
]; |
||||
private array $cookie = []; |
||||
public array $saved = []; |
||||
|
||||
public function __construct(private ThinkCookieRequestLike $request, array $config = []) |
||||
{ |
||||
$this->config = array_merge($this->config, array_change_key_case($config)); |
||||
} |
||||
|
||||
public function set(string $name, string $value, mixed $option = null): void |
||||
{ |
||||
if ($option !== null) { |
||||
if (is_numeric($option) || $option instanceof DateTimeInterface) { |
||||
$option = ['expire' => $option]; |
||||
} |
||||
$config = array_merge($this->config, array_change_key_case($option)); |
||||
} else { |
||||
$config = $this->config; |
||||
} |
||||
|
||||
if ($config['expire'] instanceof DateTimeInterface) { |
||||
$expire = $config['expire']->getTimestamp(); |
||||
} else { |
||||
$expire = !empty($config['expire']) ? 1000 + intval($config['expire']) : 0; |
||||
} |
||||
|
||||
$this->setCookie($name, $value, $expire, $config); |
||||
$this->request->setCookie($name, $value); |
||||
} |
||||
|
||||
public function forever(string $name, string $value = '', mixed $option = null): void |
||||
{ |
||||
if (is_null($option) || is_numeric($option)) { |
||||
$option = []; |
||||
} |
||||
|
||||
$option['expire'] = 315360000; |
||||
$this->set($name, $value, $option); |
||||
} |
||||
|
||||
private function setCookie(string $name, string $value, int $expire, array $option = []): void |
||||
{ |
||||
$this->cookie[$name] = [$value, $expire, $option]; |
||||
} |
||||
|
||||
public function save(): void |
||||
{ |
||||
foreach ($this->cookie as $name => $val) { |
||||
[$value, $expire, $option] = $val; |
||||
$this->saveCookie( |
||||
(string) $name, |
||||
$value, |
||||
$expire, |
||||
$option['path'], |
||||
$option['domain'], |
||||
(bool) $option['secure'], |
||||
(bool) $option['httponly'], |
||||
$option['samesite'], |
||||
); |
||||
} |
||||
} |
||||
|
||||
private function saveCookie(string $name, string $value, int $expire, string $path, string $domain, bool $secure, bool $httponly, string $samesite): void |
||||
{ |
||||
$this->saved[$name] = compact('value', 'expire', 'path', 'domain', 'secure', 'httponly', 'samesite'); |
||||
} |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
$request = new ThinkCookieRequestLike(); |
||||
$cookie = new ThinkCookieLike($request, ['SameSite' => 'lax', 'Secure' => true]); |
||||
$cookie->set('token', 'abc', new DateTimeImmutable('@42')); |
||||
$cookie->forever('remember', 'yes', ['HttpOnly' => true]); |
||||
$cookie->save(); |
||||
|
||||
var_dump($request->cookie); |
||||
var_dump($cookie->saved); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
array(2) { |
||||
["token"]=> |
||||
string(3) "abc" |
||||
["remember"]=> |
||||
string(3) "yes" |
||||
} |
||||
array(2) { |
||||
["token"]=> |
||||
array(7) { |
||||
["value"]=> |
||||
string(3) "abc" |
||||
["expire"]=> |
||||
int(42) |
||||
["path"]=> |
||||
string(1) "/" |
||||
["domain"]=> |
||||
string(0) "" |
||||
["secure"]=> |
||||
bool(true) |
||||
["httponly"]=> |
||||
bool(false) |
||||
["samesite"]=> |
||||
string(3) "lax" |
||||
} |
||||
["remember"]=> |
||||
array(7) { |
||||
["value"]=> |
||||
string(3) "yes" |
||||
["expire"]=> |
||||
int(315361000) |
||||
["path"]=> |
||||
string(1) "/" |
||||
["domain"]=> |
||||
string(0) "" |
||||
["secure"]=> |
||||
bool(true) |
||||
["httponly"]=> |
||||
bool(true) |
||||
["samesite"]=> |
||||
string(3) "lax" |
||||
} |
||||
} |
||||
@ -0,0 +1,136 @@ |
||||
--TEST-- |
||||
ThinkPHP Env pattern: ArrayAccess, magic accessors and nested env flattening |
||||
--FILE-- |
||||
<?php |
||||
|
||||
class ThinkEnvLike implements ArrayAccess |
||||
{ |
||||
private array $data = []; |
||||
private array $convert = [ |
||||
'true' => true, |
||||
'false' => false, |
||||
'off' => false, |
||||
'on' => true, |
||||
]; |
||||
|
||||
public function get(?string $name = null, mixed $default = null): mixed |
||||
{ |
||||
if ($name === null) { |
||||
return $this->data; |
||||
} |
||||
|
||||
$name = strtoupper(str_replace('.', '_', $name)); |
||||
if (isset($this->data[$name])) { |
||||
$result = $this->data[$name]; |
||||
if (is_string($result) && isset($this->convert[$result])) { |
||||
return $this->convert[$result]; |
||||
} |
||||
return $result; |
||||
} |
||||
|
||||
return $default; |
||||
} |
||||
|
||||
public function set(mixed $env, mixed $value = null): void |
||||
{ |
||||
if (is_array($env)) { |
||||
$env = array_change_key_case($env, CASE_UPPER); |
||||
foreach ($env as $key => $val) { |
||||
if (is_array($val)) { |
||||
foreach ($val as $k => $v) { |
||||
if (is_string($k)) { |
||||
$this->data[$key . '_' . strtoupper($k)] = $v; |
||||
} else { |
||||
$this->data[$key][$k] = $v; |
||||
} |
||||
} |
||||
} else { |
||||
$this->data[$key] = $val; |
||||
} |
||||
} |
||||
} else { |
||||
$name = strtoupper(str_replace('.', '_', $env)); |
||||
$this->data[$name] = $value; |
||||
} |
||||
} |
||||
|
||||
public function has(string $name): bool |
||||
{ |
||||
return !is_null($this->get($name)); |
||||
} |
||||
|
||||
public function __set(string $name, mixed $value): void |
||||
{ |
||||
$this->set($name, $value); |
||||
} |
||||
|
||||
public function __get(string $name): mixed |
||||
{ |
||||
return $this->get($name); |
||||
} |
||||
|
||||
public function __isset(string $name): bool |
||||
{ |
||||
return $this->has($name); |
||||
} |
||||
|
||||
public function offsetSet(mixed $name, mixed $value): void |
||||
{ |
||||
$this->set($name, $value); |
||||
} |
||||
|
||||
public function offsetExists(mixed $name): bool |
||||
{ |
||||
return $this->__isset($name); |
||||
} |
||||
|
||||
public function offsetUnset(mixed $name): void |
||||
{ |
||||
throw new Exception('not support: unset'); |
||||
} |
||||
|
||||
public function offsetGet(mixed $name): mixed |
||||
{ |
||||
return $this->get($name); |
||||
} |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
$env = new ThinkEnvLike(); |
||||
$env->set([ |
||||
'app' => ['debug' => 'true', 'hosts' => ['a', 'b']], |
||||
'feature' => 'off', |
||||
]); |
||||
$env['database.host'] = 'localhost'; |
||||
$env->cache_enabled = 'on'; |
||||
|
||||
var_dump($env->get('app.debug')); |
||||
var_dump($env['feature']); |
||||
var_dump($env->database_host); |
||||
var_dump(isset($env->cache_enabled)); |
||||
var_dump($env->get()); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
bool(true) |
||||
bool(false) |
||||
string(9) "localhost" |
||||
bool(true) |
||||
array(5) { |
||||
["APP_DEBUG"]=> |
||||
string(4) "true" |
||||
["APP_HOSTS"]=> |
||||
array(2) { |
||||
[0]=> |
||||
string(1) "a" |
||||
[1]=> |
||||
string(1) "b" |
||||
} |
||||
["FEATURE"]=> |
||||
string(3) "off" |
||||
["DATABASE_HOST"]=> |
||||
string(9) "localhost" |
||||
["CACHE_ENABLED"]=> |
||||
string(2) "on" |
||||
} |
||||
Loading…
Reference in new issue