{"id":33984395,"url":"https://github.com/phuria/pipolino","last_synced_at":"2025-12-13T04:29:30.123Z","repository":{"id":57041209,"uuid":"83812401","full_name":"phuria/pipolino","owner":"phuria","description":"A immutable dispatcher to process values in sequence. ","archived":false,"fork":false,"pushed_at":"2017-07-08T19:49:54.000Z","size":17,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-20T10:26:23.516Z","etag":null,"topics":["dispatcher","immutable","pipeline","processing"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/phuria.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-03-03T15:25:27.000Z","updated_at":"2019-06-24T13:43:49.000Z","dependencies_parsed_at":"2022-08-23T23:31:10.191Z","dependency_job_id":null,"html_url":"https://github.com/phuria/pipolino","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/phuria/pipolino","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phuria%2Fpipolino","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phuria%2Fpipolino/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phuria%2Fpipolino/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phuria%2Fpipolino/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phuria","download_url":"https://codeload.github.com/phuria/pipolino/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phuria%2Fpipolino/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":27699829,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-13T02:00:09.769Z","response_time":147,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dispatcher","immutable","pipeline","processing"],"created_at":"2025-12-13T04:29:29.454Z","updated_at":"2025-12-13T04:29:30.116Z","avatar_url":"https://github.com/phuria.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Pipolino\n[![Build Status](https://img.shields.io/scrutinizer/build/g/phuria/pipolino.svg?maxAge=3600)](https://scrutinizer-ci.com/g/phuria/pipolino/build-status/master)\n[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/phuria/pipolino.svg?maxAge=3600)](https://scrutinizer-ci.com/g/phuria/pipolino/?branch=master)\n[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/phuria/pipolino.svg?maxAge=3600)](https://scrutinizer-ci.com/g/phuria/pipolino/?branch=master)\n[![Packagist](https://img.shields.io/packagist/v/phuria/pipolino.svg?maxAge=3600)](https://packagist.org/packages/phuria/pipolino)\n[![license](https://img.shields.io/github/license/phuria/pipolino.svg?maxAge=2592000?style=flat-square)]()\n[![php](https://img.shields.io/badge/PHP-5.6-blue.svg?maxAge=2592000)]()\n\nThe package provides dispatcher that can be used to process\none or more values in sequence. It is a combination of \n[thephpleague/pipeline](https://github.com/thephpleague/pipeline) \nand [PSR-7 middleware dispatcher (eg. Relay)](https://github.com/relayphp/Relay.Relay).\n\n## Installation \n\n```\ncomposer require phuria/pipolino\n```\n\n## Usage\n\n```php\n$pipolino = (new Pipolino())\n    -\u003eaddStage(function(callable $next, $payload) {\n        return $next($payload * 2); // 20 * 2\n    })\n    -\u003eaddStage(function (callable $next, $payload) {\n        return $next($payload + 1); // 40 + 1\n    })\n    -\u003eaddStage(function (callable $next, $payload) {\n        return $next($payload / 10); // 41 / 10\n    });\n\necho $pipolino-\u003eprocess(20); //output: 4.1\n```\n\n## Immutable\n\nPipolino are implemented as __immutable__. Any change on object (eg. add new stage)\ncreates new object.\n\n## Stage objects\n\nObject can be used as a stage. It must have only implemented `__invoke` method.\n \n```php\nclass CacheStage\n{\n    private $cache;\n    \n    public function __construct(CacheInterface $cache)\n    {\n        $this-\u003ecache = $cache;\n    }\n    \n    public function __invoke(callable $next, $result, array $criteria)\n    {\n        $hash = sha1(serialize($criteria));\n        \n        if ($this-\u003ecache-\u003ehas($hash)) {\n            return $this-\u003ecache-\u003eget($hash);\n        }\n        \n        $result = $next($result, $criteria);\n        $this-\u003ecache-\u003eset($hash, $result, 3600);\n        \n        return $result;\n    }\n}\n```\n\n## Many arguments\n\nPipolino (in contrast to pipeline) accepts any number of arguments to process.\n\n```php\n$pipolino = (new Pipolino)\n    -\u003eaddStage(function (callable $next, $result, array $options) {\n        if (null === $result) {\n            return $options['onNull'];\n        }\n    \n        return $next($result, $context);\n    })\n    -\u003eaddStage(function (callable $next, $result, array $options) {\n        $formatted = $next(number_format($result, 2).' '.$options['currency'])\n    \n        // Can be replaced with: \"return $forrmated;\",\n        // however, should call $next().\n        return $next($formatted, $options); \n    });\n\n$options = ['onNull' =\u003e '-', 'currency' =\u003e 'USD'];\n\necho $pipolino-\u003eprocess(null, $options); // output: -\necho $pipolino-\u003eprocess(10, $options); // output: 10.00 USD\n```\n\n## Pipolino composite\n\nEach pipolino can be used as stage. This allows for easy re-use pipolino.\n\n```php\n$loadingProcess = (new Pipolino())\n    -\u003eadd(new CheckCache())\n    -\u003eadd(new LoadFromDB());\n    \n$showProcces = (new Pipolino())\n    -\u003eadd(new JsonFormat())\n    -\u003eadd($loadingProccess)\n    -\u003eadd(new NullResult());\n```\n\n## Default stage\n\nDefault stage is last stage in pipolino, \nand does not accept `$next` callable as first argument.\nIf you need to alter behavior of default stage (return first argument)\ncall `Pipolino::withDefaultStage()` method.\n\n```php\n$pipolino = (new Pipolino)\n    -\u003eaddStage(function (callable $net, $i) {\n        if (is_string($i)) {\n            $i = (int) $i;\n        }\n        \n        return $next($i);\n    })\n    -\u003eaddStage(function (callable $next, $i) {\n        if (is_int($i)) {\n            return $i % 2 ? 'even' : 'odd';\n        }\n        \n        return $next($i);\n    })\n    -\u003ewithDefaultStage(function () {\n        throw new \\Exception('Unable to guess type.');\n    });\n    \necho $pipolino-\u003eprocess(2); // output: even\necho $pipolino-\u003eprocess('4'); // output: even\necho $pipolino-\u003eproccess(2.50); // throws exception\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphuria%2Fpipolino","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphuria%2Fpipolino","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphuria%2Fpipolino/lists"}