Accessing Magnolia CMS from PHP



Jackalope and the PHP Content Repository

Housekeeping

Agenda

Grégory Joseph

David Buchmann

About JCR/PHPCR


Data in a CMS is mostly unstructured

RDBMS are not a good fit, hurray for NoSQL

like fitting a square into a circle

CMS often organize content as a tree/graph

Most NoSQL not a good fit, hurray for Graph DBs

content graph

CMS should be able to store content versions

multiple versions

JCR / PHPCR Features


(*) Not yet implemented in Jackalope

JCR / PHPCR concepts

Hierarchical document store

Magnolia browser

Nodes

Primary Node Types

Mixin Node Types

Workspaces

Differences between JCR and PHPCR

Various PHPCR implementations

Magnolia and PHPCR



Magnolia and PHPCR: Scenarios


Installation

Code along if you are watching the recorded session

Prerequisites

Setup Magnolia

Magnolia configuration window

Setup the PHP project

curl -s http://getcomposer.org/installer | php --
./composer.phar init
./composer.phar require jackalope/jackalope-jackrabbit
./composer.phar install
            

More information at http://jackalope.github.com/

PHPCR code examples

Connecting via PHPCR

// file test.php
require_once(__DIR__ . 'vendor/autoload.php');

$parameters = array(
  'jackalope.jackrabbit_uri'
    => 'http://localhost:8080/magnoliaAuthor/.davex/'
);
$repository = Jackalope\RepositoryFactoryJackrabbit::
  getRepository($parameters);

$creds = new \PHPCR\SimpleCredentials(
  'superuser','superuser');
$website = $repository->login($creds, 'website');
            

Reading a value

$path = '/demo-project/about/history';
$node = $website->getNode($path);
$title = $node->getPropertyValue('title');
echo "$title\n";
            
php test.php
$ History
            

Read binary data

// init code as before
$repository = Jackalope\RepositoryFactoryJackrabbit::
  getRepository($parameters);
$dms = $repository->login($creds, 'dms');

$path = '/demo-project/downloads/Magnolia_Flyer_4-0';
$node = $dms->getNode($path);
$properties = $node->getNode('document')
  ->getPropertiesValues();
echo "Found document, mime-type: " .
  $properties['jcr:mimeType'] . "\n";
$filename = $properties['fileName'] . '.' .
  $properties['extension'];
file_put_contents($filename, $properties['jcr:data']);
echo "Saved to $filename\n";
            

Saves the file to the current directory

Updating and creating properties

$path = '/demo-project/about/history';
$node = $website->getNode($path);

// update existing property
$node->setProperty('title', 'Updated Company History');

// create a new property
$node->setProperty('foo', 'bar');

// always need to save when writing to commit changes
$website->save();
            

Creating a new node

// add a folder node to the repository
$node = $dms->getNode('/demo-docs/internet');
$name = 'test-folder';
$type = 'mgnl:content';
$folderNode = $node->addNode($name, $type);
$folderNode->setProperty ("title", "Test Folder");
$folderNode->setProperty ("type", "folder");

// save changes
$dms->save();
            

Magnolia browser

Tree Traversal API

$path = '/demo-project/about/subsection-articles';
$node = $session->getNode($path);

foreach ($node->getNodes() as $child) {
    if ($child->hasProperty('abstract')) {
        $abstract =
          $child->getPropertyValue('abstract');
        echo $child->getPath() . ": $abstract\n";
    }
}
            

Search via SQL2 API

$qm = $website->getWorkspace()->getQueryManager();

$sql = "SELECT *
        FROM [mgnl:page]
        WHERE ISDESCENDANTNODE('/demoproject/about')";

$query = $qm->createQuery($sql, 'JCR-SQL2');
$queryResult = $query->execute();

foreach ($queryResult->getNodes() as $node) {
    if ($node->hasProperty('title')) {
        $title = $node->getPropertyValue('title');
        echo $node->getPath . ": $title\n";
    }
}
            

Doctrine PHPCR ODM

Doctrine PHPCR ODM

Conclusions

Not all data fits well in PHPCR/JCR

Door swings both ways, so remember

like fitting a square into a circle

Play with it today!

PHPCR Tutorial


See it in action!

Symfony2 CMF sandbox

PHPCR in real life

Next steps

Many individuals contribute to the effort


  • 0x616469 (Adrian Schlegel)
  • adou600 (Adrien Nicolet)
  • beberlei (Benjamin Eberlei)
  • bergie (Henri Bergius)
  • bmatzner (Bernd Matzner)
  • brki (Brian King)
  • chirimoya (Thomas Schedler)
  • chregu (Christian Stocker)
  • cordoval (Luis Cordova)
  • craigmarvelley (Craig Marvelley)
  • cryptocompress (Crypto Compress)
  • damz (Damien Tournoud)
  • dbojdo (Daniel Bojdo)
  • dbu (David Buchmann)
  • dotZoki (Zoran)
  • ebi (Tobias Ebnöther)
  • fabian (Fabian Vogler)
  • flojon (Jonas Flodén)
  • iambrosi (Ismael Ambrosi)
  • jakuza (Jacopo Romei)
  • justinrainbow (Justin Rainbow)
  • k-fish/kdambekalns (Karsten Dambekalns)
  • krizon (Kristian Zondervan)
  • lapistano (Bastian Feder)
  • lsmith77 (Lukas K. Smith)
  • mdekrijger
  • micheleorselli (Michele Orselli)
  • nacmartin (Nacho Martín)
  • nicam (Pascal Helfenstein)
  • Ocramius (Marco Pivetta)
  • ornicar (Thibault Duplessis)
  • pajooh (arash)
  • petesiss (Pete Sisson)
  • piotras
  • pitpit (Damien Pitard)
  • rande (Thomas)
  • richardmiller (Richard Miller)
  • rndstr (Roland Schilter)
  • robertlemke (Robert Lemke)
  • sebastien-roch (Sébastien Roch)
  • Seldaek (Jordi Boggiano)
  • simensen (Beau Simensen)
  • sixty-nine (Daniel Barsotti)
  • sjopet
  • starkj (Johannes Stark)
  • stof (Christophe Coevoet)
  • uwej711 (Uwe Jäger)
  • vedranzgela (Vedran Zgela)
  • videlalvaro (Alvaro Videla)
  • ...

Several companies and organisations are investing into the effort

Liip, Ideato, Nemein, IKS

Many projects have expressed interest

Symfony2 CMF, Midgard, Typo3, Nooku, ezPublish, Drupal

Github projects

Resources

Thank you !






Questions?