use formlib for creating a new loops site; automatically create subobjects

git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1246 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2006-06-10 15:21:45 +00:00
parent f6f863eeb6
commit db5a60a6a3
10 changed files with 223 additions and 41 deletions

View file

@ -28,11 +28,14 @@ from zope.app.form.browser.interfaces import ITerms
from zope.app.intid.interfaces import IIntIds
from zope.cachedescriptors.property import Lazy
from zope.dottedname.resolve import resolve
from zope.formlib.form import FormFields
from zope.formlib.form import EditForm as BaseEditForm
from zope.formlib.form import AddForm as BaseAddForm
from zope.formlib.namedtemplate import NamedTemplate
from zope.interface import implements
from zope.interface import Interface, implements
from zope.app.publisher.browser import applySkin
from zope.publisher.interfaces.browser import ISkin
from zope import schema
from zope.schema.vocabulary import SimpleTerm
from zope.security import canAccess, canWrite
from zope.security.proxy import removeSecurityProxy
@ -40,6 +43,29 @@ from zope.security.proxy import removeSecurityProxy
from cybertools.typology.interfaces import IType
from loops.interfaces import IView
from loops import util
from loops.util import _
class NameField(schema.ASCIILine):
def _validate(self, value):
super(NameField, self)._validate(value)
class IAddForm(Interface):
name = NameField(
title=_(u'Object name'),
description=_(u'Name of the object - will be used for addressing the '
'object via a URL; should therefore be unique within '
'the container and not contain special characters')
)
class AddForm(BaseAddForm):
form_fields = FormFields(IAddForm)
template = NamedTemplate('loops.pageform')
class EditForm(BaseEditForm):

View file

@ -85,13 +85,11 @@
<!-- loops top-level container -->
<addform
label="Add loops Container"
<page
name="AddLoopsContainer.html"
schema="loops.interfaces.ILoops"
content_factory="loops.Loops"
template="add.pt"
permission="zope.ManageContent"
for="zope.app.container.interfaces.IAdding"
class="loops.browser.manager.LoopsAddForm"
permission="zope.ManageApplication"
/>
<addMenuItem
@ -108,14 +106,13 @@
add="zope.ManageContent"
/>
<editform
label="Edit Loops Container"
<page
name="edit.html"
schema="loops.interfaces.ILoops"
fields="skinName"
for="loops.interfaces.ILoops"
permission="zope.ManageContent"
menu="zmi_views" title="Edit" />
class="loops.browser.manager.LoopsEditForm"
permission="zope.ManageApplication"
menu="zmi_views" title="Edit"
/>
<!-- concept manager -->

60
browser/manager.py Normal file
View file

@ -0,0 +1,60 @@
#
# Copyright (c) 2006 Helmut Merz helmutm@cy55.de
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Definition of view classes for the top-level loops container.
$Id$
"""
from zope.app import zapi
from zope.app.event.objectevent import ObjectCreatedEvent, ObjectModifiedEvent
from zope.event import notify
from zope.formlib.form import FormFields
from loops import Loops
from loops.interfaces import ILoops
from loops.browser.common import AddForm, EditForm, BaseView
from loops.setup import ISetupManager
from loops.util import _
class LoopsAddForm(AddForm):
form_fields = AddForm.form_fields + FormFields(ILoops)
label = _(u'Create Loops Site')
def createAndAdd(self, data):
container = self.context.context
name = data.pop('name', 'loopsdemo')
loops = Loops()
self.context.contentName = name
for attr in data:
setattr(loops, attr, data[attr])
notify(ObjectCreatedEvent(loops))
self.context.add(loops)
setup = ISetupManager(loops, None)
if setup is not None:
setup.setup()
return loops
class LoopsEditForm(EditForm):
form_fields = FormFields(ILoops)

View file

@ -41,12 +41,16 @@ function toggleFormFieldHelp(ob,state) {
<div id="viewspace" metal:define-slot="viewspace">
<h1 i18n:translate="heading_editform"
metal:define-slot="heading">Edit
<h1 tal:condition="not:view/label"
i18n:translate="heading_editform"
metal:define-slot="heading">Edit
<span i18n:name="title"
tal:content="context/title">Concept</span>
tal:content="context/title|context/zope:name">Concept</span>
</h1>
<h1 tal:condition="view/label"
tal:content="view/label">Headline</h1>
<metal:block define-macro="header">
<div class="form-status"

View file

@ -284,6 +284,7 @@
</class>
<adapter factory="loops.setup.SetupManager" />
<adapter factory="loops.external.NodesLoader" />
<adapter factory="loops.external.NodesExporter" />
<adapter factory="loops.external.NodesImporter" />

View file

@ -19,26 +19,30 @@ Let's first do some basic imports
>>> from zope.interface import Interface
>>> from zope.publisher.browser import TestRequest
and setup a simple loops site with its manager objects,
and provide a relation registry:
>>> from cybertools.relation.interfaces import IRelationRegistry
>>> from cybertools.relation.registry import DummyRelationRegistry
>>> from zope.app.testing import ztapi
>>> ztapi.provideUtility(IRelationRegistry, DummyRelationRegistry())
Now we can setup a simple loops site with its manager objects, using a
loops setup manager:
>>> from loops import Loops
>>> site['loops'] = Loops()
>>> loopsRoot = site['loops']
>>> from loops.concept import ConceptManager, Concept
>>> loopsRoot['concepts'] = ConceptManager()
>>> from loops.setup import SetupManager
>>> setup = SetupManager(loopsRoot)
>>> setup.setup()
>>> concepts = loopsRoot['concepts']
>>> from loops.resource import ResourceManager, Document, MediaAsset
>>> loopsRoot['resources'] = ResourceManager()
>>> resources = loopsRoot['resources']
>>> from loops.view import ViewManager, Node
>>> loopsRoot['views'] = ViewManager()
>>> views = loopsRoot['views']
some concepts,
We also add some example concepts,
>>> from loops.concept import Concept
>>> cc1 = Concept(u'Zope')
>>> concepts['cc1'] = cc1
>>> cc1.title
@ -51,6 +55,7 @@ some concepts,
resources,
>>> from loops.resource import Document, MediaAsset
>>> doc1 = Document(u'Zope Info')
>>> resources['doc1'] = doc1
>>> doc1.title
@ -61,6 +66,7 @@ resources,
and nodes (in view space):
>>> from loops.view import Node
>>> m1 = Node(u'Home')
>>> views['m1'] = m1
>>> m1.nodeType = 'menu'
@ -69,12 +75,6 @@ and nodes (in view space):
>>> m1['p1'] = m1p1
>>> m1p1.nodeType = 'page'
Finally, we also need a relation registry:
>>> from cybertools.relation.interfaces import IRelationRegistry
>>> from cybertools.relation.registry import DummyRelationRegistry
>>> from zope.app.testing import ztapi
>>> ztapi.provideUtility(IRelationRegistry, DummyRelationRegistry())
Type management with typology
=============================
@ -98,11 +98,10 @@ As we have not yet associated a type with one of our content objects we get
>>> cc1_type.token
'.unknown'
So we create two special concepts: one ('hasType') as the predicate signifying
a type relation, and the other ('type') as the one and only type concept:
During setup we created two special concepts: one ('hasType') as the predicate
signifying a type relation, and the other ('type') as the one and only type
concept:
>>> concepts['hasType'] = Concept(u'has type')
>>> concepts['type'] = Concept(u'Type')
>>> typeObject = concepts['type']
Assigning a type to a concept is a core functionality of concepts as
@ -189,8 +188,9 @@ get a type manager from all loops objects, always with the same context:
>>> types = typeManager.types
>>> sorted(t.token for t in types)
['.loops/concepts/topic', '.loops/concepts/type',
'loops.resource.Document', 'loops.resource.MediaAsset']
['.loops/concepts/predicate', '.loops/concepts/topic',
'.loops/concepts/type', 'loops.resource.Document',
'loops.resource.MediaAsset']
>>> typeManager.getType('.loops/concepts/topic') == cc1_type
True
@ -200,7 +200,7 @@ condition:
>>> types = typeManager.listTypes(include=('concept',))
>>> sorted(t.token for t in types)
['.loops/concepts/topic', '.loops/concepts/type']
['.loops/concepts/predicate', '.loops/concepts/topic', '.loops/concepts/type']
>>> types = typeManager.listTypes(exclude=('concept',))
>>> sorted(t.token for t in types)
['loops.resource.Document', 'loops.resource.MediaAsset']

View file

@ -32,8 +32,7 @@ from zope.app.folder.interfaces import IFolder
from cybertools.relation.interfaces import IRelation
import util
_ = MessageFactory('loops')
from util import _
# common interfaces

86
setup.py Normal file
View file

@ -0,0 +1,86 @@
#
# Copyright (c) 2006 Helmut Merz helmutm@cy55.de
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Automatic setup of a loops site.
$Id$
"""
import transaction
from zope.app.event.objectevent import ObjectCreatedEvent, ObjectModifiedEvent
from zope.event import notify
from zope.component import adapts
from zope.interface import implements, Interface
from zope.cachedescriptors.property import Lazy
from loops.interfaces import ILoops
from loops.concept import ConceptManager, Concept
from loops.resource import ResourceManager
from loops.view import ViewManager, Node
class ISetupManager(Interface):
""" An object that controls the setup of a loops site.
"""
def setup():
""" Set up a loops site: create all necessary objects and the
relations between them.
"""
class SetupManager(object):
adapts(ILoops)
implements(ISetupManager)
def __init__(self, context):
self.context = context
def setup(self):
concepts, resources, views = self.setupManagers()
self.setupCoreConcepts(concepts)
def setupManagers(self):
loopsRoot = self.context
concepts = self.addObject(loopsRoot, ConceptManager, 'concepts')
resources = self.addObject(loopsRoot, ResourceManager, 'resources')
views = self.addObject(loopsRoot, ViewManager, 'views')
return concepts, resources, views
def setupCoreConcepts(self, conceptManager):
typeConcept = self.addObject(conceptManager, Concept, 'type', u'Type')
hasType = self.addObject(conceptManager, Concept, 'hasType', u'has type')
predicate = self.addObject(conceptManager, Concept, 'predicate', u'Predicate')
standard = self.addObject(conceptManager, Concept, 'standard', u'subobject')
typeConcept.conceptType = typeConcept
predicate.conceptType = typeConcept
hasType.conceptType = predicate
standard.conceptType = predicate
def addObject(self, container, class_, name, title=None):
if name in container:
return container[name]
if title:
obj = container[name] = class_(title)
else:
obj = container[name] = class_()
notify(ObjectCreatedEvent(obj))
notify(ObjectModifiedEvent(obj))
return obj

View file

@ -17,6 +17,12 @@ from loops.concept import Concept, ConceptManager
from loops.resource import Document, MediaAsset, ResourceManager
from loops.view import Node, ViewManager
# just for making sure there aren't any syntax and other errors during
# Zope startup:
from loops.browser.manager import LoopsAddForm, LoopsEditForm
class Test(unittest.TestCase):
"Basic tests for the loops package."

View file

@ -23,9 +23,12 @@ $Id$
"""
from zope.interface import directlyProvides, directlyProvidedBy
from zope.i18nmessageid import MessageFactory
from zope.schema import vocabulary
#from view import TargetRelation
_ = MessageFactory('loops')
class KeywordVocabulary(vocabulary.SimpleVocabulary):