Giter VIP home page Giter VIP logo

athenaeum's Introduction

Latest Stable Version Total Downloads Latest Unstable Version License Build Status

Athenaeum

Athenaeum is a mono repository; a collection of various packages. The majority are based on well known components, such as those offered by Laravel. A few of the offered packages are:

Config

A configuration loader, supporting *.ini, *.json, *.php, *.yml, *.toml, and *.neon.

Core

A custom Laravel Application implementation, intended for testing, tinkering or development of non-essential custom applications.

Circuits

A Circuit Breaker to encapsulate failure prevention logic.

Dto

Data Transfer Object abstraction.

ETags

ETags and Http Conditional Request evaluation utilities.

Http Clients

Http Client wrapper, with a Manager able to handle multiple "profiles".

Support

Aware-of Helpers for Laravel and DTOs.

Not a Framework

Athenaeum shouldn't be mistaken for a framework, despite the amount of packages that are offered. The packages are merely helpers and utilities...

How to install

composer require aedart/athenaeum

Official Documentation

Please read the official documentation for additional information.

Versioning

This package follows Semantic Versioning 2.0.0

License

BSD-3-Clause, Read the LICENSE file included in this package

athenaeum's People

Contributors

aedart avatar kernelguy avatar trukes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

athenaeum's Issues

[Util] Move Arr to a Collecitons package

Describe the Feature
While Laravel still keeps the *\Support namespace for it's Collection component, it has been moved to a "collections" package.
This isn't the worst idea, since it will put everything related to "collections" into a single package. Thus, Athenaeum could also create a similar package for collections.

The custom utils Arr should then be moved to such a package. The original Arr could then extend the new version and be deprecated.

[Fitlers] Remove StopWords concern, in SearchFilter

The StopWords concern, inside SearchFilter ended up causing serious issues to search precision. The idea might have been good, yet the provided search filter is intended to be as simple as possible and there should be no need to attempt reinventing all kinds of complex word stemming, stop words removal and other linguistic features.

Solution for this version

Disable the "stop word" removal mechanism. A simple trim of the provided search term(s) is sufficient, for this kind of filter.

In future major version

In the next major version, this feature must be entirely removed.
Note: voku/stop-words must then also be removed as package dependency

[Arr] Array to string conversion in differenceAssoc

Describe the defect
Whenever a nested empty array is provided, the method fails comparing.

Steps To Reproduce
Attempt to compare the following:

$a = [
    'a' => true,
    'b' => [],
];

$b = [
    'a' => true,
    'b' => [],
];

$result = Arr::differenceAssoc($a, $b);

Notice that the arrays nested arrays are essentially both empty.

Expected behavior
Expected key 'b' to be returned with [1, 2, 3];

Possible Solution
Internally, empty arrays need to be converted to null or something similar, because this does not appear to work well.

Migrate to Symplify Monorepo-builder v10.x

Describe the Feature

Since v4.x, Athenaeum has been a mono-repository, using Symplify Monorepo-builder. This has worked pretty well, after all the hurdle of reorganizing everything into a single repository. Yet, since then numerous updates and breaking changes have been made to the Monorepo-builder. Among them is that GitHub Actions is now the favored way of performing the actual "split". This means that the current setup needs to be changed, if Symplify is still going to be used.

Inspiration

How should the feature be implemented?

[Collections] Summation Component

Describe the Feature
A specialised collection that is able to process "items" or "records" based on one or several criteria and produce one or more "report summary result items".

For instance, if you wish to create a summary of records that shows various types of details, e.g. total amount(s), sub-total(s), average(s), deviations, ...and other types of information, it might be a bit tricky if you have to perform several database queries and then also perform some post-query processing of numbers. This becomes especially true, if different types of "computational strategies" must be applied, depending on the type of record.
In other words, source code can become somewhat messy, even if you encapsulate this into a "Report" or "Summary" component.

To help separate "summation" logic, based on whatever condition there might be, one could encapsulate this into a collection of "items", which applies various types of computations, per item, based on provided processing strategies. Once processed, the summation component could simply yield a list of results.

Some Definitions

  • "[...] a final part of an argument reviewing points made and expressing conclusions [...]" merriam webster
  • "[...] cumulative action or effect [...]" merriam webster
  • "[...] a brief description of the most important information about something [...]" merriam webster

Also, consider the following statement about a "Summation With Details Reports";
"[...] Think of it as a more complex version of the Rows and Columns Report.

It is still able to display data from the selected fields, based on the specified criteria, but it also has computational elements to it to display more complex information, such as a count of all records or the Sum total of a list of dollar values.

A Summation with Details report also has the added benefit of being able to display results in a chart.[...]" Evolution Marketing

[Util] Show latest tag (version) for application

Describe the Feature
The Aedart\Utils\Version::package() method is only able to determine an installed package's version. When attempted on the application itself, an "incorrect" version will returned.

Possible Solution
The same approach as for the "PWM" project, in which git is used to determine the latest available tag. However, to ensure some level of cross OS compatibility, the following stackoverflow answer might be useful: https://stackoverflow.com/questions/12424787/how-to-check-if-a-shell-command-exists-from-php (see multiple answers, before implementing)

Solution could be implemented via a new method, e.g. application().

[Http Client] Call to undefined function GuzzleHttp\Psr7\parse_query()

The C1_QueryTest::canSetQueryStringValues test fails with the following message:

---------
1) C1_QueryTest: Can set query string values | "default"
 Test  tests/Integration/Http/Clients/C1_QueryTest.php:canSetQueryStringValues
  [Error] Call to undefined function GuzzleHttp\Psr7\parse_query()  
#1  /home/alin/code/athenaeum/tests/Integration/Http/Clients/C1_QueryTest.php:101
---------
2) C1_QueryTest: Can set query string values | "json"
 Test  tests/Integration/Http/Clients/C1_QueryTest.php:canSetQueryStringValues
  [Error] Call to undefined function GuzzleHttp\Psr7\parse_query()  
#1  /home/alin/code/athenaeum/tests/Integration/Http/Clients/C1_QueryTest.php:101

This happened sometime after a newer version of Guzzle Http was installed.

[Redmine] Add a "fetchAll()" method for the "HasMany" relation

In some situations, it would be nice to just fetch all related resources, e.g. all child issues, without having to manually paginate to get all the results. Using the all(), the HasMany relation can be expanded to offer this feature.

Note: Current developers will have a hard time achieving this, because it's easy to obtain the filters that have been applied on the relation.

[Util] Duration Component

Describe the Feature
A new utility component that is able to calculate various types of relative date and time duration.

The component should be able to convert any given date or time unit, e.g. 52.200 seconds, and convert it into some desirable format, like 14 hours and 30 minutes. The same should apply for the inverse.

Problem:
Sometimes, there is a need to convert and format a unit of time into several dimensions, e.g. years, months, weeks, days, hours, minutes and seconds. Maybe it's just a single unit, e.g. hours, or perhaps it's several units, like hours-minutes and seconds.
This isn't always the case, which means that whatever output-format methods is designed, should take into account the "level" or "amount" of units the given data or time

Problem:
There are so many data and time formats, that it would be a good idea to allow multiple formats as input for the duration.
E.g. php native DataTime instance, as well as DateInterval. Carbon also has extended versions, which accepts even further input formats.

$duration = Duration::from(new DateTime());

$duration = Duration::fromFormat('HH:mm:ss', '100:23:02'); // Relative formats, not just fixed 24 h date & time formats.

// ...etc

Formatting Output

An output or format method, which is able to re-calculate the internal duration according to desired output.
E.g.

$duration = Duration::fromSeconds(52200);

$duration->format('HH:mm'); // Should out 14:30 (hours and minutes)

$duration->format('DD'); // Should output ~0.6042 days

$seconds = $duration->toMinutes(); // 870 minutes

Start, Stop time and arithmetic

Another aspect is the ability calculate duration between two dates / times.

$duration = Duration::now();

sleep(2); 

$difference = $duration->diff(Duration::now());
$difference->format('mm'); // E.g. 0.3 minutes... or perhaps 0 minutes?

// --------------------------------------------------------------- //

// Add, subtract various time units.
$duration = Duration::now()->add(60, 'seconds');
$duration = Duration::now()->add('32h 01s', '%HHh %sss'); // Allow custom formats ?

$duration = Duration::now()->subtract(new DataTime());
// ...etc

// --------------------------------------------------------------- //

// Comparison
$result = $durationA->gt($durationB); // true or false

Location / Namespace
An empty component has been created in \Aedart\Utils\Dates\Duration (packages/Utils/src/Dates/Duration.php) , along with it's associated unit test component (\Aedart\Tests\Unit\Utils\Dates\DurationTest).

Improve Json bitmask operation

The resolveThrowExceptionBitmask() can be eliminated entirely.

The following can be used, in a single line.

$options |= JSON_THROW_ON_ERROR;

Unable to run migrations in tests, after upgrade to Orchestra v6.21.0

The following type error is thrown for several tests that use database migrations.

[TypeError] Argument 1 passed to Orchestra\Testbench\artisan() must be an instance of Orchestra\Testbench\TestCase, instance of Aedart\Tests\Integration\Database\Models\SluggableTest given, called in /home/alin/code/athenaeum/vendor/orchestra/testbench-core/src/Database/MigrateProcessor.php on line 70 

Basically, the author decided to declare the types for the \Orchestra\Testbench\Database\MigrateProcessor and other nested components, which are used for running migrations in tests.

Possible Solution

Need to create custom MigrateProcessor, which does not care about the test-class that is being used.

[Testing] Too many Chrome processes started, resulting in connection refused

Describe the defect
In the \Aedart\Testing\TestCases\BrowserTestCase::prepare method is executed several times which causes a Chrome Process (chrome driver) to be spawned several times. At some point, the driver simply fails with a "connection refused", which is most likely caused by this defect.

To Reproduce
Sufficient amount of browser tests will result in this. E.g. +15 browser tests does the trick.

Possible Solution
Ensure that only a single chrome process is started, regardless of amount of tests, given that no previous process is started / running.

Remove "Available since v5.x" in docs

Remove the Available since v5.x note, in the following docs:

  • Collections package
  • Database package
  • Utils Version (application() method)
  • Validation package
  • Arr::differenceAssoc()
  • SemanticVersion - validation rule
  • fresh() - http client manager
  • Redmine API Client package
  • Criteria query filter, in database package
  • Filters package
    • DateFilter
    • UTCDatetimeFilter

[6.x][Filters] Input value "filter" contains a non-scalar value.

The \Aedart\Filters\BaseProcessor::value() fails when attempting to obtain an array value. The root cause for this is Symfony's InputBag, in that they changed their get() method to only allow scalar values to be returned - thus not arrays!

Possible Solution

Use $request->get() or $request->query->all($parameter) to obtain value instead.

See symfony/symfony#41766 for additional information

[Http Client] Circuit breaker Middleware

Describe the Feature
Thus far, the #15 has changed the Http Client a lot. It now supports a true middleware layer, which means that a circuit breaker can be integrated in a much more convenient way.
Nonetheless, some configuration will most likely be required by such a middleware and has yet to be developed.

[Util] Add markdown method in Str

I have resently read Laravel String Markdown Macro, in which a markdown method is injected into the Str class. This seems like a good idea and think that Athenaeum could benefit from this, seeing that more and more markdown content is used by various projects (including many of my own!).

Possible Solution
Extend Str and add a markdown method that can parse markdown to HTML.
league/commonmark supports both CommonMark and Github-Flavored Markdown. Perhaps a good design will support both, e.g.:

// Inside Aedart\Utils\Str
public const COMMON_MARK = 1;
public const GITHUB_FLAVORED_MARKDOWN = 2;

public static function markdown(string $content, array $options = [], int $type = self::COMMON_MARK): string
{
    // ... not shown ...
}

public static function commonMark(string $content, array $options = []): string
{
    // ... not shown ...
}

public static function githubFlavoredMarkdown(string $content, array $options = []): string
{
    // ... not shown ...
}

I'm not to sure about the $environment and extensions, but this could be a good start.

Alternative Solution

Extending the Str class is slightly risky, in case that Laravel decides to create their own markdown() method. Perhaps a dedicated Markdown wrapper is more suitable?

Psr-18 Support and Guzzle v7.x, for Http Clients

Describe the Feature
It's been a while since PSr-18 has been released. Guzzle is on it's way to support this - however, it's a bit unclear when the latest version is going to be released. This needs to be resolved, before version 4.x can be released!

[Database] Add "where slug not in" query scope

We have a "whereSlugIn" query scope, but not a "whereSlugNotIn"?... This really should be supported.

Note: The \Aedart\Contracts\Database\Models\Sluggable interface should also support this method!

PHP-8x compatibility

It is time to more forward and start achieving PHP v8.x compatibility for all Athenaeum packages.

[Database] findOrCreateBySlug fails - Unique violation: ERROR: duplicate key value violates unique constraint

Describe the defect
It would appear that the find or create by slug fails finding a given resource by it's slug and proceeds to creating it, causing a duplicate database entry conflict (if one has a unique constraint on table).

To Reproduce
Steps to reproduce the behavior:

  1. Add a new model with slugs
  2. Invoke the the findOrCreateBySlug method to create a new resource
  3. Re-Invoke the the findOrCreateBySlug method to find existing resource

Expected behavior
A new resource is created the first time the method is invoked. The second time should return the existing resource.

Possible Solution
Method is based on Laravel's firstOrCreate method. If unable to determine what goes wrong, then perhaps a manual find by slug should be invoked first, and only if no result is found then a new resource should be created

HttpClient debug needs a rewind

When using the new debug() functionality on a HttpClient request, it reads the body contents of of the response, causing sub sequential calls to getBody()->getContents() to return nothing.

Found by:
$response = $client->post($url, $payload);
json_decode($response->getBody()->getContents(), JSON_THROW_ON_ERROR);

Circuit Breaker

Describe the Feature
To allow fast failure, when a 3rd part service has been detected to be down.

Some packages are available, even for Laravel. Most seem to be pretty good - perhaps a general wrapper component could solve our need. Only issue appears to be that some have not been updated for a long while.

Inspiration:

[Http Client] Add debugging methods

Describe the Feature
It can be very difficult to debug the the outgoing request. At the moment, there is little or no additional helper methods to print or log the performed request, nor the eventual received response.

Possible Solution
Add a few debugging methods to the Request Builder, e.g.: log(), debug() and dd().

log() should either use an assigned PSR Logger instance, if available. The outgoing request and received response should be logged in two entries.

debug() could use Symfony's "var dumper" to output request / response.

dd() on the other hand, should only var dump the outgoing request and STOP further execution.

[Http Client] Add integration with circuit breaker

Describe the Feature
At the moment, an entire Http Client's request flow must be wrapped into the circuit breaker's attempt() method, in order to make use of it. This can be very cumbersome.

Possible Solution
Add a way to define a circuit breaker, for each request, natively inside the Http Client. The sendRequest() should be where the circuit breaker is invoked.

There could be a design challenge in regards to PSR-18's definition of sendRequest and error handling, which needs to be evaluated.

A possible flow could be the following:

$circuitBreaker = $this->getCircuitBreakerManager()->create('weather_service');

$client = $this
    ->getHttpClientsManager()
    ->profile('weather_service')
    ->useCircuitBreaker($circuitBreaker); // NOTE: Perhaps this could also accept a profile name?

$client->get('/forecast'); // circuit breaker attempt() method should be used by sendRequest().

If the above is used, then the \Aedart\Circuits\CircuitBreaker::defaultOtherwiseCallback method must be specifiable somehow. For instance:

$circuitBreaker = $this
  ->getCircuitBreakerManager()
  ->create('weather_service')
  ->otherwise(function(){
       // ... not shown here...
   });

// ...remaining not shown ...

Enabling this feature / integration of component will make it possible to create API wrappers a bit easier, in that circuit breaker logic is performed inside the client, rather than outside. But this will also increase the complexity a lot more!

Support for "same-site" policy in Guzzle's Set-Cookie instance

Describe the Feature
The current SetCookie component from Guzzle does not support the SameSite directive, which the Athenaeum Cookies packages does.

Possible Solution
Create a pull request on Guzzle Http and add support for this directive.
If it's accepted, the change the \Aedart\Http\Clients\Requests\Builders\Guzzle\CookiesHelper::convertFromGuzzle to support it.

[Util] Version util fails for packages that are stated in root composer.json as "replaced"

After upgrading to version 2.x of jean85/pretty-package-versions, the Version utility fails obtaining package versions, for packages that are listed as "replace" in the root composer.json.

Internally, inside \Jean85\PrettyVersions, the checkReplacedPackages() appears to be responsible throwing an ReplacedPackageException exception, when the package is listed as "replaced".

I'm not entirely sure why there is a need to throw an exception...

Schedule Run command fails

Describe the defect
The schedule:run cannot run, because it's handle() requires an Exception Handler. This was introduced in Laravel v7.7.0.

Possible Solution
Create an adapter between Laravel's exception handler and the one that is provided by the Core.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.