├── .github ├── CODEOWNERS ├── FUNDING.yml ├── dependabot.yml ├── workflows │ ├── run-tests.yml │ ├── craft-release.yaml │ └── set-milestone-on-pr.yaml ├── boring-cyborg.yml └── settings.yml ├── src ├── functions_include.php ├── ProcessOutcome.php └── functions.php ├── .dunitconfig ├── Makefile ├── LICENSE ├── composer.json ├── CONTRIBUTING.md └── README.md /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @WyriHaximus 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: WyriHaximus 2 | -------------------------------------------------------------------------------- /src/functions_include.php: -------------------------------------------------------------------------------- 1 | exitCode = $exitCode; 31 | $this->stderr = trim($stderr); 32 | $this->stdout = trim($stdout); 33 | } 34 | 35 | /** 36 | * @return int 37 | */ 38 | public function getExitCode() 39 | { 40 | return $this->exitCode; 41 | } 42 | 43 | /** 44 | * @return string 45 | */ 46 | public function getStderr() 47 | { 48 | return $this->stderr; 49 | } 50 | 51 | /** 52 | * @return string 53 | */ 54 | public function getStdout() 55 | { 56 | return $this->stdout; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wyrihaximus/react-child-process-promise", 3 | "description": "Wrapping ticks into a promise", 4 | "license": "MIT", 5 | "authors": [ 6 | { 7 | "name": "Cees-Jan Kiewiet", 8 | "email": "ceesjank@gmail.com", 9 | "homepage": "https://wyrihaximus.net/" 10 | } 11 | ], 12 | "require": { 13 | "php": "^7.0|^8.0", 14 | "react/child-process": "^0.6 || ^0.5 || ^0.4", 15 | "react/promise": "^2.7", 16 | "wyrihaximus/ticking-promise": "^1.5.2|^2.0" 17 | }, 18 | "require-dev": { 19 | "vectorface/dunit": "^2.0", 20 | "phpunit/phpunit": "^6.0||^9.0", 21 | "sebastian/comparator": "^1.2.4||^4.0||^2.0", 22 | "squizlabs/php_codesniffer": "^3.3.2" 23 | }, 24 | "autoload": { 25 | "psr-4": { 26 | "WyriHaximus\\React\\": "src/" 27 | }, 28 | "files": ["src/functions_include.php"] 29 | }, 30 | "autoload-dev": { 31 | "psr-4": { 32 | "WyriHaximus\\React\\Tests\\": "tests/" 33 | } 34 | }, 35 | "config": { 36 | "sort-packages": true 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /.github/boring-cyborg.yml: -------------------------------------------------------------------------------- 1 | labelPRBasedOnFilePath: 2 | "Documentation 📚": 3 | - README.md 4 | - CONTRIBUTING.md 5 | "Dependencies 📦": 6 | - Dockerfile* 7 | - composer.* 8 | - package.json 9 | - package-lock.json 10 | - yarn.lock 11 | "Docker 🐳": 12 | - Dockerfile* 13 | - .docker/**/* 14 | "Image 🖼": 15 | - "**/*.gif" 16 | - "**/*.jpg" 17 | - "**/*.jpeg" 18 | - "**/*.png" 19 | - "**/*.webp" 20 | "CSS 👩‍🎨": 21 | - "**/*.css" 22 | "HTML 👷‍♀️": 23 | - "**/*.htm" 24 | - "**/*.html" 25 | "NEON 🦹‍♂️": 26 | - "**/*.neon" 27 | "MarkDown 📝": 28 | - "**/*.md" 29 | "YAML 🍄": 30 | - "**/*.yml" 31 | - "**/*.yaml" 32 | "JSON 👨‍💼": 33 | - "**/*.json" 34 | "Go 🐹": 35 | - "**/*.go" 36 | "JavaScript 🦏": 37 | - "**/*.js" 38 | - package.json 39 | - package-lock.json 40 | - yarn.lock 41 | "PHP 🐘": 42 | - "**/*.php" 43 | - composer.* 44 | "Configuration ⚙": 45 | - .github/* 46 | "CI 🚧": 47 | - .github/workflows/* 48 | - .scrutinizer.yml 49 | "Templates 🌲": 50 | - "**/*.twig" 51 | - "**/*.tpl" 52 | "Helm ☸": 53 | - .helm/**/* 54 | "Tests 🧪": 55 | - tests/**/* 56 | "Source 🔮": 57 | - src/**/* 58 | 59 | labelerFlags: 60 | labelOnPRUpdates: true 61 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Pull requests are highly appreciated. Here's a quick guide. 4 | 5 | Fork, then clone the repo: 6 | 7 | git clone git@github.com:your-username/reactphp-child-process-promise.git 8 | 9 | Set up your machine: 10 | 11 | composer install 12 | 13 | Make sure the tests pass: 14 | 15 | make unit 16 | 17 | Make sure the tests pass on all supported PHP versions (requires docker): 18 | 19 | make dunit 20 | 21 | Make your change. Add tests for your change. Make the tests pass: 22 | 23 | make dunit && make unit 24 | 25 | Before committing and submitting your pull request make sure it passes PSR2 coding style, unit tests pass and pass on all supported PHP versions: 26 | 27 | make contrib 28 | 29 | Push to your fork and [submit a pull request][pr]. 30 | 31 | [pr]: https://help.github.com/articles/creating-a-pull-request/ 32 | 33 | At this point you're waiting on me. I like to at least comment on pull requests 34 | within a day or two. I may suggest some changes or improvements or alternatives. 35 | 36 | Some things that will increase the chance that your pull request is accepted: 37 | 38 | * Write tests. 39 | * Follow PSR2 (travis will also check for this). 40 | * Write a [good commit message][commit]. 41 | 42 | [commit]: http://chris.beams.io/posts/git-commit/ 43 | -------------------------------------------------------------------------------- /src/functions.php: -------------------------------------------------------------------------------- 1 | '', 23 | 'stdout' => '', 24 | ]; 25 | 26 | $process->on('exit', function ($exitCode) use ($deferred, &$buffers) { 27 | $deferred->resolve(new ProcessOutcome($exitCode, $buffers['stderr'], $buffers['stdout'])); 28 | }); 29 | 30 | \WyriHaximus\React\futurePromise($loop, $process)->then(function (Process $process) use ($loop, &$buffers) { 31 | $process->start($loop); 32 | if ($process->stderr instanceof ReadableStreamInterface) { 33 | $process->stderr->on('data', function ($output) use (&$buffers) { 34 | $buffers['stderr'] .= $output; 35 | }); 36 | } 37 | if ($process->stdout instanceof ReadableStreamInterface) { 38 | $process->stdout->on('data', function ($output) use (&$buffers) { 39 | $buffers['stdout'] .= $output; 40 | }); 41 | } 42 | }); 43 | 44 | return $deferred->promise(); 45 | } 46 | -------------------------------------------------------------------------------- /.github/workflows/craft-release.yaml: -------------------------------------------------------------------------------- 1 | name: Create Release 2 | env: 3 | MILESTONE: ${{ github.event.milestone.title }} 4 | on: 5 | milestone: 6 | types: 7 | - closed 8 | jobs: 9 | generate-changelog: 10 | name: Generate Changelog 11 | runs-on: ubuntu-latest 12 | outputs: 13 | changelog: ${{ steps.changelog.outputs.changelog }} 14 | steps: 15 | - name: Generate changelog 16 | uses: WyriHaximus/github-action-jwage-changelog-generator@v1 17 | id: changelog 18 | env: 19 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 20 | with: 21 | milestone: ${{ env.MILESTONE }} 22 | - name: Show changelog 23 | run: echo "${CHANGELOG}" 24 | env: 25 | CHANGELOG: ${{ steps.changelog.outputs.changelog }} 26 | create-release: 27 | name: Create Release 28 | needs: 29 | - generate-changelog 30 | runs-on: ubuntu-latest 31 | steps: 32 | - uses: actions/checkout@v1 33 | env: 34 | CHANGELOG: ${{ needs.generate-changelog.outputs.changelog }} 35 | - run: | 36 | echo -e "${MILESTONE_DESCRIPTION}\r\n\r\n${CHANGELOG}" > release-${{ env.MILESTONE }}-release-message.md 37 | cat release-${{ env.MILESTONE }}-release-message.md 38 | release_message=$(cat release-${{ env.MILESTONE }}-release-message.md) 39 | release_message="${release_message//'%'/'%25'}" 40 | release_message="${release_message//$'\n'/'%0A'}" 41 | release_message="${release_message//$'\r'/'%0D'}" 42 | echo "::set-output name=release_message::$release_message" 43 | id: releasemessage 44 | env: 45 | MILESTONE_DESCRIPTION: ${{ github.event.milestone.description }} 46 | CHANGELOG: ${{ needs.generate-changelog.outputs.changelog }} 47 | - name: Create Reference Release with Changelog 48 | uses: fleskesvor/create-release@feature/support-target-commitish 49 | env: 50 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 51 | with: 52 | tag_name: ${{ env.MILESTONE }} 53 | release_name: ${{ env.MILESTONE }} 54 | body: ${{ steps.releasemessage.outputs.release_message }} 55 | draft: false 56 | prerelease: false 57 | -------------------------------------------------------------------------------- /.github/workflows/set-milestone-on-pr.yaml: -------------------------------------------------------------------------------- 1 | name: Set Milestone 2 | on: 3 | pull_request: 4 | types: 5 | - assigned 6 | - opened 7 | - synchronize 8 | - reopened 9 | - edited 10 | - ready_for_review 11 | - review_requested 12 | jobs: 13 | set-milestone: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v1 17 | if: github.event.pull_request.milestone == null 18 | - name: 'Get Previous tag' 19 | if: github.event.pull_request.milestone == null 20 | id: previoustag 21 | uses: "WyriHaximus/github-action-get-previous-tag@master" 22 | env: 23 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 24 | - name: 'Get next minor version' 25 | if: github.event.pull_request.milestone == null 26 | id: semvers 27 | uses: "WyriHaximus/github-action-next-semvers@master" 28 | with: 29 | version: ${{ steps.previoustag.outputs.tag }} 30 | - name: 'Get Milestones' 31 | if: github.event.pull_request.milestone == null 32 | uses: "WyriHaximus/github-action-get-milestones@master" 33 | id: milestones 34 | env: 35 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 36 | - run: printf "::set-output name=number::%s" $(printenv MILESTONES | jq --arg MILESTONE $(printenv MILESTONE) '.[] | select(.title == $MILESTONE) | .number') 37 | if: github.event.pull_request.milestone == null 38 | id: querymilestone 39 | env: 40 | MILESTONES: ${{ steps.milestones.outputs.milestones }} 41 | MILESTONE: ${{ steps.semvers.outputs.minor }} 42 | - name: 'Create Milestone' 43 | if: github.event.pull_request.milestone == null && steps.querymilestone.outputs.number == '' 44 | id: createmilestone 45 | uses: "WyriHaximus/github-action-create-milestone@master" 46 | with: 47 | title: ${{ steps.semvers.outputs.minor }} 48 | env: 49 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 50 | - name: 'Select found or created Milestone' 51 | if: github.event.pull_request.milestone == null 52 | id: selectmilestone 53 | run: | 54 | if [ $(echo ${QUERY_NUMBER} | wc -c) -eq 1 ] ; then 55 | printf "::set-output name=number::%s" "${CREATED_NUMBER}" 56 | exit 0 57 | fi 58 | 59 | printf "::set-output name=number::%s" "${QUERY_NUMBER}" 60 | env: 61 | CREATED_NUMBER: ${{ steps.createmilestone.outputs.number }} 62 | QUERY_NUMBER: ${{ steps.querymilestone.outputs.number }} 63 | - name: 'Set Milestone' 64 | if: github.event.pull_request.milestone == null 65 | uses: "WyriHaximus/github-action-set-milestone@master" 66 | with: 67 | issue_number: ${{ github.event.pull_request.number }} 68 | milestone_number: ${{ steps.selectmilestone.outputs.number }} 69 | env: 70 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ReactPHP Child Process Promise 2 | [![Linux Build Status](https://travis-ci.org/WyriHaximus/reactphp-child-process-promise.png)](https://travis-ci.org/WyriHaximus/reactphp-child-process-promise) 3 | [![Latest Stable Version](https://poser.pugx.org/WyriHaximus/react-child-process-promise/v/stable.png)](https://packagist.org/packages/WyriHaximus/react-child-process-promise) 4 | [![Total Downloads](https://poser.pugx.org/WyriHaximus/react-child-process-promise/downloads.png)](https://packagist.org/packages/WyriHaximus/react-child-process-promise) 5 | [![Code Coverage](https://scrutinizer-ci.com/g/WyriHaximus/reactphp-child-process-promise/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/WyriHaximus/reactphp-child-process-promise/?branch=master) 6 | [![License](https://poser.pugx.org/WyriHaximus/react-child-process-promise/license.png)](https://packagist.org/packages/wyrihaximus/react-child-process-promise) 7 | [![PHP 7 ready](http://php7ready.timesplinter.ch/WyriHaximus/reactphp-child-process-promise/badge.svg)](https://travis-ci.org/WyriHaximus/reactphp-child-process-promise) 8 | 9 | Wrap a [ReactPHP child process](https://github.com/reactphp/child-process) in a promise, once the process ends the promise resolves with the exit code and `STDERR` and `STDOUT` buffers. 10 | 11 | ### Installation ### 12 | 13 | To install via [Composer](http://getcomposer.org/), use the command below, it will automatically detect the latest version and bind it with `^`. 14 | 15 | ``` 16 | composer require wyrihaximus/react-child-process-promise 17 | ``` 18 | 19 | ## Examples ## 20 | 21 | ```php 22 | \WyriHaximus\React\childProcessPromise($loop, new Process('uptime'))->then(function ($result) { 23 | var_export($result); 24 | /** 25 | * Example output: 26 | * WyriHaximus\React\ProcessOutcome::__set_state(array( 27 | * 'exitCode' => 0, 28 | * 'stderr' => 'Error messages will go in this buffer', 29 | * 'stdout' => 'Normal output will go in this buffer', 30 | * )) 31 | */ 32 | }); 33 | ``` 34 | 35 | For ready to use examples see the [examples](https://github.com/WyriHaximus/reactphp-child-process-promise/tree/master/examples) directory 36 | 37 | ## Contributing ## 38 | 39 | Please see [CONTRIBUTING](CONTRIBUTING.md) for details. 40 | 41 | ## License ## 42 | 43 | Copyright 2016 [Cees-Jan Kiewiet](http://wyrihaximus.net/) 44 | 45 | Permission is hereby granted, free of charge, to any person 46 | obtaining a copy of this software and associated documentation 47 | files (the "Software"), to deal in the Software without 48 | restriction, including without limitation the rights to use, 49 | copy, modify, merge, publish, distribute, sublicense, and/or sell 50 | copies of the Software, and to permit persons to whom the 51 | Software is furnished to do so, subject to the following 52 | conditions: 53 | 54 | The above copyright notice and this permission notice shall be 55 | included in all copies or substantial portions of the Software. 56 | 57 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 58 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 59 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 60 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 61 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 62 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 63 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 64 | OTHER DEALINGS IN THE SOFTWARE. 65 | -------------------------------------------------------------------------------- /.github/settings.yml: -------------------------------------------------------------------------------- 1 | repository: 2 | private: false 3 | has_issues: true 4 | has_wiki: false 5 | has_downloads: true 6 | default_branch: master 7 | allow_squash_merge: false 8 | allow_merge_commit: true 9 | allow_rebase_merge: false 10 | 11 | # Labels: define labels for Issues and Pull Requests 12 | labels: 13 | - name: "Dependencies 📦" 14 | color: 0025ff 15 | description: "Pull requests that update a dependency file" 16 | - name: "Image 🖼" 17 | color: 00ffff 18 | - name: "HTML 👷‍♀️" 19 | color: ffffff 20 | - name: "CSS 👩‍🎨" 21 | color: b3b3b3 22 | - name: "JavaScript 🦏" 23 | color: ffff00 24 | - name: "Go 🐹" 25 | color: 00ADD8 26 | - name: "JSON 👨‍💼" 27 | color: 00ADD8 28 | - name: "NEON 🦹‍♂️" 29 | color: CE3262 30 | - name: "MarkDown 📝" 31 | color: 000000 32 | - name: "YAML 🍄" 33 | color: ff1aff 34 | - name: "Templates 🌲" 35 | color: 009933 36 | - name: "Helm ☸" 37 | color: 091C84 38 | - name: "Tests 🧪" 39 | color: ffe6e6 40 | - name: "Source 🔮" 41 | color: e6ffe6 42 | - name: "Configuration ⚙" 43 | color: b3b3cc 44 | - name: "PHP 🐘" 45 | color: 8892BF 46 | description: "Hypertext Pre Processor" 47 | - name: "Docker 🐳" 48 | color: 0db7ed 49 | description: "Pull requests that relate to Docker" 50 | - name: "CI 🚧" 51 | color: ffff00 52 | - name: "Feature 🏗" 53 | color: 66ff99 54 | - name: "Documentation 📚" 55 | color: 6666ff 56 | - name: "Security 🕵️‍♀️" 57 | color: ff0000 58 | - name: "Hacktoberfest 🎃" 59 | color: 152347 60 | - name: "Bug 🐞" 61 | color: d73a4a 62 | description: "Something isn't working" 63 | oldname: bug 64 | - name: "Duplicate ♊" 65 | color: cfd3d7 66 | description: "This issue or pull request already exists" 67 | oldname: duplicate 68 | - name: "Enhancement ✨" 69 | color: a2eeef 70 | description: "New feature or request" 71 | oldname: enhancement 72 | - name: "Good First Issue" 73 | color: 7057ff 74 | description: "Good for newcomers" 75 | oldname: "good first issue" 76 | - name: "Help Wanted" 77 | color: 008672 78 | description: "Extra attention is needed" 79 | oldname: "help wanted" 80 | - name: Invalid 81 | color: e4e669 82 | description: "This doesn't seem right" 83 | oldname: invalid 84 | - name: "Question ❓" 85 | color: d876e3 86 | description: "Further information is requested" 87 | oldname: question 88 | - name: "Will not be fixed 🛑" 89 | color: ffffff 90 | description: "This will not be worked on" 91 | oldname: wontfix 92 | - name: "Sponsor Request ❤️" 93 | color: fedbf0 94 | description: "Issue/PR opened by sponsor" 95 | 96 | branches: 97 | - name: master 98 | protection: 99 | required_pull_request_reviews: 100 | required_approving_review_count: 1 101 | dismiss_stale_reviews: true 102 | require_code_owner_reviews: true 103 | # Required. Require status checks to pass before merging. Set to null to disable 104 | required_status_checks: 105 | # Required. Require branches to be up to date before merging. 106 | strict: true 107 | # Required. The list of status checks to require in order to merge into this branch 108 | contexts: [] 109 | # Required. Enforce all configured restrictions for administrators. Set to true to enforce required status checks for repository administrators. Set to null to disable. 110 | enforce_admins: true 111 | # Required. Restrict who can push to this branch. Team and user restrictions are only available for organization-owned repositories. Set to null to disable. 112 | restrictions: 113 | apps: [] 114 | users: [] 115 | teams: [] 116 | --------------------------------------------------------------------------------