Code Monkey home page Code Monkey logo

php-file-manipulator's Introduction

PHPFile::manipulator(:fire::fire::fire:);

tests version Total Downloads License

Programatically 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.

Intro gif

Contents

Installation

composer require ajthinking/php-file-manipulator
php artisan vendor:publish --provider="PHPFileManipulator\ServiceProvider"

Usage

Quick start examples

use PHPFile;
use LaravelFile;

// find files with the query builder
PHPFile::in('database/migrations')
    ->where('extends', 'Migration')
  	->andWhere('className', 'like', 'Create')
    ->get()
    ->each(function($file) {
        // Do something
        $file->add()->use(['Database\CustomMigration'])
          ->extends('Database\CustomMigration')
          ->save();
    });

// add relationship methods
LaravelFile::load('app/User.php')
    ->hasMany(['App\Car'])
    ->hasOne(['App\Life'])
    ->belongsTo(['App\Wife'])
  	->methodNames()

// move User.php to a Models directory
PHPFile::load('app/User.php')
    ->namespace('App\Models')
    ->move('app/Models/User.php')

// install a package trait
PHPFile::load('app/User.php')
    ->addUseStatements('Package\Tool')
    ->addTraitUseStatement('Tool')
    ->save()

// add a route
LaravelFile::load('routes/web.php')
    ->addRoute('dummy', 'Controller@method')
    ->save()
    
// debug will write result relative to storage/.debug
LaravelFile::load('app/User.php')
    ->setClassName('Mistake')
    ->debug()

// add items to protected properties
LaravelFile::load('app/User.php')
    ->add()->fillable('message')
    ->add()->casts(['is_admin' => 'boolean'])
    ->add()->hidden('secret')    

// create new files from templates
LaravelFile::model('Beer')
    ->save()
LaravelFile::controller('BeerController')
    ->save()

// many in one go
LaravelFile::create('Beer', ['model', 'controller', 'migration'])

Template engine

Let'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.

<?php

/**
 * Optionally use FAKE names to silence IDE warnings
 */
use PHPFileManipulator\Support\FakeName; 
use PHPFileManipulator\Support\FakeName as ANY;
use PHPFileManipulator\Support\FakeName as ___TARGET_CLASS___;

/**
 * This is just a placeholder class where we can add our snippets
 */
class _ extends FakeName
{
    /**
    * ___DOC_BLOCK___
    */
    public function mySpecialMethod($arg)
    {
        $want = abs($arg);
        return $this->doSomethingWith(___TARGET_CLASS___::class, 'my template')
            ->use(ANY::thing(new static('you' . $want)));
    }    
}

Your snippet is then instantly available anywhere in your code:

use PHPFileManipulator\Support\Snippet;

// Get the snippet
Snippet::mySpecialMethod()

// Pass an array of replacement pairs to replace any handles:
Snippet::mySpecialMethod([
    '___DOC_BLOCK___' => 'Inserted with php-file-manipulator :)',
    '___TARGET_CLASS___' => 'App\Rocket'
]);

// Integrated example
PHPFile::load('app/User.php')
    ->addMethod(
        Snippet::mySpecialMethod([
            // replacement pairs ...
        ])
    )->save();

ℹ️ The Snippet class currently only supports templates on class methods.

Querying the Abstract Syntax Tree

As 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.

Example: how can we fetch explicit column names in a migration file?

LaravelFile::load('database/migrations/2014_10_12_000000_create_users_table.php')
    ->astQuery() // get a ASTQueryBuilder

    ->method()
        ->named('up')
    ->staticCall()
        ->where('class', 'Schema')
        ->named('create')
    ->args
    ->closure()
    ->stmts
    ->methodCall()
        ->where('var->name', 'table')
    ->args
	->value
	->value
	->get(); // exit ASTQueryBuilder, get a Collection        

The ASTQueryBuilder examines all possible paths and automatically terminates those that cant complete the query:

  • Three kinds of methods are provided (hinted with indentation in the code example)
    • Traversing (methods,staticCalls,firstArg ...)
    • Filtering (named, whereClass ...)
    • Resolving (getValue)
  • The ASTQueryBuilder relies entirely on nikic/php-parser. To understand this syntax better tinker with dd($file->ast().

LaravelFile available methods

To list all the available methods A-Z on LaravelFile, run:

php artisan file:api

image

To group methods by EndpointProvider use the --group flag:

php artisan file:api --group

Use the --provider flag to only view methods from a specific EndpointProvider, for instance IO:

php artisan file:api --provider=IO

Errors

If a file can't be parsed, a FileParseError will be thrown. This can happen if you try to explicitly load the file but also when performing queries matching problematic files.

To see all offending files run php artisan file:errors. To ignore files with problems, put them in config/php-file-manipulator.php -> ignored_paths.

Limitations / Missing features

In general this package assumes code to be parsed follows guidellines and conventions from PSR and Laravel. Some examples are listed below.

  • Can't use group use syntax (use Something\{X, Y};)

  • Assumes one class per file

  • Assumes no multiple/grouped property declarations (protected $a, $b = 1;)

Contributing

Development installation

The test suite requires that you are inside laravel application

laravel new host
cd host
git clone [email protected]:ajthinking/php-file-manipulator.git packages/Ajthinking/PHPFileManipulator

Add this to the host projects composer.json

    "repositories": [
        {
            "type": "path",
            "url": "/PATH/TO/PROJECTS/host/packages/Ajthinking/PHPFileManipulator"
        }
    ],

Then,

composer require ajthinking/php-file-manipulator @dev
php artisan vendor:publish --provider="PHPFileManipulator\ServiceProvider"

Finally in host root run

vendor/phpunit/phpunit/phpunit packages/Ajthinking/PHPFileManipulator/tests

Roadmap

PRs and issues are welcome. Have a look at the Trello board for planned features.

License

MIT

Acknowledgements

Like this package?

Star it ⭐

Say hi: @ajthinking 💎

Github Sponsors :octocat:❤️

php-file-manipulator's People

Contributors

ajthinking avatar septio avatar

Watchers

 avatar

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.