Git Product home page Git Product logo

phulp's Introduction

phulp

The task manager for php

Latest Stable Version Total Downloads Latest Unstable Version License Build Status

Why

Sometimes I need a tool like Gulp for my PHP projects, but I don't want to install npm only to install Gulp. I thought "I need something like Gulp, but in PHP". After a little research I found Phing, but it's not focused in minification and management for CSS/JS and related frontend stuff.

Well, I decided to write Phulp, the PHP port of Gulp! And a little curiosity: it's faster than Gulp.

PS: I made benchs using PHP 7

Documentation

Plugins

Like Gulp we also have plugins, and you also can create your own.

Available plugins you can find in the plugin section over the Phulp Page.

To make your plugin available in the Phulp plugin page, add the keyword "phulpplugin" in your composer.json file of your project, and don't forget to let a cool composer.json description.

And tag your github project with the tags "phulpplugin", and "phulp", to be searchable on github.

Usage

Install:
$ composer require --dev reisraff/phulp
Create your Phulpfile (the configuration file, that describes all your tasks):
<?php

use Phulp\Output as out;

// Define the default task
$phulp->task('default', function ($phulp) {
    out::outln(out::colorize('Arguments:', 'green'));
    out::outln(print_r($phulp->getArguments(), true));

    $phulp->start(['clean', 'iterate_src_folder', 'sync_command', 'async_command']);
    if ($phulp->getArgument('repeat-clean', false)) {
        out::outln(out::colorize('Repeating "clean"', 'green'));
        $phulp->start(['clean']);
    }
});

// Define the clean task
$phulp->task('clean', function ($phulp) {
    if (! file_exists('dist')) {
        mkdir('dist');
    }
    $phulp->src(['dist/*'])
        ->pipe($phulp->clean());
});

// Define the iterate_src_folder task
$phulp->task('iterate_src_folder', function ($phulp) {
    // Define the source folder
    $phulp->src(['src/*php'])
        ->pipe($phulp->iterate(function ($file) {
            out::outln(sprintf(
                '%s %s',
                out::colorize('Iterated ->', 'green'),
                out::colorize($file->getFullPath() . DIRECTORY_SEPARATOR . $file->getName(), 'blue')
            ));
        }))
        ->pipe($phulp->dest('dist/'));
});

// Define the sync_command task
$phulp->task('sync_command', function ($phulp) {
    $command = $phulp->exec(
        'sleep 1 && echo $MSG',
        [
            'env' => [
                'MSG' => 'Sync-command'
            ],
            'cwd' => '/tmp',
            'sync' => true, // defines sync,
            'quiet' => true,
            'onStdOut' => function ($line) { out::outln($line); },
            'onStdErr' => function ($line) { },
            'onFinish' => function ($exitCode, $stdOut, $stdErr) { },
        ]
    );

    $exitCode = $command->getExitCode();
    $stdout = $command->getStdout();
    $stderr = $command->getStderr();

    out::outln('done');
});

// Define the async_command task
$phulp->task('async_command', function ($phulp) {
    $command = $phulp->exec(
        'sleep 1 && echo $MSG',
        [
            'env' => [
                'MSG' => 'Async-command'
            ],
            'cwd' => '/tmp',
            'sync' => false, // defines async,
            'quiet' => false,
            'onStdOut' => function ($line) { },
            'onStdErr' => function ($line) { },
            'onFinish' => function ($exitCode, $stdOut, $stdErr) { },
        ]
    );

    out::outln('done');
});

// Define the watch task
$phulp->task('watch', function ($phulp) {
    // Phulp will watch 'src' folder
    $phulp->watch(
        $phulp->src(['src/*php']),
        function ($phulp, $distFile) {
            out::outln(sprintf(
                '%s %s',
                out::colorize('File Changed ->', 'green'),
                out::colorize($distFile->getFullPath() . DIRECTORY_SEPARATOR . $distFile->getName(), 'blue')
            ));
            $phulp->start(['default']);
        }
    );
});
Run:

Run the phulp over the Phulpfile directory

If you have not configured the bin-dir:

$ vendor/bin/phulp --help
$ vendor/bin/phulp # Will run the `default` task
$ vendor/bin/phulp --arg=repeat-clean:true # Will run the `default` task with the argument repeat-clean with value `true`
$ vendor/bin/phulp --autoload=/my/autoload/path/autoload.php # Will run the `default` task adding a alternative autoload php file
$ vendor/bin/phulp watch # Will run the `watch` task
The full documentation:

Docs

Example:

https://github.com/reisraff/phulp/blob/master/example/phulpfile.php

Run the example file:

$ composer install
$ cd example
$ ../bin/phulp
$ ../bin/phulp watch

Contributors Guide

Clone

$ git clone [email protected]:reisraff/phulp.git
$ cd phulp
$ composer install

Tests

First install the dependencies, and after you can run:

$ bin/phulp test

TODO

The "Issues" page from this repository is being used for TO-DO management.

Credits

@reisraff

phulp's People

Contributors

alexmsilva avatar carusogabriel avatar glensc avatar ina6ra avatar oliveiramiguel avatar raphaelstolt avatar reisraff avatar schlaefer avatar

Stargazers

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

Watchers

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

phulp's Issues

Phulp\Source: provider the basepath/real-relativepath/filename

_Basepath:_ Sometimes we need of the basepath of the file, for example to delete the directory.

_Real-Relativepath:_ The symfony finder if I am no wrong sometimes does not give the real-relativepath based in the direcories provided to Finder::in()

_Filename:_ Separate the filename from the path

"!" in glob pattern

Enhance the glob patter by using the "!" behavior.

like: "!src/**/.gitignore" (everything that is not .gitignore).

Adding separate files

Sometimes we need to add files in a certain order. Therefore, it would be good to be able to add seperate files not only directives.

Get rid of all the static stuff

I don't see any valid reason for static stuff (except for the Output class, maybe). Is there any particular reason you chose this not consequently object-oriented approach?

I already refactored a local clone to work object-oriented.
If you're interested in that, I could redo this in a fork, and open a pull request.

Key changes:

  • well, no static Phulp methods;
  • constructor inject an Output object into Phulp;
  • pass $this (i.e., the Phulp object) to each task callback;
  • refactor Watch: don't pass in $tasks (which you don't even need), but a (new) Phulp callback.

This way it is easier to write real unit test - which I'd be glad to help you with, BTW.

Another plus for testing would be using factories (for DistFile, Source and Watch) - but that's another story/issue.

// EDIT: This is how a PhulpFile.php could look like:

$phulp->task('default', function ($phulp) {
    $phulp->src(['src/'], '/php$/')
        ->pipe($phulp->iterate(function ($distFile) {
            echo $distFile->getName() . PHP_EOL;
        }));
});

How to pass variables to other tasks

I would like to know how to pass variables to other tasks.

$env = '';

$phulp->task('reset', function($phulp) {
  var_dump($env);
  // $phulp->exec([
  //   'command' => "phinx --ansi migrate{$env}"
  // ]);
});

$phulp->task('test', function($phulp) {
  $env = ' -e test';
  $phulp->start(['reset']);
});

$phulp->task('pro', function($phulp) {
  $env = ' -e production';
  $phulp->start(['reset']);
});

$env is NULL

$ phulp test
Starting task "test"
Starting task "reset"
NULL

How can I solve it?

Website not working

Error in console, angular undefined. Seems like you've missed including the script dependencies?

[PROPOSAL] - Upgrade phulp::exec

<?php

use Phulp\Output as out;

$phulp->task('async-command', function ($phulp) {
    $onStdOut = function ($tick, $stdIn) {
        // $tick @var string
        // $stdIn @var object stream

        // out::out($tick);

        if (-1 !== strpos($tick, 'Do you really want to do this? [y/n]')) {
            $stdIn->write('y' . PHP_EOL);
    };
    $onStdErr = function ($tick, $stdIn) {
        // $tick @var string
        // $stdIn @var object stream

        // out::err($tick);

        if (-1 !== strpos($tick, 'Write all output on file? [y/n]')) {
            $stdIn->write('y' . PHP_EOL);
        }
    };
    $onFinish = function ($sigInt, $stdOut, $stdErr) {
        // $sigInt @var int
        // $stdOut @var string
        // $stdErr @var string
        return;
    };

    // $result @var boolean
    $result = $phulp->exec(
        'ls -lah', // command
        [
            'cwd' => '/var/log', // default getcwd()

            // ENV vars, default = []
            'env' => [
                'ENVIRONMENT' => 'PROD'
            ],

            'quiet' => true // default=false, write stdout, and stderr by itselt
            'sync' => false // default=true
            'onStdOut' => $onStdOut, // handle tick
            'onStdErr' => $onStdErr, // handle tick
            'onFinish' => $onFinish, // handle sigInt, stdout, stderr
        ]
    );
});

$phulp->task('sync-command', function ($phulp) {
    $result = $phulp->exec('ls -lah');

    $sigInt = $result->getSigInt(); // $sigInt @var int
    $stdOut = $result->getStdOut(); // $stdOut @var string
    $stdErr = $result->getStdErr(); // $stdErr @var string
});

doctrine/collections >= 1.5 break support php 5.6

The current dependence doctrine/collections is specified as "^1.3". But this installs version 1.5.0, which breaks down the work with php 5.6. Since there is a hotfix "Use PHP 7 sintax to simplify code".

Gets the duality - phulp is declared as working with php 5.6, but does not really work.

Solution 1:
   In phulp, set the dependence on php 7.

Solution 2:
   In phulp, set the dependence on doctrine/collections as "1.3" (without ^).

Thank you in advance.

Outputs

Colorful output for info/warning/error.

_Info: When starts and finish a task and others infos (blue)
_Warning
: For warnings (orange)
_Error_: For errors (red)

[Proposal] Use phulp config file

I want to prepare and use phulp.json.
With phulp.json you can solve three problems.

Part 1

If there is no composer command or it is an alias it will result in an error

$ phulp run
sh: composer: command not found

If you have phulp.json you can set it without depending on composer command.

# phulp.json
{
  "PATH": "$PATH",
  "BASHRC_PATH": "$HOME/.bashrc",
  "VENDOR_DIR": "$HOME/.composer/vendor",
  "PHULP_ARGV_SIZE": 1
}

// bin/phulp

// $vendor = exec('composer config vendor-dir');
// $files[] = "{$vendor}/autoload.php";

$config = getcwd() . '/phulp.json';
if (file_exists($config)) {
    $json = file_get_contents($config);
    $json = json_decode($json, true);
    if (isset($json['VENDOR_DIR'])) {
        $vendor = exec("echo " . $json['VENDOR_DIR']);
        if($vendor) $files[] = "{$vendor}/autoload.php";
    }
}

Part 2

You can change the setting on the plugin or phulpfile side without depending on the main body.

// phulpfile.php

$phulp->task('default', function($phulp) {
  $shell = new \Phulp\Shell\Shell($phulp);
  $shell->exec([
    'command' => 'alias command',
    'env' => $shell->getConfig('BASHRC_PATH')
  ]);
});

Part 3

Sometimes I want to specify the number of arguments of the phulp command.

$ phulp db import empty
[22:09:25] Task "db" has finished in 2.9452 seconds
[22:09:25] The task "import" does not exists.

With phulp.json, you can specify the number of arguments of phulp command.

// src/Phulp.php

    public function run(array $tasks = ['default'])
    {
        if( isset($this->config['PHULP_ARGV_SIZE']) ) {
            $tasks = array_slice($tasks, 0, $this->config['PHULP_ARGV_SIZE']);
        }
        $this->start($tasks);
        $this->getLoop()->run();
    }

Thus...

I am glad if there is a function to use phulp.json.
I will send you a pull request if necessary.

Implementation uses the following code as it is.

Thank you.

Performance improvements

Hi! I've just started using phulp in the hope of removing node dependencies when building simple PHP projects. So glad I found this since it is exactly what I wanted for so long (especially paired with Asset Packagist). I've just published a bunch of plugins I've put together for a current project, several features commonly used for gulp plus one that makes it possible to pipe files to Assetic for preprocessing. Doing this I've noticed drastic performance differences between phulp and gulp and I believe it's mostly due to gulps parallelism and streaming paradigm.

After a bit of research, my suggestions for improving phulp is as follows (this is partially based on assumptions in the code base, I've looked through most of it but I may have missed something):

  1. Use globbing patterns as sources rather than a separately defined regex. Many beginners have a really hard to put together proper regex patterns and the minimatch patterns gulp uses are a lot simpler to understand. This project gets us very close for the same globbing features (only need to add parantheses, e.g. (jpg|png), to make it fully compatible): https://github.com/webmozart/glob

    The linked library has a glob matching feature (Glob::match) which could be used to exclude files from the source in case they are prefixed by an exclamation mark, e.g. '!**/.gitkeep'

  2. Implement threading and byte streams. Gulp's strength and performance comes from its use of streams. Usually parallel programming is implemented in PHP with the pthreads extension but it can be done without extensions through the amphp project. Then the pipe implementation could be reworked to handle streams and tasks could be run in parallel. The pipes could then (either by inheritance or method definitions) handle streams, buffered files, or wait until all files are buffered to process them in one batch command (probably not recommended but perhaps sometimes wanted). This would also allow splitting streams as is a quite common practice with gulp when you have specific preprocessing rules for some files.

  3. Make watch event-based. Using inotify it could be converted into listening for events rather than polling for changes in the filesystem. Since inotify is not usually packaged with default php installations we could check for the extension first and automatically select the poll-based approach whenever inotify is missing in the environment.

I might start looking at this when I find some time in case there would be interest in pursuing making phulp threaded? Would something like this be merged or is it not inline with the project's goals? I assume it would be since it's inspired by gulp, but would like confirmation first.

Thanks for a great project!

Remove the need to have PhulpFile class

I was thinking in remove the need to have PhulpFile class. Why haven't just a simple script calling Phulp mtehods?

For example:

<?php
//PhulpFile.php

Phulp::task('default', function() {
    Phulp::start(['clean']);

    Phulp::src(['src/'], '/php$/', false)
        ->pipe(Phulp::iterate(function ($distFile) {
            \Phulp\Output::out($distFile->getName(), 'blue');
        }))
        ->pipe(Phulp::dest('dist/'));
});

gh-pages

Add the stars and the number of downloads for each phulpplugin.

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.