Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ composer.lock

# PHPUnit coverage file
clover.xml

.vscode
69 changes: 4 additions & 65 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,9 @@
PHP Cron Scheduler
==

[![Latest Stable Version](https://poser.pugx.org/peppeocchi/php-cron-scheduler/v/stable)](https://packagist.org/packages/peppeocchi/php-cron-scheduler) [![License](https://poser.pugx.org/peppeocchi/php-cron-scheduler/license)](https://packagist.org/packages/peppeocchi/php-cron-scheduler) [![Build Status](https://travis-ci.org/peppeocchi/php-cron-scheduler.svg)](https://travis-ci.org/peppeocchi/php-cron-scheduler) [![Coverage Status](https://coveralls.io/repos/github/peppeocchi/php-cron-scheduler/badge.svg?branch=v2.x)](https://coveralls.io/github/peppeocchi/php-cron-scheduler?branch=v2.x) [![StyleCI](https://styleci.io/repos/38302733/shield)](https://styleci.io/repos/38302733) [![Total Downloads](https://poser.pugx.org/peppeocchi/php-cron-scheduler/downloads)](https://packagist.org/packages/peppeocchi/php-cron-scheduler)

This is a framework agnostic cron jobs scheduler that can be easily integrated with your project or run as a standalone command scheduler.
The idea was originally inspired by the [Laravel Task Scheduling](http://laravel.com/docs/5.1/scheduling).

## Installing via Composer
The recommended way is to install the php-cron-scheduler is through [Composer](https://getcomposer.org/).
Please refer to [Getting Started](https://getcomposer.org/doc/00-intro.md) on how to download and install Composer.

After you have downloaded/installed Composer, run

`php composer.phar require peppeocchi/php-cron-scheduler`

or add the package to your `composer.json`
```json
{
"require": {
"peppeocchi/php-cron-scheduler": "3.*"
}
}
```
Split from peppeocchi/php-cron-scheduler

Scheduler V3 requires php >= 7.1, please use the [v2 branch](https://github.com/peppeocchi/php-cron-scheduler/tree/v2.x) for php versions < 7.1.
Scheduler requires php >= 7.4

## How it works

Expand Down Expand Up @@ -245,12 +225,12 @@ $scheduler->call(function () {
})->output('my_file.log');
```

### Send output to email/s
### Send output to email/s (UNTESTED)

You can define one or multiple email addresses where you want the output of your script/command/function execution to be sent to.
In order for the email to be sent, the output of the job needs to be sent first to a file.
In fact, the files will be attached to your email address.
In order for this to work, you need to install [swiftmailer/swiftmailer](https://github.com/swiftmailer/swiftmailer)
In order for this to work, you need to install [symfony/mailer](https://symfony.com/doc/current/mailer.html)

```php
$scheduler->php('script.php')->output([
Expand All @@ -262,47 +242,6 @@ $scheduler->php('script.php')->output([
]);
```

You can optionally customize the `Swift_Mailer` instance with a custom `Swift_Transport`.
You can configure:
- `subject` - The subject of the email sent
- `from` - The email address set as sender
- `body` - The body of the email
- `transport` - The transport to use. For example if you want to use your gmail account or any other SMTP account. The value should be an instance of `Swift_Tranport`
- `ignore_empty_output` - If this is set to `true`, jobs that return no output won't fire any email.

The configuration can be set "globally" for all the scheduler commands, when creating the scheduler.

```php
$scheduler = new Scheduler([
'email' => [
'subject' => 'Visitors count',
'from' => 'cron@email.com',
'body' => 'This is the daily visitors count',
'transport' => Swift_SmtpTransport::newInstance('smtp.gmail.com', 465, 'ssl')
->setUsername('username')
->setPassword('password'),
'ignore_empty_output' => false,
]
]);
```

Or can be set on a job per job basis.

```php
$scheduler = new Scheduler();

$scheduler->php('myscript.php')->configure([
'email' => [
'subject' => 'Visitors count',
]
]);

$scheduler->php('my_other_script.php')->configure([
'email' => [
'subject' => 'Page views count',
]
]);
```

### Schedule conditional execution

Expand Down
20 changes: 12 additions & 8 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"name": "peppeocchi/php-cron-scheduler",
"name": "adamz01h/php-cron-scheduler",
"description": "PHP Cron Job Scheduler",
"license": "MIT",
"keywords": ["cron job", "scheduler"],
"keywords": ["cron job", "scheduler", "windows"],
"authors": [
{
"name": "Giuseppe Occhipinti",
Expand All @@ -13,20 +13,24 @@
"email": "carsten@carstenwindler.de",
"homepage": "http://carstenwindler.de",
"role": "Contributor"
},
{
"name": "adamz01h",
"role": "Contributor"
}
],
"minimum-stability": "dev",
"require": {
"php": "^7.1",
"dragonmantank/cron-expression": "^2.3"
"php": ">=7.4",
"dragonmantank/cron-expression": "^3.5"
},
"require-dev": {
"phpunit/phpunit": "~5.7",
"satooshi/php-coveralls": "^1.0",
"swiftmailer/swiftmailer": "~5.4 || ^6.0"
"phpunit/phpunit": "^9.5",
"php-coveralls/php-coveralls": "^1.0",
"symfony/mailer": "~5.4 || ^6.0"
},
"suggest": {
"swiftmailer/swiftmailer": "Required to send the output of a job to email address/es (~5.4 || ^6.0)."
"symfony/mailer": "Required to send the output of a job to email address/es"
},
"autoload": {
"psr-4": {
Expand Down
45 changes: 25 additions & 20 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -1,28 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="./vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false">
<phpunit
backupGlobals="false"
backupStaticAttributes="false"
bootstrap="./vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
>
<testsuites>
<testsuite name="Scheduler Test Suite">
<directory>./tests/</directory>
</testsuite>
</testsuites>

<php>
<env name="APP_ENV" value="testing"/>
<env name="APP_ENV" value="testing" />
</php>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory>src/GO</directory>
</whitelist>
</filter>
<logging>
<log type="coverage-clover" target="clover.xml"/>
</logging>
</phpunit>

<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">src/GO</directory>
</include>

<report>
<clover outputFile="clover.xml" />
</report>
</coverage>

</phpunit>
49 changes: 39 additions & 10 deletions src/GO/Job.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php namespace GO;

//Should work in linux and windows systems
use DateTime;
use Exception;
use InvalidArgumentException;
Expand Down Expand Up @@ -193,7 +194,7 @@ public function getId()
* @param DateTime $date
* @return bool
*/
public function isDue(DateTime $date = null)
public function isDue(?DateTime $date = null)
{
// The execution time is being defaulted if not defined
if (! $this->executionTime) {
Expand Down Expand Up @@ -257,16 +258,25 @@ public function canRunInBackground()
* @param callable $whenOverlapping A callback to ignore job overlapping
* @return self
*/
public function onlyOne($tempDir = null, callable $whenOverlapping = null)
public function onlyOne($tempDir = null, ?callable $whenOverlapping = null)
{
if ($tempDir === null || ! is_dir($tempDir)) {
$tempDir = $this->tempDir;
}

$this->lockFile = implode('/', [
trim($tempDir),
trim($this->id) . '.lock',
]);
if(file_exists('/dev/null')){
//linux systems
$this->lockFile = implode('/', [
trim($tempDir),
trim($this->id) . '.lock',
]);
}else{
//windows systems need back slashes for file paths
$this->lockFile = implode('\\', [
trim(str_replace('/', '\\', $tempDir)),
trim($this->id) . '.lock',
]);
}

if ($whenOverlapping) {
$this->whenOverlapping = $whenOverlapping;
Expand Down Expand Up @@ -303,8 +313,15 @@ public function compile()

// Add the boilerplate to redirect the output to file/s
if (count($this->outputTo) > 0) {
$compiled .= ' | tee ';
$compiled .= $this->outputMode === 'a' ? '-a ' : '';
if(file_exists('/dev/null')){
//linux systems
$compiled .= ' | tee ';
$compiled .= $this->outputMode === 'a' ? '-a ' : '';
}else{
//windows systems
$compiled .= ' ';
$compiled .= $this->outputMode === 'a' ? '>> ' : '> ';
}
foreach ($this->outputTo as $file) {
$compiled .= $file . ' ';
}
Expand All @@ -314,14 +331,26 @@ public function compile()

// Add boilerplate to remove lockfile after execution
if ($this->lockFile) {
$compiled .= '; rm ' . $this->lockFile;
if(file_exists('/dev/null')){
//linux systems
$compiled .= '; rm ' . $this->lockFile;
}else{
//windows systems
$compiled .= ' & del ' . $this->lockFile;
}
}

// Add boilerplate to run in background
if ($this->canRunInBackground()) {
// Parentheses are need execute the chain of commands in a subshell
// that can then run in background
$compiled = '(' . $compiled . ') > /dev/null 2>&1 &';
if(file_exists('/dev/null')){
//linux systems
$compiled = '(' . $compiled . ') > /dev/null 2>&1 &';
}else{
//windows systems
$compiled = '(' . $compiled . ') > NUL 2>&1';
}
}

return trim($compiled);
Expand Down
Loading