Skip to content

Commit

Permalink
Minor refactor to not use trait, extend readme
Browse files Browse the repository at this point in the history
  • Loading branch information
Zsolt Gál committed Jun 22, 2018
1 parent c802acc commit e05a9d0
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 52 deletions.
18 changes: 11 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,31 +24,35 @@ $ruleSet->add(
new Rule(
'aboutOneDay', // rule name, which would be used as a translation key
'23hour' // timespan, as a limit, without spaces between numerics and time. Check DefaultRuleSet for examples
),
),
new Formatter(
'days', // duration type, according to durations in \Technodelight\TimeAgo\Translation\SecondsDurationMap
'day', // duration type, according to durations in \Technodelight\TimeAgo\Translation\SecondsDurationMap
'floor' // strategy (function) to use for calculating the amount. In this example "days" are calculated with floor()
)
);
$timeAgo = new Technodelight\TimeAgo(
new DateTime('-1 hour'),
new Technodelight\TimeAgo\Translator(
new Technodelight\TimeAgo\Translation,
new Technodelight\TimeAgo\Translation( // this only needs an array as an input
[
'aboutOneDay' => 'About one day'
]
),
$ruleSet
)
);
$timeAgo->inWords(); // => 1 day ago
$timeAgo->inWords(); // => About one day
```

The example below shows how customisable is TimeAgo:
The example below shows how customisable is TimeAgo:

```
// with all dependencies injected:
$translationLoader = new Technodelight\TimeAgo\TranslationLoader; // can load built-in translations
$timeAgo = new Technodelight\TimeAgo(
new DateTime('-1 hour'), // static datetime
new Technodelight\TimeAgo\Translator( // this only needs an array as an input
new Technodelight\TimeAgo\Translator(
$translationLoader->load('hu') // use a fixed translation
)
);
Expand All @@ -60,7 +64,7 @@ $timeAgo->inWords(); // => körülbelül 1 órája
```
In the above example you can pass any of the translations supplied with this repository. All credits goes to Jimmi Westerberg and to the contributors of his repository.

By default, the `TimeAgo` uses the current system language as a guide to determine the required translation file, and it defaults to english if this information was not successfully resolved.
Of course, you can pass your own translation when required:

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

namespace Technodelight\TimeAgo\Translation;

class DefaultSecondsDurationMap implements SecondsDurationMap
{
/**
* Durations mapped to values in seconds
*
* @var array [['duration' => 123]]
*/
private $secondsDurationMap = array(
'sec' => 1,
'min' => 60,
'hour' => 3600,
'day' => 86400,
'month' => 2592000,
'year' => 31104000,
);

/**
* Converts a definition like "1day" into seconds
*
* @param string $human
* @return int
*/
public function inSeconds($human)
{
$parts = explode(' ', preg_replace('~-\s+~', '-', $human));
$seconds = 0;
foreach ($parts as $def) {
$operand = '+';
if (strpos($def, '-') !== false) {
$def = substr($def, strpos($def, '-') + 1);
$operand = '-';
}
sscanf($def, '%d%s', $amount, $duration);

$seconds += ($this->durationToSeconds($duration, $amount) * ($operand == '+' ? 1 : -1));
}

return $seconds;
}

/**
* Returns an amount for a duration type
*
* @param string $duration
* @return int
*/
public function amountForDuration($duration)
{
if (isset($this->secondsDurationMap[$duration])) {
return $this->secondsDurationMap[$duration];
}

return 0;
}

/**
* @param string $duration
* @param int $amount
* @return int
*/
private function durationToSeconds($duration, $amount)
{
return $amount * $this->secondsDurationMap[$duration];
}
}
23 changes: 16 additions & 7 deletions src/Technodelight/TimeAgo/Translation/Formatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,44 @@

class Formatter
{
use SecondsDurationMap;

/**
* @var string
*/
private $duration;

/**
*
* @var string
*/
private $strategy;

public function __construct($duration, $strategy = null)
/**
* @var SecondsDurationMap
*/
private $map;

/**
* @param string $duration
* @param callable $strategy a rounding function like 'round', 'floor' or 'ceil'
* @param SecondsDurationMap|null $map
*/
public function __construct($duration, $strategy = null, SecondsDurationMap $map = null)
{
$this->duration = $duration;
$this->strategy = $strategy ?: 'round';
$this->strategy = is_callable($strategy) ? $strategy : 'round';
$this->map = $map ?: new DefaultSecondsDurationMap;
}

/**
* @param int $seconds
* Return amount of seconds rounded according to configured strategy
*
* @param int|float $seconds
* @return int
*/
public function format($seconds)
{
return (int) call_user_func(
$this->strategy,
($seconds / $this->secondsDurationMap[$this->duration])
($seconds / $this->map->amountForDuration($this->duration))
);
}
}
23 changes: 19 additions & 4 deletions src/Technodelight/TimeAgo/Translation/Rule.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

class Rule
{
use SecondsDurationMap;

/**
* @var string
*/
Expand All @@ -16,22 +14,39 @@ class Rule
*/
private $timespan;

public function __construct($name, $timespan)
/**
* @param string $name the name of the rule, used as translation key
* @param string $timespan timespan definition, like '1hour 29sec'
* @param SecondsDurationMap|null $map
* @see SecondsDurationMap
*/
public function __construct($name, $timespan, SecondsDurationMap $map = null)
{
$map = $map ?: new DefaultSecondsDurationMap;
$this->name = $name;
$this->timespan = $this->inSeconds($timespan);
$this->timespan = $map->inSeconds($timespan);
}

/**
* @return string
*/
public function name()
{
return $this->name;
}

/**
* @return int
*/
public function timespan()
{
return $this->timespan;
}

/**
* @param int|float $seconds
* @return bool
*/
public function match($seconds)
{
return $seconds <= $this->timespan;
Expand Down
25 changes: 24 additions & 1 deletion src/Technodelight/TimeAgo/Translation/RuleSet.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,29 @@

class RuleSet
{
/**
* @var Rule[]
*/
private $rules = array();

/**
* Add new rule to the set with formatter
*
* @param Rule $rule the rule which determines where to "cut"
* @param Formatter $formatter the formatter which is responsible to render the "amount" of time
* @return void
*/
public function add(Rule $rule, Formatter $formatter)
{
$this->rules[] = array($rule, $formatter);
}

/**
* Finds a matching rule for an amount of time
*
* @param int $seconds
* @return Rule|null
*/
public function getMatchingRule($seconds)
{
$this->sortRulesByTimespan();
Expand All @@ -28,6 +44,13 @@ public function getMatchingRule($seconds)
return $lastRule;
}

/**
* Finds a (configured) formatter for a given rule
*
* @param Rule $ruleToFind
* @return Formatter
* @throws LogicException when no formatter found
*/
public function formatterForRule(Rule $ruleToFind)
{
foreach ($this->rules as $ruleFormatterPair) {
Expand All @@ -37,7 +60,7 @@ public function formatterForRule(Rule $ruleToFind)
}
}

throw new LogicException('A formatter should have been available');
throw new LogicException(sprintf('A formatter for rule %s was not found', $ruleToFind->name()));
}

private function sortRulesByTimespan()
Expand Down
45 changes: 12 additions & 33 deletions src/Technodelight/TimeAgo/Translation/SecondsDurationMap.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,21 @@

namespace Technodelight\TimeAgo\Translation;

trait SecondsDurationMap
interface SecondsDurationMap
{
/**
* Durations mapped to values in seconds
* Converts a definition like "1day" into seconds
*
* @var array
* @param string $human
* @return int
*/
private $secondsDurationMap = array(
'sec' => 1,
'min' => 60,
'hour' => 3600,
'day' => 86400,
'month' => 2592000,
'year' => 31104000,
);
public function inSeconds($human);

private function inSeconds($human)
{
$parts = explode(' ', preg_replace('~-\s+~', '-', $human));
$seconds = 0;
foreach ($parts as $def) {
$operand = '+';
if (strpos($def, '-') !== false) {
$def = substr($def, strpos($def, '-') + 1);
$operand = '-';
}
sscanf($def, '%d%s', $amount, $duration);

$seconds += ($this->durationToSeconds($duration, $amount) * ($operand == '+' ? 1 : -1));
}

return $seconds;
}

private function durationToSeconds($duration, $amount)
{
return $amount * $this->secondsDurationMap[$duration];
}
/**
* Returns an amount for a duration type
*
* @param string $duration
* @return int
*/
public function amountForDuration($duration);
}

0 comments on commit e05a9d0

Please sign in to comment.