Implement relative startdates *yay*

Fixes #18
This commit is contained in:
Tim Schumacher 2014-09-21 20:01:56 +02:00
parent d21c818e84
commit 33b63429ef
8 changed files with 148 additions and 82 deletions

View file

@ -36,7 +36,8 @@
"enko/ics": "~0.1", "enko/ics": "~0.1",
"doctrine/migrations": "dev-master", "doctrine/migrations": "dev-master",
"doctrine/doctrine-migrations-bundle": "dev-master", "doctrine/doctrine-migrations-bundle": "dev-master",
"jbroadway/urlify" : "~1.0" "jbroadway/urlify" : "~1.0",
"enko/relativedateparser" : "v0.2"
}, },
"require-dev": { "require-dev": {
"sensio/generator-bundle": "~2.3" "sensio/generator-bundle": "~2.3"

119
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"hash": "77745a3287830b815f677d20df33b385", "hash": "ce7476174febffa01f09dfba2d9e3bb5",
"packages": [ "packages": [
{ {
"name": "doctrine/annotations", "name": "doctrine/annotations",
@ -81,16 +81,16 @@
}, },
{ {
"name": "doctrine/cache", "name": "doctrine/cache",
"version": "v1.3.0", "version": "v1.3.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/doctrine/cache.git", "url": "https://github.com/doctrine/cache.git",
"reference": "e16d7adf45664a50fa86f515b6d5e7f670130449" "reference": "cf483685798a72c93bf4206e3dd6358ea07d64e7"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/doctrine/cache/zipball/e16d7adf45664a50fa86f515b6d5e7f670130449", "url": "https://api.github.com/repos/doctrine/cache/zipball/cf483685798a72c93bf4206e3dd6358ea07d64e7",
"reference": "e16d7adf45664a50fa86f515b6d5e7f670130449", "reference": "cf483685798a72c93bf4206e3dd6358ea07d64e7",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -106,7 +106,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "1.0.x-dev" "dev-master": "1.4.x-dev"
} }
}, },
"autoload": { "autoload": {
@ -119,17 +119,6 @@
"MIT" "MIT"
], ],
"authors": [ "authors": [
{
"name": "Jonathan H. Wage",
"email": "jonwage@gmail.com",
"homepage": "http://www.jwage.com/",
"role": "Creator"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com",
"homepage": "http://www.instaclick.com"
},
{ {
"name": "Roman Borschel", "name": "Roman Borschel",
"email": "roman@code-factory.org" "email": "roman@code-factory.org"
@ -138,11 +127,17 @@
"name": "Benjamin Eberlei", "name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de" "email": "kontakt@beberlei.de"
}, },
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{ {
"name": "Johannes Schmitt", "name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com", "email": "schmittjoh@gmail.com"
"homepage": "http://jmsyst.com",
"role": "Developer of wrapped JMSSerializerBundle"
} }
], ],
"description": "Caching library offering an object-oriented API for many cache backends", "description": "Caching library offering an object-oriented API for many cache backends",
@ -151,7 +146,7 @@
"cache", "cache",
"caching" "caching"
], ],
"time": "2013-10-25 19:04:14" "time": "2014-09-17 14:24:04"
}, },
{ {
"name": "doctrine/collections", "name": "doctrine/collections",
@ -798,6 +793,42 @@
], ],
"time": "2014-07-30 23:43:46" "time": "2014-07-30 23:43:46"
}, },
{
"name": "enko/relativedateparser",
"version": "v0.2",
"source": {
"type": "git",
"url": "https://github.com/HackspaceJena/RelativeDateParser.git",
"reference": "0f1e587c652eac6c109c05637da9e6b5328c8564"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/HackspaceJena/RelativeDateParser/zipball/0f1e587c652eac6c109c05637da9e6b5328c8564",
"reference": "0f1e587c652eac6c109c05637da9e6b5328c8564",
"shasum": ""
},
"require": {
"symfony/config": "~2.5",
"symfony/translation": "~2.5"
},
"type": "library",
"autoload": {
"psr-0": {
"": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Tim Schumacher",
"email": "tim@bandenkrieg.hacked.jp"
}
],
"time": "2014-09-21 17:06:28"
},
{ {
"name": "incenteev/composer-parameter-handler", "name": "incenteev/composer-parameter-handler",
"version": "v2.1.0", "version": "v2.1.0",
@ -1308,22 +1339,22 @@
}, },
{ {
"name": "sensio/framework-extra-bundle", "name": "sensio/framework-extra-bundle",
"version": "v3.0.1", "version": "v3.0.2",
"target-dir": "Sensio/Bundle/FrameworkExtraBundle", "target-dir": "Sensio/Bundle/FrameworkExtraBundle",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sensiolabs/SensioFrameworkExtraBundle.git", "url": "https://github.com/sensiolabs/SensioFrameworkExtraBundle.git",
"reference": "dbc1e5aa830f3bf8063b29102add3c1e476d616e" "reference": "9b22aaee517e80aad3238ea0328458b6f964066f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sensiolabs/SensioFrameworkExtraBundle/zipball/dbc1e5aa830f3bf8063b29102add3c1e476d616e", "url": "https://api.github.com/repos/sensiolabs/SensioFrameworkExtraBundle/zipball/9b22aaee517e80aad3238ea0328458b6f964066f",
"reference": "dbc1e5aa830f3bf8063b29102add3c1e476d616e", "reference": "9b22aaee517e80aad3238ea0328458b6f964066f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"doctrine/common": "~2.2", "doctrine/common": "~2.2",
"symfony/framework-bundle": "~2.5" "symfony/framework-bundle": "~2.3"
}, },
"require-dev": { "require-dev": {
"symfony/expression-language": "~2.4", "symfony/expression-language": "~2.4",
@ -1351,9 +1382,7 @@
"authors": [ "authors": [
{ {
"name": "Fabien Potencier", "name": "Fabien Potencier",
"email": "fabien@symfony.com", "email": "fabien@symfony.com"
"homepage": "http://fabien.potencier.org",
"role": "Lead Developer"
} }
], ],
"description": "This bundle provides a way to configure your controllers with annotations", "description": "This bundle provides a way to configure your controllers with annotations",
@ -1361,7 +1390,7 @@
"annotations", "annotations",
"controllers" "controllers"
], ],
"time": "2014-05-22 23:27:44" "time": "2014-09-02 07:11:30"
}, },
{ {
"name": "sensiolabs/security-checker", "name": "sensiolabs/security-checker",
@ -1410,16 +1439,16 @@
}, },
{ {
"name": "swiftmailer/swiftmailer", "name": "swiftmailer/swiftmailer",
"version": "v5.2.1", "version": "v5.2.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/swiftmailer/swiftmailer.git", "url": "https://github.com/swiftmailer/swiftmailer.git",
"reference": "2b9af56cc676c338d52fca4c657e5bdff73bb7af" "reference": "e02f71a35436af4bd58a1bd90116089e632e29e1"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/2b9af56cc676c338d52fca4c657e5bdff73bb7af", "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/e02f71a35436af4bd58a1bd90116089e632e29e1",
"reference": "2b9af56cc676c338d52fca4c657e5bdff73bb7af", "reference": "e02f71a35436af4bd58a1bd90116089e632e29e1",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1445,13 +1474,11 @@
], ],
"authors": [ "authors": [
{ {
"name": "Fabien Potencier", "name": "Chris Corbyn"
"email": "fabien@symfony.com",
"homepage": "http://fabien.potencier.org",
"role": "Lead Developer"
}, },
{ {
"name": "Chris Corbyn" "name": "Fabien Potencier",
"email": "fabien@symfony.com"
} }
], ],
"description": "Swiftmailer, free feature-rich PHP mailer", "description": "Swiftmailer, free feature-rich PHP mailer",
@ -1460,7 +1487,7 @@
"mail", "mail",
"mailer" "mailer"
], ],
"time": "2014-06-13 11:44:54" "time": "2014-09-20 07:17:36"
}, },
{ {
"name": "symfony/assetic-bundle", "name": "symfony/assetic-bundle",
@ -1692,16 +1719,16 @@
}, },
{ {
"name": "symfony/symfony", "name": "symfony/symfony",
"version": "v2.5.3", "version": "v2.5.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/symfony.git", "url": "https://github.com/symfony/symfony.git",
"reference": "f077a238c781f845487a7c81fea8033ccd0e6a02" "reference": "3a369dddea56596df91977d8c2083e70784852f2"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/symfony/zipball/f077a238c781f845487a7c81fea8033ccd0e6a02", "url": "https://api.github.com/repos/symfony/symfony/zipball/3a369dddea56596df91977d8c2083e70784852f2",
"reference": "f077a238c781f845487a7c81fea8033ccd0e6a02", "reference": "3a369dddea56596df91977d8c2083e70784852f2",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1759,7 +1786,7 @@
"doctrine/data-fixtures": "1.0.*", "doctrine/data-fixtures": "1.0.*",
"doctrine/dbal": "~2.2", "doctrine/dbal": "~2.2",
"doctrine/orm": "~2.2,>=2.2.3", "doctrine/orm": "~2.2,>=2.2.3",
"egulias/email-validator": "1.1.0", "egulias/email-validator": "~1.2",
"ircmaxell/password-compat": "1.0.*", "ircmaxell/password-compat": "1.0.*",
"monolog/monolog": "~1.3", "monolog/monolog": "~1.3",
"ocramius/proxy-manager": ">=0.3.1,<0.6-dev", "ocramius/proxy-manager": ">=0.3.1,<0.6-dev",
@ -1802,7 +1829,7 @@
"keywords": [ "keywords": [
"framework" "framework"
], ],
"time": "2014-08-06 07:03:01" "time": "2014-09-03 09:51:48"
}, },
{ {
"name": "twig/extensions", "name": "twig/extensions",

View file

@ -17,6 +17,8 @@ use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Validator\Constraints\DateTime;
use enko\RelativeDateParser\RelativeDateParser;
class GenerateEventsCommand extends ContainerAwareCommand class GenerateEventsCommand extends ContainerAwareCommand
{ {
@ -44,18 +46,19 @@ class GenerateEventsCommand extends ContainerAwareCommand
$entities = $repo->findAll(); $entities = $repo->findAll();
foreach($entities as $entity) { foreach($entities as $entity) {
/** @var RepeatingEvent $entity */ /** @var RepeatingEvent $entity */
$period = new \DatePeriod($entity->nextdate,new \DateInterval($entity->repeating_pattern),$end); $next_date = is_null($entity->nextdate) ? new DateTime() : $entity->nextdate;
$parser = new RelativeDateParser($entity->repeating_pattern,$next_date,'de');
$event = null; $event = null;
foreach($period as $date) { while (($next_date = $parser->getNext()) < $end) {
/** @var \DateTime $date */ /** @var \DateTime $next_date */
$output->writeln(sprintf("Creating Event %s for %s",$entity->summary,$date->format('Y-m-d H:i'))); $output->writeln(sprintf("Creating Event %s for %s",$entity->summary,$next_date->format('Y-m-d H:i')));
$event = new Event(); $event = new Event();
$event->location = $entity->location; $event->location = $entity->location;
$event->startdate = $date; $event->startdate = $next_date;
if ($entity->duration > 0) { if ($entity->duration > 0) {
$duration = new \DateInterval("PT".$entity->duration.'H'); $duration = new \DateInterval("PT".$entity->duration.'H');
/** @var \DateTime $enddate */ /** @var \DateTime $enddate */
$enddate = clone $date; $enddate = clone $next_date;
$enddate->add($duration); $enddate->add($duration);
$entity->enddate = $enddate; $entity->enddate = $enddate;
} }
@ -72,10 +75,10 @@ class GenerateEventsCommand extends ContainerAwareCommand
} }
$entityManager->persist($event); $entityManager->persist($event);
$entityManager->flush(); $entityManager->flush();
$parser->setNow($next_date);
} }
if (!is_null($event)) { if (!is_null($event)) {
$entity->nextdate = $event->startdate; $entity->nextdate = $event->startdate;
$entity->nextdate->add(new \DateInterval($entity->repeating_pattern));
$entityManager->persist($entity); $entityManager->persist($entity);
$entityManager->flush(); $entityManager->flush();
} }

View file

@ -295,4 +295,15 @@ class RepeatingEventController extends Controller
); );
} }
/**
* Deletes a Event entity.
*
* @Route("/wiederholungsmuster", name="repeating_patterns")
* @Method({"GET", "POST"})
* @Template("CalciferBundle:RepeatingEvent:repeating_patterns.html.twig")
*/
public function repeatingPatternsHelpAction(Request $request) {
return null;
}
} }

View file

@ -84,17 +84,4 @@ class RepeatingEvent extends BaseEntity
* ) * )
*/ */
protected $tags = []; protected $tags = [];
public function getFormatedRepeatPattern() {
switch($this->repeating_pattern) {
case 'P7D':
return 'Wöchentlich';
case 'P14D':
return 'Alle 2 Wochen';
case 'P1M':
return 'Monatlich';
default:
return $this->repeating_pattern;
}
}
} }

View file

@ -44,7 +44,7 @@
{{ entity.nextdate.format('Y-m-d H:i') }} {{ entity.nextdate.format('Y-m-d H:i') }}
</td> </td>
<td> <td>
{{ entity.getFormatedRepeatPattern() }} {{ entity.repeating_pattern }}
</td> </td>
<td> <td>
<a href="{{ path('repeating_event_edit', {'slug':entity.slug}) }}">Bearbeiten</a> | <a href="{{ path('repeating_event_edit', {'slug':entity.slug}) }}">Bearbeiten</a> |

View file

@ -38,23 +38,23 @@
</div> </div>
<div class="field"> <div class="field">
<label class="control-label required" for="event_duration">Wiederholungsmuster</label> <label class="control-label required" for="event_duration">Terminwiederholungsmuster</label>
<div class="ui left labeled input"> <div class="ui left labeled input attached-label">
<div class="ui dropdown selection fluid"> <input type="text"
<input name="repeating_pattern" type="hidden" value="{{ entity.repeating_pattern|default('') }}"> id="repeating_pattern"
name="repeating_pattern"
value="{{ entity.repeating_pattern|default('') }}"
required="required"
maxlength="255"
class="form-control">
<div class="default text">Bitte wähle einen Wert aus</div>
<i class="dropdown icon"></i>
<div class="menu">
<div class="item" data-value="P7D">Wöchentlich</div>
<div class="item" data-value="P14D">Jede 2. Woche</div>
<div class="item" data-value="P1M">Monatlich</div>
</div>
<div class="ui corner label"> <div class="ui corner label">
<i class="icon asterisk"></i> <i class="icon asterisk"></i>
</div> </div>
<div class="ui bottom attached label">
Gebe hier ein <a href="{{ path("repeating_patterns") }}">Wiederholungsmuster</a> an.
</div> </div>
</div> </div>

View file

@ -0,0 +1,37 @@
{% extends 'CalciferBundle::layout.html.twig' %}
{% block css %}
{% stylesheets filter="compass"
"@CalciferBundle/Resources/assets/css/events.scss" %}
<link rel="stylesheet" href="{{ asset_url }}"/>
{% endstylesheets %}
{% endblock %}
{% block javascripts %}
{% javascripts
"@CalciferBundle/Resources/assets/js/events.js" %}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
{% endblock %}
{% block body -%}
<div class="ui one column page grid title">
<div class="ui column">
<h1 class="ui header">
Wiederholungsmuster
</h1>
</div>
</div>
<div class="ui one column page grid segment">
<div class="ui column">
<p>Es gibt 2 verschiedene Wiederholungsmustertypen. Feste Termine oder Interval Termine.</p>
<p>Der erste definiert sich dadurch das der Termin immer an einem bestimmten Tag im Monat passieren soll. Das Hackspace-Plenum findet z.B. am <code>Zweiten Freitag des Monats</code> statt. Die Sicherheitssprechstunde findet immer am <code>Ersten Dienstag des Monats</code> statt. Anhand dieser Beispiele sollte eigentlich klar sein wie dieses Wiederholungsmuster funktioniert:</p>
<p>An erster stelle definiert man die Woche: Erster, Zweiter, Dritter, Letzter (In manchen Fällen kann Dritter und Letzter auch identisch sein).</p>
<p>An zweiter stelle definiert man den Wochentag: Montag, Dienstag, Mitwoch usw.</p>
<p>An letzter Stelle steht noch pro Forma „des Monats“</p>
<p>Der zweite Wiederholungstyp ist für regelmäßige Termine wie z.B. die Elektrorunde gedacht, die <code>Alle 7 Tage</code>. Für die Brettspielerei würde man <code>Alle 2 Wochen</code> schreiben.</p>
</div>
</div>
{% endblock %}