Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Child annotation and file handling #4

Merged
merged 12 commits into from May 9, 2011
15 changes: 15 additions & 0 deletions README.markdown
Expand Up @@ -24,6 +24,21 @@ Notes
Getting Started
---------------

0. Register custom node types in Jackrabbit

- stop your Jackrabbit instance
- run "java -jar jackrabbit-standalone-2.2.4.jar --cli file://<path to your repository>"
- enter "registernodetype <path to phpcr.cnd>"
- enter "quit"
- start your server again ...

where phpcr.cnd contains

<phpcr='http://www.doctrine-project.org/phpcr-odm'>
[phpcr:managed]
mixin
- phpcr:alias (STRING)

1. Define one of those mapping drivers

// Annotation driver
Expand Down
105 changes: 105 additions & 0 deletions lib/Doctrine/ODM/PHPCR/Document/File.php
@@ -0,0 +1,105 @@
<?php

namespace Doctrine\ODM\PHPCR\Document;

/**
* This class represents a JCR file, aka nt:file.
* @see http://wiki.apache.org/jackrabbit/nt:file
*
* @phpcr:Document(alias="file", nodeType="nt:file")
*/
class File
{
/** @phpcr:Id */
protected $id;

/** @phpcr:Node */
protected $node;

/** @phpcr:Date(name="jcr:created") */
protected $created;

/** @phpcr:String(name="jcr:createdBy") */
protected $createdBy;

/** @phpcr:Child(name="jcr:content") */
protected $content;

/**
* setter for id
*
* @param string $id of the node
*/
public function setId($id)
{
$this->id = $id;
}

/**
* getter for id
*
* @return string id of the node
*/
public function getId()
{
return $this->id;
}

/**
* getter for created
* The created date is assigned by the content repository
*
* @return DateTime created date of the file
*/
public function getCreated()
{
return $this->created;
}

/**
* getter for createdBy
* The createdBy is assigned by the content repository
* This is the name of the (jcr) user that created the node
*
* @return string name of the (jcr) user who created the file
*/
public function getCreatedBy()
{
return $this->createdBy;
}

/**
* Set the content for this file from the given filename.
* Calls file_get_contents with the given filename
*
* @param string $filename name of the file which contents should be used
*/
public function setFileContentFromFilesystem($filename)
{
$this->getContent();
$this->content->setData(file_get_contents($filename));
}

/**
* Set the content for this file from the given string.
*
* @param string $content the content for the file
*/
public function setFileContent($content)
{
$this->getContent();
$this->content->setData($content);
}

/*
* Ensure content object is created
*/
private function getContent()
{
if ($this->content === null)
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this { should be on the previous line

$this->content = new Resource();
}
return $this->content;
}
}
67 changes: 67 additions & 0 deletions lib/Doctrine/ODM/PHPCR/Document/Folder.php
@@ -0,0 +1,67 @@
<?php

namespace Doctrine\ODM\PHPCR\Document;

/**
* This class represents a Folder in the repository, aka nt:folder
* @see http://wiki.apache.org/jackrabbit/nt:folder
*
* @phpcr:Document(alias="folder", nodeType="nt:folder")
*/
class Folder
{
/** @phpcr:Id */
protected $id;

/** @phpcr:Node */
protected $node;

/** @phpcr:Date(name="jcr:created") */
protected $created;

/** @phpcr:String(name="jcr:createdBy") */
protected $createdBy;

/**
* setter for id
*
* @param string $id of the node
*/
public function setId($id)
{
$this->id = $id;
}

/**
* getter for id
*
* @return string id of the node
*/
public function getId()
{
return $this->id;
}

/**
* getter for created
* The created date is assigned by the content repository
*
* @return DateTime created date of the file
*/
public function getCreated()
{
return $this->created;
}

/**
* getter for createdBy
* The createdBy is assigned by the content repository
* This is the name of the (jcr) user that created the node
*
* @return string name of the (jcr) user who created the file
*/
public function getCreatedBy()
{
return $this->createdBy;
}
}
144 changes: 144 additions & 0 deletions lib/Doctrine/ODM/PHPCR/Document/Resource.php
@@ -0,0 +1,144 @@
<?php

namespace Doctrine\ODM\PHPCR\Document;

/**
* This class represents a jcr nt:resource and is used by the File document
* @see http://wiki.apache.org/jackrabbit/nt:resource
*
* @phpcr:Document(alias="resource", nodeType="nt:resource")
*/
class Resource
{
/** @phpcr:Id */
protected $id;

/** @phpcr:Node */
protected $node;

/** @phpcr:Binary(name="jcr:data") */
protected $data;

/** @phpcr:String(name="jcr:mimeType") */
protected $mimeType;

/** @phpcr:String(name="jcr:encoding") */
protected $encoding;

/** @phpcr:Date(name="jcr:lastModified") */
protected $lastModified;

/** @phpcr:String(name="jcr:lastModifiedBy") */
protected $lastModifiedBy;

/**
* setter for the data property
* This property stores the content of this resource
*
* @param string $data the contents of this resource
*/
public function setData($data)
{
$this->data = $data;
}

/**
* getter for the data property
* This returns the content of this resource
*
* @param string
*/
public function getData()
{
return $this->data;
}

/**
* setter for the mimeType property
* This property stores the mimeType of this resource
*
* @param string $mimeType
*/
public function setMimeType($mimeType)
{
$this->mimeType = $mimeType;
}

/**
* getter for the mimeType property
* This returns the mimeType of this resource
*
* @return string
*/
public function getMimeType()
{
return $this->mimeType;
}

/**
* setter for the encoding property
* This property stores the encoding of this resource
*
* @param string $encoding
*/
public function setEncoding($encoding)
{
$this->encoding = $encoding;
}

/**
* getter for the encoding property
* This returns the encoding of this resource
*
* @return string
*/
public function getEncoding()
{
return $this->encoding;
}

/**
* setter for the lastModified property
* This property stores the lastModified date of this resource
* If not set, this might be set by PHPCR
*
* @param DateTime $lastModified
*/
public function setLastModified($lastModified)
{
$this->lastModified = $lastModified;
}

/**
* getter for the lastModified property
* This returns the lastModified date of this resource
*
* @return DateTime
*/
public function getLastModified()
{
return $this->lastModified;
}

/**
* setter for the lastModifiedBy property
* name of the jcr user that last modified this resource
*
* @param string $lastModifiedBy
*/
public function setLastModifiedBy($lastModifiedBy)
{
$this->lastModifiedBy = $lastModifiedBy;
}

/**
* getter for the lastModifiedBy property
* This returns name of the jcr user that last modified this resource
*
* @return string
*/
public function getLastModifiedBy()
{
return $this->lastModifiedBy;
}
}
29 changes: 28 additions & 1 deletion lib/Doctrine/ODM/PHPCR/Mapping/ClassMetadataInfo.php
Expand Up @@ -180,6 +180,12 @@ class ClassMetadataInfo implements ClassMetadata

public $associationsMappings = array();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: In general i want to see the ClassMetadataInfo implementations of MongoDB, CouchDB and PHPCR ODM come together a bit more. Right now I prefer the way MongoDB does reference/embed the most.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't look at those but at JCR ... therefore it's named Child now ...
For the reference stuff I think we should also go the JCR way, i.e. have properties fo type Reference or WeakReference on the nodes, multivalued if it is a to-many association.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imho in jackalope we should follow JCR/Jackrabbit naming, but in PHPCR ODM we should follow the naming of the other ODM's as much as possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But what do we do if the concepts behind are different? A child in JCR is just a full-feature repository node as every other - it is visible from outside. Ther e is no notion of containment or anything else ...
Anyway I will look at the other ODMs to.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO we should focus PHPCR ODM on the things that are the same or similar. This is also why I am advocating with the renaming of path to id. The main point from my POV is to make it possible to share knowledge and code with the other ODM's. For most PHPCR specific stuff imho developers can fallback to Jackalope. However we can also of course add some connivence features to PHOCR ODM that are PHPCR specific.

So I guess the gist is that we should always carefully review if there are similar concepts on the other ODM's and if we can sensibly adopt the naming form there. Of course this is just my POV.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Three last comments here (this should be part of my feedback on the list):

  • If the concepts are the same or similar it should be named the same way and work the same way
  • If it's all the same you loose the good reasons for using phpcr ...
  • The fallback to PHPCR is there but it basically breaks your controllers or services - somewhere you need to place the code. If not in the ODM it will move up ...



/**
* Mapping of child doucments that are child nodes in the repository
*/
public $childMappings = array();

/**
* PHPCR documents are always versioned, this flag determines if this version is exposed to the userland.
*
Expand Down Expand Up @@ -478,13 +484,34 @@ public function mapField(array $mapping)
$this->fieldMappings[$mapping['fieldName']] = $mapping;
}

public function mapId(array $mapping)
{
if (isset($mapping['id']) && $mapping['id'] === true) {
$mapping['type'] = 'string';
$this->setIdentifier($mapping['fieldName']);
if (isset($mapping['strategy'])) {
$this->idGenerator = constant('Doctrine\ODM\PHPCR\Mapping\ClassMetadata::GENERATOR_TYPE_' . strtoupper($mapping['strategy']));
}
}
$this->validateAndCompleteFieldMapping($mapping, false);
}

public function mapNode(array $mapping)
{
$this->validateAndCompleteFieldMapping($mapping, false);

$this->node = $mapping['fieldName'];
}

public function mapChild(array $mapping)
{
$mapping = $this->validateAndCompleteFieldMapping($mapping, false);
if (!isset($mapping['name'])) {
$mapping['name'] = $mapping['fieldName'];
}
$this->childMappings[$mapping['fieldName']] = $mapping;
}

protected function validateAndCompleteFieldMapping($mapping, $isField = true)
{
if (!isset($mapping['fieldName'])) {
Expand All @@ -493,7 +520,7 @@ protected function validateAndCompleteFieldMapping($mapping, $isField = true)
if ($isField && !isset($mapping['name'])) {
$mapping['name'] = $mapping['fieldName'];
}
if (isset($this->fieldMappings[$mapping['fieldName']]) || isset($this->associationsMappings[$mapping['fieldName']])) {
if (isset($this->fieldMappings[$mapping['fieldName']]) || isset($this->associationsMappings[$mapping['fieldName']]) || isset($this->childMappings[$mapping['fieldName']])) {
throw MappingException::duplicateFieldMapping($this->name, $mapping['fieldName']);
}
if ($isField && !isset($mapping['type'])) {
Expand Down