The Versioning
module provides a Repository API.
Architecture
Versioning\RepositoryManager
holds various repositories
Versioning\RepositoryService
holds a repository of type Versioning\Entity\RepositoryInterface
and multiple revisions of type Versioning\Entity\RevisionInterface
Versioning\Entity\RepositoryInterface
must be implemented by Models/Entities that will be used as a repository
Versioning\Entity\RevisionInterface
must be implemented by Models/Entities that will be used as a Revision
Changes are not persistent! That means, an ObjectManager needs to take care of it!
Setup
Repository.php
class Repository implements \Versioning\Entity\RepositoryInterface
{
// ...
}
Revision.php
class Revision implements \Versioning\Entity\RevisionInterface
{
// ...
}
Usage
Declare a repository
$repository = new Repository();
$serviceManager->get('Versioning\RepositoryManager')->addRepository($repository);
// Store changes in the database
$entityManager->persist($repository);
$entityManager->flush();
Fetch the RepositoryService
$repositoryService = $serviceManager->get('Versioning\RepositoryManager')->getRepository($repository);
Add a revision
$revision = new Revision();
$revision->setId(2);
$revision->setContent('Testinhalt');
$repositoryService->addRevision($revision);
// Store changes in the database
$entityManager->persist($revision);
$entityManager->flush();
Find a revision
$repositoryService->getRevision(2);
Check out a revision
$repositoryService->checkoutRevision(2);
// Store changes in the database
$entityManager->persist($repositoryService->getRepository());
$entityManager->flush();
Get the current revision
$revision = $repositoryService->getCurrentRevision();
Get the latest revision
$revision = $repositoryService->getHead();
Remove a revision from the repository
$revision = $repositoryService->getRevision(2);
$repositoryService->removeRevision(2);
// Store changes in the database
$entityManager->remove(revision);
$entityManager->flush();
The Uuid
module provides "universal unique ids" for any object.
Architecture
UUid\Manager\UUidManager implements UUid\Manager\UUidManagerInterface
: The Manager used for finding and creating uuids.
UUid\Entity\Uuid implements Uuid\Entity\UuidInterface
: The Entity stored in the uuid table.
UUid\Entity\UuidEntity implements Uuid\Entity\UuidHolder
: An Entitiy that has a uuid.
// Der ServiceManager kennt UUid\Manager\UUidManager
.
The ServiceManager knows about UUid\Manager\UUidManager
.
// #### Achtung
Warning
$uuidManager->create()
flushes the `ObjectManager due to restrictions in Doctrine!
Setup
Consider blog entries that have Uuids.
BlogPost.php
class BlogPost extends UuidEntity {
// ...
}
Create a new BlogPost
First way
$blogPost = new BlogPost();
$uuidManager->injectUuid($blogPost);
$uuidManager->getObjectManager()->flush();
Second way
$blogPost = new BlogPost();
$uuid = $uuidManager->create();
$uuidManager->injectUuid($blogPost, $uuid);
$uuidManager->getObjectManager()->flush();
Third way
class BlogPost extends UuidEntity{
public function __construct(){
$this->setUuid(new Uuid());
}
}
$blogPost = new BlogPost();
$this->getObjectManager()->persist($blogPost->getUuid());
$this->getObjectManager()->persist($blogPost);
$this->getObjectManager()->flush();
Access the uuid
Access the uuid hash
echo $blogPost->getUuid();
The User
module takes care of everything related to users.
Architecture
UserManager
holds the User
s
UserService
hold the entity
User
the entity
Setup
No setup required.
Get the current session's user
$user = $userManager->getUserFromRequest();
if(!$user){
echo "not logged in";
} else {
echo "hello ".$user->getUsername();
}
Create a User
$user = $userManager->createUser(array(
'usename' => 'Richard Stallman',
'password' => 'foaijwf293foa0wf23',
//..
));
$userManager->getObjectManager()->flush();
Find a User
// by user id
$user = $userManager->getUser(1);
// by username
$user = $userManager->findUserByUsername('foobar');
// by email
$user = $userManager->findUserByUsername('foo@bar.de');
By user Id
$user = $userManager->getUser(1);
By username
$user = $userManager->findUserByUsername('foobar');
By email
$user = $userManager->findUserByUsername('foo@bar.de');
The Term
module manages words which may be used by the `Taxonomy˚.
Architecture
TermManager
manages Term
s
TermService
holds a Term
Term
the entity
Setup
No setup required.
Find a Term
// by id
$term = $termManager->getTerm(1);
// by name
$term = $termManager->findTermByName('foobar');
// by slug
$term = $termManager->findTermBySlug('foobar');
// Das Taxonomymodul ist zuständig, um Taxonomien (zb. Kategorie, Land, Lehrplan, ...) zu verwalten.
// Die Datenstruktur ist ein Baum wobei es nur eine Wurzel geben sollte (um die Taxonomien zentral verwalten zu können), jeder Knotenpunkt kann einen konfigurierbaren Typen haben.
The Taxonomy
module manages taxonomies, like "category", "country", "curriculum"...
The underlying datastructure is a tree. Each node can be of a configurable type.
Architecture
// * SharedTaxonomyManager implements SharedTaxonomyManagerInterface
verwaltet die unterschiedlichen Taxonomy Typen (zb. Kategorie, Lehrplan), kann aber auch Terme über die ID finden
// * TaxonomyManager implements TaxonomyManagerInterface
stellt einen Taxonomy Typen da, welcher mehrere Terme hält.
// * TaxonomyService implements TaxonomyServiceInterface
ist ein einzelner Term, wobei es sich um einen Delegator bzw eine Fassade hält.
// * TaxonomyType implements TaxonomyTypeInterface
ist ein Taxonomy Typ (zb "category" oder "curriculum")
// * Taxonomy implements TaxonomyInterface
ist ein Taxonomy Typ in einer bestimmten Sprache (zb "category" & "de")
// * TaxonomyTerm implements TaxonomyTermInterface
ist der eigentliche Term, wobei die Inhalte des Terms speratat über das Term Modul gespeichert werden, um doppelte Inhalte zu vermeiden.
SharedTaxonomyManager implements SharedTaxonomyManagerInterface
manages various Taxonomy types (e.g. "category" oder "curriculum"), but can also find Term
s by their id.
TaxonomyManager implements TaxonomyManagerInterface
represents a Taxonomy
type, which manages multiple Term
s.
TaxonomyService implements TaxonomyServiceInterface
a delegator/Ffssade managing a single Term
TaxonomyType implements TaxonomyTypeInterface
is a Taxonomy
type (e.g. "category" oder "curriculum")
Taxonomy implements TaxonomyInterface
is a Taxonomy
type in a given language (e.g. "category" & "en")
TaxonomyTerm implements TaxonomyTermInterface
is the actual Term
. The Term
's contents are stored seperately via the Term
module in order to avoid redundancy.
Configuration
module.config.php
return array(
'taxonomy' => array(
// define your associations here
'associations' => array(
// you can get the associated entities with $termService->getAssociated('foolinks');
'foolinks' => function (ServiceLocatorInterface $sm, $collection)
{
return $sm->get('FoobarService')->doSomething($collection);
}
),
// define your types here
'types' => array(
// type 'foo'
'foo' => array(
'options' => array(
// no associations are allowed. You can not use $termService->getAssociated('foolinks')!
'allowed_associations' => array(
),
// the only parent type allowed is 'root'. Note that you can't add foo to foo, as it is not an allowed parent type
'allowed_parents' => array(
'root',
),
// use custom templates
'templates' => array(
// use a custom template for the update view
'update' => 'taxonomy/taxonomy/update'
),
// radix disabled, you can't set parent_id to null!
'radix_enabled' => false
)
),
'bar' => array(
'options' => array(
// Associations are allowed. You can use $termService->getAssociated('foolinks')!
'allowed_associations' => array(
'foolinks'
),
// self-referencing is allowed here
'allowed_parents' => array(
'foo',
'bar'
),
'radix_enabled' => false
)
),
// this is the root, it should always be present
'root' => array(
'options' => array(
'radix_enabled' => true
)
),
)
),
);
Usage
Find a Taxonomy
// by id
$sharedTaxonomyManager->getTaxonomy(1);
// by name (type) and language
$sharedTaxonomyManager->findTaxonomyByName('foo', $languageService);
Find term via the SharedTaxonomyManager
$term = $sharedTaxonomyManager->getTerm(3);
echo $term->getId(); // outputs '3'
Find a Term via a TaxonomyManager
// by id
$term = $taxonomyManager->getTerm(3);
echo $term->getId(); // outputs '3'
// by parent
$ancestors = explode('/', 'path/to/term');
$term = $taxonomyManager->findTermByAncestors($ancestors);
echo $term->getName(); // outputs 'term'
Find the root(s) of a type.
Find all Terms of a type that do not have a parent or are of a different type then their parents.
$result = $taxonomyManager->getSaplings();
foreach($result as $term){
echo $term->getId();
}
Find related Terms
All children
$children = $termService->getChildren();
foreach($children as $term){
echo $term->getId();
}
All children of a specific type
$children = $termService->findChildrenByTaxonomyName('bar');
foreach($children as $term){
echo $term->getId();
}
Find parent
$parent = $termService->getParent();
Associations
// Damit Assoziationen funktionieren, muss zunächst eine m:n Tabelle von der zu Assoziierenden Tabelle zu term_taxonomy
in der Datenbank angelegt werden. Außerdem muss Doctrine\ORM wissen, dass es diese Assoziation gibt, womit dem Entity ein neues Attribut verliehen werden muss.
Before a Association can be used, a m:n table must be created between term_taxonomy
and the table to be associated.
Additionally Doctrine\ORM
needs to know about the association.
Creating an Association
$termService = $sharedTaxonomyManager()->getTaxonomy('', $languageService)->getTerm(1)
$foolinks = $termService->associate('foolinks', $foolinkEntity);
echo $termService->isAssociated('foolinks', $foolinkEntity); // outputs: true
// make things persistent
$sharedTaxonomyManager()->getObjectManager()->flush();
Fetching assiciated elements
$termService = $sharedTaxonomyManager()->getTaxonomy('', $languageService)->getTerm(1)
$foolinks = $termService->getAssociated('foolinks');
Removing an association
$termService = $sharedTaxonomyManager()->getTaxonomy('', $languageService)->getTerm(1)
$foolinks = $termService->removeAssociation('foolinks', $foolinkEntity);
echo $termService->isAssociated('foolinks', $foolinkEntity); // outputs: false
// make things persistent
$sharedTaxonomyManager()->getObjectManager()->flush();
The ClassResolver
module finds concrete implementation of interfaces.
Configuration
module.config.php
return array(
'class_resolver' => array(
'FooInterface' => 'Foo',
'BarInterface' => 'Bar',
),
);
Resolve an interface
$classResolver = $serviceManager->get('ClassResolver\ClassResolver');
echo $classResolver->resolveClassName('FooInterface'); // 'Foo'
$classResolver = $serviceManager->get('ClassResolver\ClassResolver');
$bar = $classResolver->resolve('BarInterface'); // equivalent to `$bar = $serviceLocator->get('Bar');`
Events:
* createEntity.preFlush (Entity\Service\EntityServiceInterface $entity, array $params)
* createEntity.postFlush (Entity\Service\EntityServiceInterface $entity, array $params)
- deleteEntity.preFlush (Entity\Service\EntityServiceInterface $entity, array $params)
- deleteEntity.postFlush (Entity\Service\EntityServiceInterface $entity, array $params)
The Tokenizer
module manages the replacement of tokens in strings. For exmaple, hello {user}
becomes hello foobar
.
Usage
Set up the provider
To enable the replacement of tokens, you have to implement a provider for the data:
Provider.php
use Token\Provider\ProviderInterface;
use Token\Provider\AbstractProvider;
class TokenizerProvider extends AbstractProvider implements ProviderInterface
{
public function getData()
{
/**
*
* Tokens
*/
return array(
'title' => $this->getObject()->getTitle(),
'category' => $this->getObject()->getCategory()->getName(),
'id' => $this->getObject()->getId()
);
}
protected function validObject($object)
{
// Optimalerweise steht hier zum Beispiel: if( ! $object instanceOf FooInterface )
if (! is_object($object) )
throw new \InvalidArgumentException(sprintf('Expected PostInterface but got `%s`', get_class($object)));
}
}
Use the tokenizer
SomeService.php
class SomeService {
use \Token\TokenizerAwareTrait;
public function foobar($object)
{
$string = $this->getTokenizer()->transliterate('TokenizerProvider', $object, 'token/{id}-{title}');
echo $string; // output: token/1-test
}
}
The Alias
module beautifies the URLs. For example, /page/view/1
becomes /alias/page/association/finances
.
Features
- Decoupled: The
AliasManager
is decoupled from the rest of the software and can therefore be used more flexibly.
- Fallbacks: Fallbacks ensure that no problems arise during the allocation of aliases.
- AutoAlias: You can configure automatic aliasing.
- Listeners: Listeners make the creation of aliases easy by using automatic aliasing.
- UrlGenerating: The URL ViewHelper checks whether an alias already exists for the given URL and returns it.
- Aliases do not become obsolete: It is possible to define more than one alias for a given URL. Thus changing titles do not affect the availability of the content.
Create aliases
Thanks to Listeners, the creation of aliases is easy:
module.config.php
return array(
'alias_manager' => array(
'aliases' => array(
'page' => array(
// Siehe token guide
'tokenize' => 'page/{category}/{title}',
'provider' => 'TokenizerProvider',
'fallback' => 'page/{category}/{id}-{title}'
)
)
)
);
Listener.php
use Alias\Listener\AbstractListener;
use Zend\EventManager\Event;
class BlogControllerListener extends AbstractListener
{
/**
* Gets executed on 'onUpdate'
*
* @param Event $e
* @return null
*/
public function onUpdate(Event $e)
{
$page = $e->getParam('page');
$entity = $page->getEntity();
$language = $e->getParam('language');
$url = $e->getTarget()
->url()
->fromRoute('page/view', array(
'page' => $page->getId()
));
$this->getAliasManager()->autoAlias('page', $url, $entity, $language);
}
public function attachShared(\Zend\EventManager\SharedEventManagerInterface $events)
{
$this->listeners[] = $events->attach('SomeController', 'update', array(
$this,
'onUpdate'
));
}
}
SomeController.php
use Zend\Mvc\Controller\AbstractActionController;
class SomeController extends AbstractActionController
{
use \Language\Manager\LanguageManagerAwareTrait, \Common\Traits\ObjectManagerAwareTrait;
public function updateAction()
{
$data = $this->params()->fromPost();
// Siehe user guide
$language = $this->getLanguageManager()->getLanguageFromRequest();
$id = $data['id'];
$title = $data['title'];
$content = $data['content'];
$page = $this->updatePage($id, $title, $content);
$this->getEventManager()->trigger('update', $this, array(
'page' => $page,
'language' => $language
));
$this->getObjectManager()->flush();
return 'saved!';
}
}
Some content is published under a specific license.
Configuration
You can specify a default license for each language:
module.config.php
return [
'license_manager' => [
'defaults' =>
[
'de' => 'cc-by-sa-3.0',
'en' => 'cc-by-sa-3.0'
]
],
]
In this example, the manager will search the database for a license with language en
and title cc-by-sa-3.0
.
Usage
Implement LicenseAwareInterface
To use the LicenseManager
for injection of licenses, the Entity
or Model
has to implement the LicenseAwareInterface
.
Entity.php
class Entity implements LicenseAwareInterface
{
// ...
}
A concrete implementation (using Doctrine) might look as follows:
use Doctrine\ORM\Mapping as ORM;
// ORM definitions like ORM\Entity or ORM\Table
class Entity implements LicenseAwareInterface
{
/**
* @ORM\ManyToOne(targetEntity="License\Entity\LicenseInterface")
*/
protected $license;
public function getLicense()
{
return $this->license;
}
public function setLicense (LicenseInterface $license)
{
$this->license = $license;
return $this;
}
}
In this case, LicenseInterface
is not a mistake but will be resolved by Doctrine automatically.
Inject licenses
If you pass no additional parameters, the default license will be injected. In this case, the LicenseManager
fetches the current request language from the LanguageManager
:
class SomeService
{
use \License\Manager\LicenseManagerAwareTrait;
public function createEntity()
{
$entity = new Entity();
$this->getLicenseManager()->injectLicense($entity);
}
}
A custom license has to be passed as an additional parameter:
class SomeService
{
use \License\Manager\LicenseManagerAwareTrait;
public function createEntity()
{
$entity = new Entity();
$license = $this->getLicenseManager()->getLicense(3); // Finds a license with the id 3
$this->getLicenseManager()->injectLicense($entity, $license);
}
}