Skip to content

Commit 7076f4b

Browse files
committed
Merge branch 'release/0.3.0'
2 parents 6809668 + 3ba7ec9 commit 7076f4b

File tree

113 files changed

+4923
-463
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

113 files changed

+4923
-463
lines changed

.travis.yml

+6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ php:
44
- 5.3
55
- 5.4
66
- 5.5
7+
- 5.6
8+
- hhvm
79

810
before_script:
911
- composer install
12+
13+
matrix:
14+
allow_failures:
15+
- php: hhvm # this should be the default, eh?

README.md

+135-34
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ Ruler
33

44
Ruler is a simple stateless production rules engine for PHP 5.3+.
55

6-
[![Build Status](https://secure.travis-ci.org/bobthecow/Ruler.png?branch=master)](http://travis-ci.org/bobthecow/Ruler)
6+
[![Package version](http://img.shields.io/packagist/v/ruler/ruler.svg)](https://packagist.org/packages/ruler/ruler)
7+
[![Build status](http://img.shields.io/travis/bobthecow/Ruler/develop.svg)](http://travis-ci.org/bobthecow/Ruler)
78

89

910
Ruler has an easy, straightforward DSL
@@ -12,8 +13,6 @@ Ruler has an easy, straightforward DSL
1213
... provided by the RuleBuilder:
1314

1415
```php
15-
<?php
16-
1716
$rb = new RuleBuilder;
1817
$rule = $rb->create(
1918
$rb->logicalAnd(
@@ -42,8 +41,6 @@ $rule->execute($context); // "Yay!"
4241
... you can use it without a RuleBuilder:
4342

4443
```php
45-
<?php
46-
4744
$actualNumPeople = new Variable('actualNumPeople');
4845
$rule = new Rule(
4946
new Operator\LogicalAnd(array(
@@ -75,8 +72,6 @@ Things you can do with your Ruler
7572
### Compare things
7673

7774
```php
78-
<?php
79-
8075
// These are Variables. They'll be replaced by terminal values during Rule evaluation.
8176

8277
$a = $rb['a'];
@@ -85,23 +80,80 @@ $b = $rb['b'];
8580
// Here are bunch of Propositions. They're not too useful by themselves, but they
8681
// are the building blocks of Rules, so you'll need 'em in a bit.
8782

88-
$a->greaterThan($b); // true if $a > $b
89-
$a->greaterThanOrEqualTo($b); // true if $a >= $b
90-
$a->lessThan($b); // true if $a < $b
91-
$a->lessThanOrEqualTo($b); // true if $a <= $b
92-
$a->equalTo($b); // true if $a == $b
93-
$a->notEqualTo($b); // true if $a != $b
94-
$a->contains($b); // true if in_array($b, $a) || strpos($b, $a) !== false
95-
$a->doesNotContain($b); // true if !in_array($b, $a) || strpos($b, $a) === false
96-
$a->sameAs($b); // true if $a === $b
97-
$a->notSameAs($b); // true if $a !== $b
83+
$a->greaterThan($b); // true if $a > $b
84+
$a->greaterThanOrEqualTo($b); // true if $a >= $b
85+
$a->lessThan($b); // true if $a < $b
86+
$a->lessThanOrEqualTo($b); // true if $a <= $b
87+
$a->equalTo($b); // true if $a == $b
88+
$a->notEqualTo($b); // true if $a != $b
89+
$a->stringContains($b); // true if strpos($b, $a) !== false
90+
$a->stringDoesNotContain($b); // true if strpos($b, $a) === false
91+
$a->stringContainsInsensitive($b); // true if stripos($b, $a) !== false
92+
$a->stringDoesNotContainInsensitive($b); // true if stripos($b, $a) === false
93+
$a->startsWith($b); // true if strpos($b, $a) === 0
94+
$a->startsWithInsensitive($b); // true if stripos($b, $a) === 0
95+
$a->endsWith($b); // true if strpos($b, $a) === len($a) - len($b)
96+
$a->endsWithInsensitive($b); // true if stripos($b, $a) === len($a) - len($b)
97+
$a->sameAs($b); // true if $a === $b
98+
$a->notSameAs($b); // true if $a !== $b
9899
```
99100

100-
### Combine things
101+
102+
### Math even more things
101103

102104
```php
103-
<?php
105+
$c = $rb['c'];
106+
$d = $rb['d'];
107+
108+
// Mathematical operators are a bit different. They're not Propositions, so
109+
// they don't belong in rules all by themselves, but they can be combined
110+
// with Propositions for great justice.
111+
112+
$rb['price']
113+
->add($rb['shipping'])
114+
->greaterThanOrEqualTo(50)
115+
116+
// Of course, there are more.
117+
118+
$c->add($d); // $c + $d
119+
$c->subtract($d); // $c - $d
120+
$c->multiply($d); // $c * $d
121+
$c->divide($d); // $c / $d
122+
$c->modulo($d); // $c % $d
123+
$c->exponentiate($d); // $c ** $d
124+
$c->negate(); // -$c
125+
$c->ceil(); // ceil($c)
126+
$c->floor(); // floor($c)
127+
```
128+
129+
130+
### Reason about sets
131+
132+
```php
133+
$e = $rb['e']; // These should both be arrays
134+
$f = $rb['f'];
135+
136+
// Manipulate sets with set operators
137+
138+
$e->union($f);
139+
$e->intersect($f);
140+
$e->complement($f);
141+
$e->symmetricDifference($f);
142+
$e->min();
143+
$e->max();
144+
145+
// And use set Propositions to include them in Rules.
146+
147+
$e->containsSubset($f);
148+
$e->doesNotContainSubset($f);
149+
$e->setContains($a);
150+
$e->setDoesNotContain($a);
151+
```
152+
104153

154+
### Combine Rules
155+
156+
```php
105157
// Create a Rule with an $a == $b condition
106158
$aEqualsB = $rb->create($a->equalTo($b));
107159

@@ -123,27 +175,27 @@ $context = new Context(array(
123175
$eitherOne->evaluate($context);
124176
```
125177

126-
### Combine more things
127178

128-
```php
129-
<?php
179+
### Combine more Rules
130180

181+
```php
131182
$rb->logicalNot($aEqualsB); // The same as $aDoesNotEqualB :)
132183
$rb->logicalAnd($aEqualsB, $aDoesNotEqualB); // True if both conditions are true
133184
$rb->logicalOr($aEqualsB, $aDoesNotEqualB); // True if either condition is true
134185
$rb->logicalXor($aEqualsB, $aDoesNotEqualB); // True if only one condition is true
135186
```
136187

188+
137189
### `evaluate` and `execute` Rules
138190

139191
`evaluate()` a Rule with Context to figure out whether it is true.
140192

141193
```php
142-
<?php
143-
144-
$context = new Context(array('userName', function() {
145-
return isset($_SESSION['userName']) ? $_SESSION['userName'] : null;
146-
}));
194+
$context = new Context(array(
195+
'userName' => function() {
196+
return isset($_SESSION['userName']) ? $_SESSION['userName'] : null;
197+
}
198+
));
147199

148200
$userIsLoggedIn = $rb->create($rb['userName']->notEqualTo(null));
149201

@@ -155,10 +207,7 @@ if ($userIsLoggedIn->evaluate($context)) {
155207
If a Rule has an action, you can `execute()` it directly and save yourself a
156208
couple of lines of code.
157209

158-
159210
```php
160-
<?php
161-
162211
$hiJustin = $rb->create(
163212
$rb['userName']->equalTo('bobthecow'),
164213
function() {
@@ -169,6 +218,7 @@ $hiJustin = $rb->create(
169218
$hiJustin->execute($context); // "Hi, Justin!"
170219
```
171220

221+
172222
### Even `execute` a whole grip of Rules at once
173223

174224
```php
@@ -219,8 +269,6 @@ static values, or even code for lazily evaluating the Variables needed by your
219269
Rules.
220270

221271
```php
222-
<?php
223-
224272
$context = new Context;
225273

226274
// Some static values...
@@ -254,6 +302,18 @@ for a shipping price calculator?
254302
> If the current User has placed 5 or more orders, but isn't "really annoying",
255303
> give 'em free shipping.
256304
305+
```php
306+
$rb->create(
307+
$rb->logicalAnd(
308+
$rb['orderCount']->greaterThanOrEqualTo(5),
309+
$rb['reallyAnnoyingUsers']->doesNotContain($rb['userName'])
310+
),
311+
function() use ($shipManager, $context) {
312+
$shipManager->giveFreeShippingTo($context['user']);
313+
}
314+
);
315+
```
316+
257317

258318
Access variable properties
259319
--------------------------
@@ -264,7 +324,6 @@ Context Variable values. This can come in really handy.
264324
Say we wanted to log the current user's name if they are an administrator:
265325

266326
```php
267-
268327
// Reusing our $context from the last example...
269328

270329
// We'll define a few context variables for determining what roles a user has,
@@ -304,7 +363,7 @@ everything we might need to access in a rule, we can use VariableProperties, and
304363
their convenient RuleBuilder interface:
305364

306365
```php
307-
// We can skip over the Context Variable building above. We'll simply set our,
366+
// We can skip over the Context Variable building above. We'll simply set our,
308367
// default roles on the VariableProperty itself, then go right to writing rules:
309368

310369
$rb['user']['roles'] = array('anonymous');
@@ -335,6 +394,48 @@ If none of the above are true, it will return the default value for this
335394
VariableProperty.
336395

337396

397+
Add your own Operators
398+
----------------------
399+
400+
If none of the default Ruler Operators fit your needs, you can write your own! Just define
401+
additional operators like this:
402+
403+
```php
404+
405+
namespace My\Ruler\Operators;
406+
407+
use Ruler\Context;
408+
use Ruler\Operator\VariableOperator;
409+
use Ruler\Proposition;
410+
use Ruler\Value;
411+
412+
class ALotGreaterThan extends VariableOperator implements Proposition
413+
{
414+
public function evaluate(Context $context)
415+
{
416+
list($left, $right) = $this->getOperands();
417+
$value = $right->prepareValue($context)->getValue() * 10;
418+
419+
return $left->prepareValue($context)->greaterThan(new Value($value));
420+
}
421+
422+
protected function getOperandCardinality()
423+
{
424+
return static::BINARY;
425+
}
426+
}
427+
```
428+
429+
Then you can use them with RuleBuilder like this:
430+
431+
```php
432+
$rb->registerOperatorNamespace('My\Ruler\Operators');
433+
$rb->create(
434+
$rb['a']->aLotGreaterThan(10);
435+
);
436+
```
437+
438+
338439
But that's not all...
339440
---------------------
340441

composer.json

+2-3
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,13 @@
55
"homepage": "https://github.com/bobthecow/Ruler",
66
"license": "MIT",
77
"require": {
8-
"php": ">=5.3.0",
9-
"pimple/pimple": "1.0.*"
8+
"php": ">=5.3.0"
109
},
1110
"require-dev": {
1211
"phpunit/phpunit": "*"
1312
},
1413
"autoload": {
15-
"psr-0": {
14+
"psr-0": {
1615
"Ruler": "src",
1716
"Ruler\\Test": "tests"
1817
}

0 commit comments

Comments
 (0)