{"id":25229058,"url":"https://github.com/ajthinking/phpfilemanipulatormedia","last_synced_at":"2025-04-05T14:12:43.312Z","repository":{"id":95889704,"uuid":"261111347","full_name":"ajthinking/PHPFileManipulatorMedia","owner":"ajthinking","description":null,"archived":false,"fork":false,"pushed_at":"2020-05-04T07:49:32.000Z","size":2886,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-11T10:47:27.175Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ajthinking.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-05-04T07:48:49.000Z","updated_at":"2020-05-04T07:49:35.000Z","dependencies_parsed_at":"2023-03-13T16:43:37.719Z","dependency_job_id":null,"html_url":"https://github.com/ajthinking/PHPFileManipulatorMedia","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ajthinking%2FPHPFileManipulatorMedia","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ajthinking%2FPHPFileManipulatorMedia/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ajthinking%2FPHPFileManipulatorMedia/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ajthinking%2FPHPFileManipulatorMedia/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ajthinking","download_url":"https://codeload.github.com/ajthinking/PHPFileManipulatorMedia/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247345844,"owners_count":20924102,"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","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":[],"created_at":"2025-02-11T10:47:01.709Z","updated_at":"2025-04-05T14:12:43.306Z","avatar_url":"https://github.com/ajthinking.png","language":"PHP","funding_links":["https://github.com/sponsors/ajthinking"],"categories":[],"sub_categories":[],"readme":"# ```PHPFile::manipulator```(:fire::fire::fire:);\n\n![tests](https://github.com/ajthinking/php-file-manipulator/workflows/tests/badge.svg)\n![version](https://img.shields.io/packagist/v/ajthinking/php-file-manipulator?color=blue)\n[![Total Downloads](https://poser.pugx.org/ajthinking/php-file-manipulator/downloads)](https://packagist.org/packages/ajthinking/php-file-manipulator)\n[![License](https://poser.pugx.org/ajthinking/php-file-manipulator/license)](https://packagist.org/packages/ajthinking/php-file-manipulator)\n\n\n\nProgramatically manipulate `PHP` / `Laravel` files on disk with an intuiutive, fluent API. Features include *File-* and *Code/AST* QueryBuilders, an inline PHP Template engine and categorization of read/write operations in `Resource` endpoints.\n\n\u003cimg src=\"https://user-images.githubusercontent.com/3457668/73567244-43055f80-4466-11ea-8103-cc68fba870d7.gif\" alt=\"Intro gif\"\u003e\n\n## Contents\n  * [Installation](#installation)\n  * [Usage](#usage)\n    + [Quick start examples](#quick-start-examples)    \n    + [Build your own templates](#build-your-own-templates)\n    + [Querying the Abstract Syntax Tree](#querying-the-abstract-syntax-tree)\n    + [LaravelFile available methods](#laravelfile-available-methods)    \n    + [Gotchas](#gotchas)\n  * [Contributing](#contributing)\n    + [Development installation](#development-installation)\n    + [Roadmap](#roadmap)  \n  * [License](#license)\n  * [Acknowledgements](#acknowledgements)\n  * [Like this package?](#like-this-package-)\n\n\n## Installation\n```\ncomposer require ajthinking/php-file-manipulator\nphp artisan vendor:publish --provider=\"PHPFileManipulator\\ServiceProvider\"\n```\n\n\n## Usage\n\n\n### Quick start examples \n```php\nuse PHPFile;\nuse LaravelFile;\n\n// find files with the query builder\nPHPFile::in('database/migrations')\n    -\u003ewhere('classExtends', 'Migration')\n  \t-\u003eandWhere('className', 'like', 'Create')\n    -\u003eget()\n    -\u003eeach(function($file) {\n        // Do something\n        $file-\u003eaddUses(['Database\\CustomMigration'])\n          -\u003eclassExtends('Database\\CustomMigration')\n          -\u003esave();\n    });\n\n// add relationship methods\nLaravelFile::load('app/User.php')\n    -\u003ehasMany(['App\\Car'])\n    -\u003ehasOne(['App\\Life'])\n    -\u003ebelongsTo(['App\\Wife'])\n  \t-\u003eclassMethodNames()\n\n// move User.php to a Models directory\nPHPFile::load('app/User.php')\n    -\u003enamespace('App\\Models')\n    -\u003emove('app/Models/User.php')\n\n// install a package trait\nPHPFile::load('app/User.php')\n    -\u003eaddUseStatements('Package\\Tool')\n    -\u003eaddTraitUseStatement('Tool')\n    -\u003esave()\n\n// add a route\nLaravelFile::load('routes/web.php')\n    -\u003eaddRoute('dummy', 'Controller@method')\n    -\u003esave()\n    \n// debug will write result relative to storage/.debug\nLaravelFile::load('app/User.php')\n    -\u003esetClassName('Mistake')\n    -\u003edebug()\n\n// add items to protected properties\nLaravelFile::load('app/User.php')\n    -\u003eadd()-\u003efillable('message')\n    -\u003eadd()-\u003ecasts(['is_admin' =\u003e 'boolean'])\n    -\u003eadd()-\u003ehidden('secret')    \n\n// create new files from templates\nLaravelFile::model('Beer')\n    -\u003esave()\nLaravelFile::controller('BeerController')\n    -\u003esave()\n\n// many in one go\nLaravelFile::create('Beer', ['model', 'controller', 'migration'])\n```\n\n### Template engine\nLet's make a snippet for a method we want to insert. Start by creating a file `storage/php-file-manipulator/snippets/my-stuff.php` like shown below. In the file, we put our template code including any encapsuling constructs (in our case we will have to put a class since methods only exists inside classes). Name anything you want to be configurable with a handle for instance `'___TARGET_CLASS___'`. Even your snippet name itself may be a handle as long as it is unique.\n\n```php\n\u003c?php\n\n/**\n * Optionally use FAKE names to silence IDE warnings\n */\nuse PHPFileManipulator\\Support\\FakeName; \nuse PHPFileManipulator\\Support\\FakeName as ANY;\nuse PHPFileManipulator\\Support\\FakeName as ___TARGET_CLASS___;\n\n/**\n * This is just a placeholder class where we can add our snippets\n */\nclass _ extends FakeName\n{\n    /**\n    * ___DOC_BLOCK___\n    */\n    public function mySpecialMethod($arg)\n    {\n        $want = abs($arg);\n        return $this-\u003edoSomethingWith(___TARGET_CLASS___::class, 'my template')\n            -\u003euse(ANY::thing(new static('you' . $want)));\n    }    \n}\n```\n\nYour snippet is then instantly available anywhere in your code:\n```php\nuse PHPFileManipulator\\Support\\Snippet;\n\n// Get the snippet\nSnippet::mySpecialMethod()\n\n// Pass an array of replacement pairs to replace any handles:\nSnippet::mySpecialMethod([\n    '___DOC_BLOCK___' =\u003e 'Inserted with php-file-manipulator :)',\n    '___TARGET_CLASS___' =\u003e 'App\\Rocket'\n]);\n\n// Integrated example\nPHPFile::load('app/User.php')\n    -\u003eaddMethod(\n        Snippet::mySpecialMethod([\n            // replacement pairs ...\n        ])\n    )-\u003esave();\n````\n\n\u003e :information_source: The `Snippet` class currently only supports templates on *class methods*.\n\n\n### Querying the Abstract Syntax Tree\nAs seen in the previous examples we can query and manipulate nodes with simple or primitive values, such as *strings* and *arrays*. However, if we want to perform custom or more in dept queries we must use the `ASTQueryBuilder`.\n\nExample: how can we fetch explicit column names in a migration file?\n\n```php\nLaravelFile::load('database/migrations/2014_10_12_000000_create_users_table.php')\n    -\u003eastQuery() // get a ASTQueryBuilder\n\n    -\u003emethod()\n        -\u003enamed('up')\n    -\u003estaticCall()\n        -\u003ewhere('class', 'Schema')\n        -\u003enamed('create')\n    -\u003eargs\n    -\u003eclosure()\n    -\u003estmts\n    -\u003emethodCall()\n        -\u003ewhere('var-\u003ename', 'table')\n    -\u003eargs\n\t-\u003evalue\n\t-\u003evalue\n\t-\u003eget(); // exit ASTQueryBuilder, get a Collection        \n```\n\n\n\nThe ASTQueryBuilder examines all possible paths and automatically terminates those that cant complete the query:\n\n\u003cimg src=\"docs/img/ASTQueryBuilder2.png\" width=\"600px\"\u003e\n\n* Three kinds of methods are provided (hinted with indentation in the code example)\n    * Traversing (`methods`,`staticCalls`,`firstArg` ...)\n    * Filtering (`named`, `whereClass` ...)\n    * Resolving (`getValue`)\n* The ASTQueryBuilder relies entirely on [nikic/php-parser](https://github.com/nikic/php-parser). To understand this syntax better tinker with `dd($file-\u003east()`. \n\n### LaravelFile available methods\nTo list all the available methods A-Z on `LaravelFile`, run: \n```\nphp artisan file:api\n```\n\n![image](https://user-images.githubusercontent.com/3457668/73381863-c8520e00-42c6-11ea-9f9e-2f9e93fe8818.png)\n\nTo group methods by `EndpointProvider` use the `--group` flag:\n```\nphp artisan file:api --group\n```\n\nUse the `--provider` flag to only view methods from a specific `EndpointProvider`, for instance `IO`:\n```\nphp artisan file:api --provider=IO\n```\n\n### Gotchas\n\n\u003e If a file can't be parsed, a `FileParseError` will be thrown.\n\n\u003e To see *all* offending files run `php artisan file:errors`.\n\n\u003e :warning: This package assumes code follows guidellines and conventions from [PSR](https://www.php-fig.org/psr/) and [Laravel](https://laravel.com/docs). Examples: use no more than one class and namespace per file, refrain from multiple property declarations in same line, avoid group use statements etc.\n\n\u003e :warning: Files to be processed must have encoding UTF-8\n\n## Contributing\n### Development installation\nThe test suite requires that you are inside laravel application\n```bash\nlaravel new host\ncd host\ngit clone git@github.com:ajthinking/php-file-manipulator.git packages/Ajthinking/PHPFileManipulator\n```\nAdd this to the host projects `composer.json`\n```json\n    \"repositories\": [\n        {\n            \"type\": \"path\",\n            \"url\": \"/PATH/TO/PROJECTS/host/packages/Ajthinking/PHPFileManipulator\"\n        }\n    ],\n```\nThen,\n```bash\ncomposer require ajthinking/php-file-manipulator @dev\nphp artisan vendor:publish --provider=\"PHPFileManipulator\\ServiceProvider\"\n```\nFinally in host root run\n```bash\nvendor/phpunit/phpunit/phpunit packages/Ajthinking/PHPFileManipulator/tests\n```\n\n### Roadmap\nPRs and issues are welcome. Have a look at the [Trello board](https://trello.com/b/1M2VRnoQ/php-file-manipulator) for planned features.\n\n\u003ca href=\"https://trello.com/b/1M2VRnoQ/php-file-manipulator\"\u003e\n    \u003cimg src=\"docs/img/trello.png\" width=\"600px\"\u003e\n\u003c/a\u003e\n\n## License\nMIT\n\n\n## Acknowledgements\n* Built with [nikic/php-parser](https://github.com/nikic/php-parser)\n* PSR Printing fixes borrowed from [tcopestake/PHP-Parser-PSR-2-pretty-printer](https://github.com/tcopestake/PHP-Parser-PSR-2-pretty-printer)\n\n\n## Like this package?\n\u003ca href=\"https://github.com/ajthinking/php-file-manipulator/stargazers\" \u003eStar it :star: \u003c/a\u003e\n\n[Say hi: @ajthinking :gem:](https://twitter.com/ajthinking)\n\n[Github Sponsors :octocat::heart:](https://github.com/sponsors/ajthinking)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fajthinking%2Fphpfilemanipulatormedia","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fajthinking%2Fphpfilemanipulatormedia","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fajthinking%2Fphpfilemanipulatormedia/lists"}