Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
aea652b
Pass the inverse flag to the base Laravel MorphToMany constructor
LukeTowers Jul 19, 2022
bcbafd8
[1.2] Sortable Relation trait (#94)
bennothommo Jul 27, 2022
49514ac
regenerate the resizer fixtures (#100)
mjauvin Jul 27, 2022
71d6e70
Use extension if provided in resizer options (#99)
mjauvin Jul 27, 2022
87009af
Switch to external config writer library (#102)
bennothommo Aug 1, 2022
4ef95b4
Update config writer files with correct namespace
bennothommo Aug 1, 2022
444c099
Remove Input::all() override.
bennothommo Aug 4, 2022
411695b
Allow for ** wildcard to trust all proxies in a chain of proxies
LukeTowers Aug 4, 2022
d98af36
Add relatedModel to dissociate events (#101)
mjauvin Aug 10, 2022
a2253ef
Automatically purge dynamic properties added to models
LukeTowers Aug 10, 2022
7e57a08
Deprecate Purgeable model behavior and include Purgeable trait in the…
LukeTowers Aug 10, 2022
6ce6951
Improve reliability of extension detection logic in File->fromUrl()
LukeTowers Aug 13, 2022
c603360
Reorder Str helper methods alphabetically
LukeTowers Aug 13, 2022
3067d7d
Adds Str::join() helper
LukeTowers Aug 13, 2022
35b3bbb
Add test for new Str::join() helper
LukeTowers Aug 13, 2022
f6be9c5
Re-do image resizer tests
bennothommo Aug 15, 2022
69b2647
Respect session config when setting the auth manager cookie
LukeTowers Aug 16, 2022
c64d9ca
Improve accuracy of docblock message
LukeTowers Aug 22, 2022
c15ec51
Support creating File model from file on disk (#106)
jaxwilko Aug 22, 2022
583b7e1
Allow the file_name & content_type to be set when using FileModel->fr…
LukeTowers Aug 25, 2022
a25db10
Add SVG utility (#61)
bennothommo Aug 26, 2022
66c4800
Added support for including anon classes multiple times per execution…
jaxwilko Sep 1, 2022
87470d7
Fix Updater->resolve()
LukeTowers Sep 2, 2022
39656d3
Add Winter\Storm\Console\Traits\HandlesCleanup trait
LukeTowers Sep 4, 2022
3500516
Add missing implementation for HandlesCleanup CLI trait to function o…
LukeTowers Sep 4, 2022
993562d
Use modern constant for clarity
LukeTowers Sep 4, 2022
6112214
add dummy fireEvent() method
mjauvin Sep 7, 2022
8dab2d7
Revert "add dummy fireEvent() method"
mjauvin Sep 7, 2022
09005bc
Update testing of trusted proxies
bennothommo Sep 12, 2022
a5e1980
Fix 'ClassName@method' Event handler format. (#116)
mjauvin Sep 21, 2022
5c46aa3
Added Str::unique() & Arr::moveKeyToIndex() helpers (#114)
jaxwilko Sep 21, 2022
16f44dc
Added fix to allow pivots to use custom pivot models on attach (#120)
jaxwilko Sep 27, 2022
9dea960
Fix support for queueing emails (#117)
damsfx Sep 28, 2022
623845f
Improve slug generation performance (#118)
RomainMazB Sep 28, 2022
a39671f
Fix hidden file glob on systems without GLOB_BRACE support (#121)
bennothommo Sep 29, 2022
01a214f
Readability improvement for Sluggable trait (#119)
RomainMazB Sep 29, 2022
e6e3c5b
Fix BC break in event args for belongsToMany model.relation.afterAttach
LukeTowers Sep 29, 2022
e67da1a
Don't attempt to store array source DBs if storage is disabled
bennothommo Oct 4, 2022
57c7669
Merge eventArgs using spread operator instead of array union `+` oper…
ericp-mrel Oct 5, 2022
d712423
Support source root level paths in Halcyon datasources (#123)
jaxwilko Oct 9, 2022
6cc669a
Fixed bug when dynamically adding hasMany* relations (#124)
jaxwilko Oct 13, 2022
302593d
Reverse order in checking mail config styles (#107)
bennothommo Oct 17, 2022
6d2d552
Patch alert method to keep compatibility with Laravel (#125)
jaxwilko Oct 18, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,11 @@ jobs:

- name: Run tests
run: ./vendor/bin/phpunit ./tests

- name: Upload test artifacts on failure
uses: actions/upload-artifact@v3
if: ${{ failure() }}
with:
name: ResizerTest-${{ matrix.operatingSystem }}-PHP${{ matrix.phpVersion }}
path: tests/artifacts/ResizerTest/
if-no-files-found: error
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ php_errors.log
tests/.phpunit.result.cache
.phpunit.result.cache
tests/tmp
tests/artifacts/*
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

"assetic/framework": "~3.0",
"doctrine/dbal": "^2.6",
"enshrined/svg-sanitize": "^0.15",
"erusev/parsedown-extra": "~0.7",
"laravel/framework": "^9.1",
"laravel/tinker": "^2.7",
Expand All @@ -47,7 +48,8 @@
"symfony/yaml": "^6.0",
"twig/twig": "~3.0",
"wikimedia/less.php": "~3.0",
"wikimedia/minify": "~2.2"
"wikimedia/minify": "~2.2",
"winter/laravel-config-writer": "^1.0.1"
},
"require-dev": {
"phpunit/phpunit": "^9.5.8",
Expand Down
5 changes: 0 additions & 5 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -260,11 +260,6 @@ parameters:
count: 1
path: src/Database/Relations/BelongsTo.php

-
message: "#^Call to an undefined method Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:getRelationDefinition\\(\\)\\.$#"
count: 3
path: src/Database/Relations/BelongsTo.php

-
message: "#^Call to an undefined method Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\Relation\\:\\:getForeignKey\\(\\)\\.$#"
count: 3
Expand Down
17 changes: 16 additions & 1 deletion src/Auth/Manager.php
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
<?php namespace Winter\Storm\Auth;

use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Cookie;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Request;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Session\SessionManager;

/**
* Authentication manager
Expand Down Expand Up @@ -78,6 +80,7 @@ class Manager implements \Illuminate\Contracts\Auth\StatefulGuard
protected function init()
{
$this->ipAddress = Request::ip();
$this->sessionManager = App::make(SessionManager::class);
}

//
Expand Down Expand Up @@ -479,7 +482,19 @@ protected function setPersistCodeInSession($user, $remember = true)
Session::put($this->sessionKey, $toPersist);

if ($remember) {
Cookie::queue(Cookie::forever($this->sessionKey, json_encode($toPersist)));
$config = $this->sessionManager->getSessionConfig();
Cookie::queue(
Cookie::forever(
$this->sessionKey,
json_encode($toPersist),
$config['path'],
$config['domain'],
$config['secure'] ?? false,
$config['http_only'] ?? true,
false,
$config['same_site'] ?? null
)
);
}
}

Expand Down
2 changes: 0 additions & 2 deletions src/Config/ConfigWriter.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
<?php namespace Winter\Storm\Config;

use Exception;

use PhpParser\Error;
use PhpParser\Lexer\Emulative;
use PhpParser\ParserFactory;
Expand Down
80 changes: 11 additions & 69 deletions src/Console/Command.php
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
<?php namespace Winter\Storm\Console;

use Winter\Storm\Support\Str;
use Illuminate\Console\Command as BaseCommand;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Command\SignalableCommandInterface;

/**
* Command base class
* Contains utilities to make developing CLI commands nicer
*
* @author Luke Towers
*/
abstract class Command extends BaseCommand
abstract class Command extends BaseCommand implements SignalableCommandInterface
{
use Traits\HandlesCleanup;
use Traits\ProvidesAutocompletion;

/**
* @var array List of commands that this command replaces (aliases)
*/
Expand All @@ -34,9 +35,10 @@ public function __construct()
* Write a string in an alert box.
*
* @param string $string
* @param int|string|null $verbosity
* @return void
*/
public function alert($string)
public function alert($string, $verbosity = null)
{
$maxLength = 80;
$padding = 5;
Expand All @@ -59,82 +61,22 @@ public function alert($string)
$width = $innerLineWidth + ($border * 2);

// Top border
$this->comment(str_repeat('*', $width));
$this->comment(str_repeat('*', $width), $verbosity);

// Alert content
foreach ($lines as $line) {
// Apply padding and borders to each line
$this->comment(
str_repeat('*', $border)
. str_pad($line, $innerLineWidth, ' ', STR_PAD_BOTH)
. str_repeat('*', $border)
. str_repeat('*', $border),
$verbosity
);
}

// Bottom border
$this->comment(str_repeat('*', $width));
$this->comment(str_repeat('*', $width), $verbosity);

$this->newLine();
}

/**
* Provide autocompletion for this command's input
*/
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
{
$inputs = [
'arguments' => $input->getArguments(),
'options' => $input->getOptions(),
];

foreach ($inputs as $type => $data) {
switch ($type) {
case 'arguments':
$dataType = 'Argument';
$suggestionType = 'Values';
break;
case 'options':
$dataType = 'Option';
$suggestionType = 'Options';
break;
default:
// This should not be possible to ever be triggered given the type is hardcoded above
throw new \Exception('Invalid input type being parsed during completion');
}
if (!empty($data)) {
foreach ($data as $name => $value) {
// Skip the command argument since that's handled by Artisan directly
if (
$type === 'arguments'
&& in_array($name, ['command'])
) {
continue;
}

$inputRoutingMethod = "mustSuggest{$dataType}ValuesFor";
$suggestionValuesMethod = Str::camel('suggest ' . $name) . $suggestionType;
$suggestionsMethod = 'suggest' . $suggestionType;

if (
method_exists($this, $suggestionValuesMethod)
&& $input->{$inputRoutingMethod}($name)
) {
$values = $this->$suggestionValuesMethod($value, $inputs);
$suggestions->{$suggestionsMethod}($values);
}
}
}
}
}

/**
* Example implementation of a suggestion method
*/
// public function suggestMyArgumentValues(string $value = null, array $allInput): array
// {
// if ($allInput['arguments']['dependent'] === 'matches') {
// return ['some', 'suggested', 'values'];
// }
// return ['all', 'values'];
// }
}
2 changes: 1 addition & 1 deletion src/Console/Traits/ConfirmsWithInput.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Console Command Trait that provides confirmation step that requires set
* input to be provided in order to act as confirmation for an action
*
* @package winter\wn-system-module
* @package winter\storm
* @author Luke Towers
*/
trait ConfirmsWithInput
Expand Down
77 changes: 77 additions & 0 deletions src/Console/Traits/HandlesCleanup.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php namespace Winter\Storm\Console\Traits;

/**
* Console Command Trait that injects cross-platform signal handling to trigger
* cleanup on exit through the handleCleanup() method on the implementing class.
*
* >**NOTE:** This trait requires the implementing class to implement the
* Symfony\Component\Console\Command\SignalableCommandInterface interface
*
* @package winter\storm
* @author Luke Towers
*/
trait HandlesCleanup
{
/**
* Returns the process signals this command listens to
* @see https://www.php.net/manual/en/pcntl.constants.php
* Used to support the handleCleanup() end-class method
*/
public function getSubscribedSignals(): array
{
$signals = [];
if (method_exists($this, 'handleCleanup')) {
// Handle Windows OS
if (PHP_OS_FAMILY === 'Windows') {
// Attach to Windows Ctrl+C & Ctrl+Break events
if (function_exists('sapi_windows_set_ctrl_handler')) {
sapi_windows_set_ctrl_handler([$this, 'handleWindowsSignal'], true);
}
// Handle Unix-like OS
} else {
$signals = [SIGINT, SIGTERM, SIGQUIT];
}
}

return $signals;
}

/**
* Handle the provided Unix process signal
*/
public function handleSignal(int $signal): void
{
// Handle the signal
if (method_exists($this, 'handleCleanup')) {
$this->handleCleanup();
}

// Exit cleanly at this point if this was a user termination
if (in_array($signal, [SIGINT, SIGQUIT])) {
exit(0);
}
}

/**
* Handle the provided Windows process singal.
*/
public function handleWindowsSignal(int $event): void
{
// Remove the handler
sapi_windows_set_ctrl_handler([$this, 'handleWindowsSignal'], false);

// Handle the signal
if (
method_exists($this, 'handleCleanup')
&& (
$event === PHP_WINDOWS_EVENT_CTRL_C
|| $event === PHP_WINDOWS_EVENT_CTRL_BREAK
)
) {
$this->handleCleanup();

// Exit cleanly at this point if this was a user termination
exit(0);
}
}
}
76 changes: 76 additions & 0 deletions src/Console/Traits/ProvidesAutocompletion.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php namespace Winter\Storm\Console\Traits;

use Winter\Storm\Support\Str;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;

/**
* Console Command Trait that injects cross-platform signal handling to trigger
* cleanup on exit through the handleCleanup() method on the implementing class.
*
* @package winter\storm
* @author Luke Towers
*/
trait ProvidesAutocompletion
{
/**
* Provide autocompletion for this command's input
*/
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
{
$inputs = [
'arguments' => $input->getArguments(),
'options' => $input->getOptions(),
];

foreach ($inputs as $type => $data) {
switch ($type) {
case 'arguments':
$dataType = 'Argument';
$suggestionType = 'Values';
break;
case 'options':
$dataType = 'Option';
$suggestionType = 'Options';
break;
default:
// This should not be possible to ever be triggered given the type is hardcoded above
throw new \Exception('Invalid input type being parsed during completion');
}
if (!empty($data)) {
foreach ($data as $name => $value) {
// Skip the command argument since that's handled by Artisan directly
if (
$type === 'arguments'
&& in_array($name, ['command'])
) {
continue;
}

$inputRoutingMethod = "mustSuggest{$dataType}ValuesFor";
$suggestionValuesMethod = Str::camel('suggest ' . $name) . $suggestionType;
$suggestionsMethod = 'suggest' . $suggestionType;

if (
method_exists($this, $suggestionValuesMethod)
&& $input->{$inputRoutingMethod}($name)
) {
$values = $this->$suggestionValuesMethod($value, $inputs);
$suggestions->{$suggestionsMethod}($values);
}
}
}
}
}

/**
* Example implementation of a suggestion method
*/
// public function suggestMyArgumentValues(string $value = null, array $allInput): array
// {
// if ($allInput['arguments']['dependent'] === 'matches') {
// return ['some', 'suggested', 'values'];
// }
// return ['all', 'values'];
// }
}
Loading