Liiptalk Neos CMS

Preview:

Citation preview

building a CMS for ambitious editors

history

born under the TYPO3 umbrella

goals

foundation

FLOW full stack PHP framework

yet an other framework

convention over configuration

security framework

privilegeTargets:

'TYPO3\Flow\Security\Authorization\Privilege\Method\MethodPrivilege':

'Acme.MyPackage:RestrictedController.customerAction': matcher: 'method(Acme\MyPackage\Controller\RestrictedController-> customerAction())'

'Acme.MyPackage:RestrictedController.adminAction': matcher: 'method(Acme\MyPackage\Controller\RestrictedController-> (admin|drop)Action())’

'Acme.MyPackage:editOwnPost': matcher: ‘method(Acme\MyPackage\Controller\PostController-> editAction(post.owner == current.userService.currentUser))'

roles: 'Acme.MyPackage:Customer': privileges: - privilegeTarget: 'Acme.MyPackage:RestrictedController.customerAction' permission: GRANT - privilegeTarget: 'Acme.MyPackage:RestrictedController.adminAction' permission: GRANT - privilegeTarget: 'Acme.MyPackage:RestrictedController.editOwnPost' permission: GRANT

'Acme.MyPackage:Customer': privileges: - privilegeTarget: 'Acme.MyPackage:RestrictedController.customerAction' permission: GRANT

'Acme.MyPackage:PrivilegedCustomer': parentRoles: ['Acme.MyPackage:Customer'] privileges: - privilegeTarget: 'Acme.MyPackage:RestrictedController.editOwnPost' permission: GRANT

security CLI helpers

$ ./flow security:showunprotectedactions

TYPO3\Neos\Controller\Backend\ContentController initializeUploadAssetAction initializeCreateImageVariantAction

TYPO3\Neos\Controller\LoginController initializeIndexAction

TYPO3\Neos\Controller\Service\WorkspacesController initializeUpdateAction

Ttree\CloudButler\Controller\JobController initializeRegisterAction

AOP

help with single responsibility principle

danger zone

We compile your code

Powerful Reflection API

@Flow\CompileStatic

/** * Returns a map of action method names and their parameters. * * @param \TYPO3\Flow\Object\ObjectManagerInterface $objectManager * @return array Array of method parameters by action name * @Flow\CompileStatic */ static public function getActionMethodParameters($objectManager) { $reflectionService = $objectManager->get( 'TYPO3\Flow\Reflection\ReflectionService'); $className = get_called_class(); $methodParameters = $reflectionService->getMethodParameters($className, get_class_methods($className)); foreach ($methodParameters as $parameterName => $parameterInfo) { ... } return $methodParameters; }

NEOS is just a package

NEOS Content Repository

where content lives

yaml configuration

'My.Package:SpecialHeadline': superTypes: 'TYPO3.Neos:Content': true ui: label: 'Special Headline' group: 'general' properties: headline: type: 'string' defaultValue: 'My Headline Default' ui: inlineEditable: true validation: 'TYPO3.Neos/Validation/StringLengthValidator': minimum: 1 maximum: 255

inspired by PHPCR

editing content

editor experience

workspace

content dimensions

contents lives in multiple contexts

WYSIFTW

developer

don’t hide features

create values

flexible content structure

modern rendering stack

fusion

prototype(Vendor:Staff) < prototype(TYPO3.Neos:Content) { templatePath = ‘resource://Vendor.Site/Private/Templates/ElementName.html'

headline = ${q(node).property('headline')} subheadline = ${q(node).property('subheadline')} text = ${q(node).property('text')} image = ${q(node).property('image')} }

prototype(Vendor:Staff) < prototype(TYPO3.Neos:Content) { templatePath = ‘resource://Vendor.Site/Private/Templates/ElementName.html'

headline = ${q(node).property('headline')} subheadline = ${q(node).property('subheadline')} text = ${q(node).property('text')} image = ${q(node).property(‘image’)}

staffIdentifier = ${q(node).property(‘staffIdentifier’)} staffIdentifier.@process.callErp = ${ErpApi.getStaffDetails(value)} }

prototype(Vendor:YourTwoColumns) {

prototype(Vendor:Staff) { templatePath = ‘resource://Vendor.Site/Private/Templates/Compact.html' }

}

prototype(Vendor:StaffDirectory.Document) {

prototype(Vendor:Staff) { templatePath = ‘resource://Vendor.Site/Private/Templates/Square.html' staffPageLink = ${q(node).property(‘staffIdentifier’)} staffPageLink.@process.callErp = ${ErpApi.getStaffUri(value)} }

}

prototype(Vendor:StaffListing) < prototype(Flowpack.Listable:Listable) { @context.limit = 10 collection = ${q(site).find('[instanceof Vendor:Staff]’).get()} itemRenderer = ‘Vendor:StaffListingItem' }

prototype(Vendor:StaffListingItem) < prototype(Vendor:Staff) { templatePath = ‘resource://Vendor.Site/Private/Templates/ListingItem.html' }

cache on steroid

prototype(Vendor:StaffListingItem) { @cache { mode = 'cached'

maximumLifetime = '86400'

entryIdentifier { node = ${node} }

entryTags { 1 = ${'Node_' + documentNode.identifier} } }

}

much much more open to organize a workshop to build

something on top of NEOS

from the lab

CQRS for the content repository

touch points

neos.io

hello@ttree.ch - @ttreeagency - github.com/ttreeagency

tt ttreedigital beans