Skip to content

Commit

Permalink
Refactor + upgrade dependencies
Browse files Browse the repository at this point in the history
- Improve repositories generation
- Upgrade to squirrelphp/queries 1.2
- Upgrade squirrelphp/debug usage
  • Loading branch information
iquito committed Dec 15, 2021
1 parent 79edc03 commit cbffb53
Show file tree
Hide file tree
Showing 29 changed files with 464 additions and 424 deletions.
24 changes: 20 additions & 4 deletions bin/squirrel_repositories_generate
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ $inputDefinition->addOption(new InputOption(
'verbose',
'v',
InputOption::VALUE_NONE,
'Verbose mode, showing all generated repositories' // Description
'Verbose mode, showing all generated repositories and possible file conflicts' // Description
));
$inputDefinition->addOption(new InputOption(
'force',
'f',
InputOption::VALUE_NONE,
'Force creating repositories and gitignore files, even when there are file conflicts' // Description
));
$inputDefinition->addOption(new InputOption(
'source-dir',
Expand All @@ -36,18 +42,28 @@ $inputDefinition->addOption(new InputOption(
$input = new ArgvInput(null, $inputDefinition);
$srcDirectories = $input->getOption('source-dir');
$isVerbose = $input->getOption('verbose');
$isForce = $input->getOption('force');

// Execute command to generate repositories
$cmd = new \Squirrel\Entities\Generate\RepositoriesGenerateCommand(
$srcDirectories,
$isForce,
new \Squirrel\Entities\Generate\PHPFilesInDirectoryGetContents()
);
$log = $cmd();
[$logRepositories, $logConflicts] = $cmd();

// Show detailed log
if ($isVerbose === true) {
echo implode("\n", $log);
echo implode("\n", $logRepositories);
}

// Show summary
echo "\n" . count($log) . ' entities found for which repositories were generated.' . "\n";
if (\count($logConflicts) > 0 && $isForce === false) {
echo "\n" . count($logConflicts) . ' file conflicts found, where existing files (which seem to not have been generated by this command) would be overwritten. Re-run with --force if you want to overwrite these files, or with --verbose to see which files have conflicts.' . "\n";
} else {
echo "\n" . count($logRepositories) . ' entities found for which repositories were generated.' . "\n";

if (\count($logConflicts) > 0) {
echo count($logConflicts) . ' file conflicts found, those files were overwritten because of --force flag.' . "\n";
}
}
8 changes: 4 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"php": ">=8.0",
"symfony/console": "^5.0|^6.0",
"symfony/finder": "^5.0|^6.0",
"squirrelphp/queries": "^0.13"
"squirrelphp/queries": "^1.2"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.3",
Expand Down Expand Up @@ -61,9 +61,9 @@
"phpunit": "vendor/bin/phpunit --colors=always",
"phpunit_clover": "vendor/bin/phpunit --coverage-text --coverage-clover build/logs/clover.xml",
"coverage": "XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-html tests/_reports",
"phpcs": "vendor/bin/phpcs --standard=ruleset.xml --extensions=php --cache=.phpcs-cache --ignore=tests/TestEntities/NonRepositoryWithAttributeInUse.php --colors src bin tests",
"phpcsd": "vendor/bin/phpcs -s --standard=ruleset.xml --extensions=php --cache=.phpcs-cache --ignore=tests/TestEntities/NonRepositoryWithAttributeInUse.php --colors src bin tests",
"phpcsfix": "vendor/bin/phpcbf --standard=ruleset.xml --extensions=php --cache=.phpcs-cache --ignore=tests/TestEntities/NonRepositoryWithAttributeInUse.php src bin tests",
"phpcs": "vendor/bin/phpcs --standard=ruleset.xml --extensions=php --cache=.phpcs-cache --ignore=tests/TestEntities/NonRepositoryWithAttributeInUse.php,tests/TestEntities/UserNickname.php --colors src bin tests",
"phpcsd": "vendor/bin/phpcs -s --standard=ruleset.xml --extensions=php --cache=.phpcs-cache --ignore=tests/TestEntities/NonRepositoryWithAttributeInUse.php,tests/TestEntities/UserNickname.php --colors src bin tests",
"phpcsfix": "vendor/bin/phpcbf --standard=ruleset.xml --extensions=php --cache=.phpcs-cache --ignore=tests/TestEntities/NonRepositoryWithAttributeInUse.php,tests/TestEntities/UserNickname.php src bin tests",
"binupdate": "@composer bin all update --ansi",
"bininstall": "@composer bin all install --ansi"
}
Expand Down
2 changes: 1 addition & 1 deletion src/Builder/DeleteEntries.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ private function accidentalDeleteAllCheck(): void
if (\count($this->where) === 0 && $this->confirmNoWhere !== true) {
throw Debug::createException(
DBInvalidOptionException::class,
[BuilderInterface::class],
'No restricting "where" arguments defined for DELETE ' .
'and no override confirmation with "confirmNoWhereRestrictions" call',
ignoreClasses: [BuilderInterface::class],
);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Builder/MultiSelectEntriesFreeform.php
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,9 @@ private function makeSureBadPracticeWasConfirmed(): void
if ($this->confirmBadPractice !== true) {
throw Debug::createException(
DBInvalidOptionException::class,
[BuilderInterface::class],
'No confirmation that freeform queries are bad practice - ' .
'call "confirmFreeformQueriesAreNotRecommended" with "OK" to confirm the freeform query',
ignoreClasses: [BuilderInterface::class],
);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Builder/MultiUpdateEntriesFreeform.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ private function makeSureBadPracticeWasConfirmed(): void
if ($this->confirmBadPractice !== true) {
throw Debug::createException(
DBInvalidOptionException::class,
[BuilderInterface::class],
'No confirmation that freeform queries are bad practice - ' .
'call "confirmFreeformQueriesAreNotRecommended" with "OK" to confirm the freeform query',
ignoreClasses: [BuilderInterface::class],
);
}
}
Expand Down
36 changes: 18 additions & 18 deletions src/Builder/SelectEntries.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,50 +9,50 @@
/**
* Select query builder as a fluent object - build query and return object(s) or flattened fields
*
* Properties are only protected so we can extend it with generated repositories
*
* @implements \IteratorAggregate<int,object>
*/
class SelectEntries implements BuilderInterface, \IteratorAggregate
{
use FlattenedFieldsWithTypeTrait;

private RepositoryReadOnlyInterface $repository;

/**
* @var array<int|string,mixed> WHERE restrictions in query
*/
private array $where = [];
protected array $where = [];

/**
* @var array<int|string,string> ORDER BY sorting in query
*/
private array $orderBy = [];
protected array $orderBy = [];

/**
* @var int How many results should be returned
*/
private int $limitTo = 0;
protected int $limitTo = 0;

/**
* @var int Where in the result set to start (so many entries are skipped)
*/
private int $startAt = 0;
protected int $startAt = 0;

/**
* @var bool Whether the SELECT query should block the scanned entries
*/
private bool $blocking = false;
protected bool $blocking = false;

/**
* @var string[] Only retrieve some of the fields of the objects, default is to return all
*/
private array $fields = [];
protected array $fields = [];

public function __construct(RepositoryReadOnlyInterface $repository)
{
$this->repository = $repository;
public function __construct(
protected RepositoryReadOnlyInterface $repository,
) {
}

public function field(string $onlyGetThisField): self
public function field(string $onlyGetThisField): static
{
$this->fields = [$onlyGetThisField];
return $this;
Expand All @@ -61,7 +61,7 @@ public function field(string $onlyGetThisField): self
/**
* @param string[] $onlyGetTheseFields
*/
public function fields(array $onlyGetTheseFields): self
public function fields(array $onlyGetTheseFields): static
{
$this->fields = $onlyGetTheseFields;
return $this;
Expand All @@ -70,7 +70,7 @@ public function fields(array $onlyGetTheseFields): self
/**
* @param array<int|string,mixed> $whereClauses
*/
public function where(array $whereClauses): self
public function where(array $whereClauses): static
{
$this->where = $whereClauses;
return $this;
Expand All @@ -79,7 +79,7 @@ public function where(array $whereClauses): self
/**
* @param array<int|string,string>|string $orderByClauses
*/
public function orderBy($orderByClauses): self
public function orderBy(array|string $orderByClauses): static
{
if (\is_string($orderByClauses)) {
$orderByClauses = [$orderByClauses];
Expand All @@ -89,19 +89,19 @@ public function orderBy($orderByClauses): self
return $this;
}

public function startAt(int $startAtNumber): self
public function startAt(int $startAtNumber): static
{
$this->startAt = $startAtNumber;
return $this;
}

public function limitTo(int $numberOfEntries): self
public function limitTo(int $numberOfEntries): static
{
$this->limitTo = $numberOfEntries;
return $this;
}

public function blocking(bool $active = true): self
public function blocking(bool $active = true): static
{
$this->blocking = $active;
return $this;
Expand Down
2 changes: 1 addition & 1 deletion src/Builder/UpdateEntries.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ public function writeAndReturnAffectedNumber(): int
if (\count($this->where) === 0 && $this->confirmNoWhere !== true) {
throw Debug::createException(
DBInvalidOptionException::class,
[BuilderInterface::class],
'No restricting "where" arguments defined for UPDATE ' .
'and no override confirmation with "confirmNoWhereRestrictions" call',
ignoreClasses: [BuilderInterface::class],
);
}

Expand Down
89 changes: 48 additions & 41 deletions src/Generate/FindClassesWithAttribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ public function __invoke(string $fileContents): array

// Stores the most recent namespace, import class name and classname in loop
$namespace = '';
$importClassName = '';

// Get all PHP tokens from a file
$tokens = \token_get_all($fileContents);
Expand All @@ -24,70 +23,61 @@ public function __invoke(string $fileContents): array
$namespaceStarted = false;
$classNameStarted = false;
$useImportStarted = false;
$attributeStarted = false;
$attributeUseFound = false;

// Go through all PHP tokens
// Go through all PHP tokens in the file
foreach ($tokens as $key => $token) {
// "use" name started, so collect all parts until we reach the end of the name
// Skip all whitespace tokens
if ($token[0] === T_WHITESPACE) {
continue;
}

// Look for usage of our attributes in use imports
if ($useImportStarted === true) {
// @codeCoverageIgnoreStart
// In PHP8 the whole class namespace is its own token
if (PHP_VERSION_ID >= 80000 && $token[0] === T_NAME_QUALIFIED) {
$importClassName = $token[1];
} elseif (PHP_VERSION_ID < 80000 && \in_array($token[0], [T_STRING, T_NS_SEPARATOR], true)) {
// In PHP 7.4 the namespace is made of string and namespace separators
$importClassName .= $token[1];
} elseif ($token[0] === T_WHITESPACE) { // Ignore whitespace, can be before or after the class name
} else { // Every other token indicates that we have reached the end of the name
$namespaceStarted = false;

// We have found the attribute namespace - so there can be entities in this file
if (
$importClassName === 'Squirrel\\Entities\\Attribute'
|| $importClassName === 'Squirrel\\Entities\\Attribute\\Entity'
|| $importClassName === 'Squirrel\\Entities\\Attribute\\Field'
) {
if ($token[0] === T_NAME_QUALIFIED) {
if ($this->isAttributeUsage($token[1])) {
$attributeUseFound = true;
}
}

$useImportStarted = false;
}

// Look for usage of our attributes in attributes (usually those would be fully qualified, unusual but possible)
if ($attributeStarted === true) {
if ($token[0] === T_NAME_FULLY_QUALIFIED || $token[0] === T_NAME_QUALIFIED) {
if ($this->isAttributeUsage($token[1])) {
$attributeUseFound = true;
}
}
// @codeCoverageIgnoreEnd

$attributeStarted = false;
}

// "namespace" name started, so collect all parts until we reach the end of the name
// Record a new namespace to correctly assign the namespace for found classes
if ($namespaceStarted === true) {
// @codeCoverageIgnoreStart
// In PHP8 the whole class namespace can be its own token
if (PHP_VERSION_ID >= 80000 && $token[0] === T_NAME_QUALIFIED) {
if ($token[0] === T_NAME_QUALIFIED || $token[0] === T_STRING) {
$namespace = $token[1];
$namespaceStarted = false;
} elseif (\in_array($token[0], [T_STRING, T_NS_SEPARATOR], true)) {
// In PHP 7.4 the namespace is made of string and namespace separators
// In PHP8 the namespace can be one string
$namespace .= $token[1];
} elseif ($token[0] === T_WHITESPACE) { // Ignore whitespace, can be before or after the namespace
} else { // Every other token indicates that we have reached the end of the name
$namespaceStarted = false;
}
// @codeCoverageIgnoreEnd

$namespaceStarted = false;
}

// "class" name started, so collect all parts until we reach the end of the name
// Record any classes if we have found attributes
if ($classNameStarted === true) {
// Only a string is expected for the class name
if ($token[0] === T_STRING) {
if (\strlen($token[1]) > 0 && $attributeUseFound === true) {
$classes[] = [$namespace, $token[1]];
}
} elseif ($token[0] === T_WHITESPACE) { // Ignore whitespace, can be before or after the class name
} else { // Every other token indicates that we have reached the end of the name
$classNameStarted = false;
}

$classNameStarted = false;
}

// "use" token - everything coming after this has to be checked for the attribute classes
if ($token[0] === T_USE) {
$useImportStarted = true;
$importClassName = '';
}

// "namespace" token - start collecting the namespace name
Expand All @@ -96,13 +86,30 @@ public function __invoke(string $fileContents): array
$namespace = '';
}

// "class" token - start collecting the class name which is being defined
// "class" token - collect the class name if attributes were found earlier
if ($token[0] === T_CLASS) {
$classNameStarted = true;
}

// "attribute" token - look for fully qualified attribute
if ($token[0] === T_ATTRIBUTE) {
$attributeStarted = true;
}
}

// Return list of the classes found
return $classes;
}

private function isAttributeUsage(string $class): bool
{
// Remove any preceding slashes
$class = \ltrim($class, '\\');

if (\str_starts_with($class, 'Squirrel\\Entities\\Attribute')) {
return true;
}

return false;
}
}
Loading

0 comments on commit cbffb53

Please sign in to comment.