独自ビューレットの作成 [Plone4.0]

サイドメニューポートレットの作成

sidemenu.JPGサイドメニュー用に指定したフォルダ内の index.html ページとフォルダタイプ一覧を表示するポートレットを作成する。

configure.zcmlの設定

プロダクトの browser ディレクトリの configure.zcml ファイルを次のように編集してポートレットを登録する。

   <configure xmlns="http://namespaces.zope.org/zope"
              xmlns:browser="http://namespaces.zope.org/browser"
              xmlns:plone="http://namespaces.plone.org/plone">

      :

+      <plone:portlet
+          name="portlets.lmenu"
+          interface=".lmenu.ILMenuPortlet"
+          assignment=".lmenu.Assignment"
+          renderer=".lmenu.Renderer"
+          addview=".lmenu.AddForm"
+          editview=".lmenu.EditForm"
+          />

   </configure>

lmenu.py作成

プロダクトの browser ディレクトリに lmenu.py としてテンプレートから呼び出すメソッドなどを定義する。

from zope import schema
from zope.component import getMultiAdapter
from zope.formlib import form
from zope.interface import implements

from plone.app.portlets.portlets import base
from plone.memoize import ram
from plone.memoize.compress import xhtml_compress
from plone.memoize.instance import memoize
from plone.portlets.interfaces import IPortletDataProvider
from plone.app.portlets.cache import render_cachekey

from Acquisition import aq_inner
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from Products.CMFCore.utils import getToolByName
from Products.CMFPlone import PloneMessageFactory as _

from plone.app.vocabularies.catalog import SearchableTextSourceBinder
from plone.app.form.widgets.uberselectionwidget import UberSelectionWidget

class ILMenuPortlet(IPortletDataProvider):

    name = schema.TextLine(
            title=_(u"Title"),
            description=_(u""),
            required=True)

    root = schema.Choice(
            title=_(u"label_navigation_root_path", default=u"Root node"),
            description=_(u''),
            required=False,
            source=SearchableTextSourceBinder({'is_folderish' : True},
                                              default_query='path:'))

class Assignment(base.Assignment):
    implements(ILMenuPortlet)

    def __init__(self, name=u"", root=None):
        self.root = root
        self.name = name

    @property
    def title(self):
        return _(u"Side Menu")

class Renderer(base.Renderer):

    _template = ViewPageTemplateFile('lmenu.pt')

    @property
    def available(self):
        return len(self._data())

    def title(self):
        return self.data.name

    def menu_list(self):
        return self._data()

    @memoize
    def _data(self):
        context = aq_inner(self.context)
        catalog = getToolByName(context, 'portal_catalog')
        urltool = getToolByName(context, 'portal_url')
        query = str(urltool.getPortalPath()) + str(self.data.root)
        mtop = catalog(id = 'index.html',
                       portal_type=['Document','Topic'],
                       path = { 'query' : query, 'depth' : 1,})
        mfolder = catalog(portal_type='Folder',
                          path = { 'query' : query, 'depth' : 1,},
                          sort_on = 'getObjPositionInParent')
        menu = mtop + mfolder
        return menu

    def render(self):
        return self._template()

class AddForm(base.AddForm):
    form_fields = form.Fields(ILMenuPortlet)
    form_fields['root'].custom_widget = UberSelectionWidget
    label = _(u"Add Side Menu")
    description = _(u"This portlet displays Side Menu.")

    def create(self, data):
        return Assignment(root=data.get('root', u""), name=data.get('name', u"Menu"))

class EditForm(base.EditForm):
    form_fields = form.Fields(ILMenuPortlet)
    form_fields['root'].custom_widget = UberSelectionWidget
    label = _(u"Edit Side Menu Portlet")
    description = _(u"This portlet displays Side Menu.")

lmenu.ptの作成

プロダクトの browser ディレクトリに lmenu.pt としてテンプレートを定義する。

<dl class="portlet portletNews"
    tal:omit-tag=""
    i18n:domain="plone">

    <div id="menu">
    <div class="l-menu-head" tal:content="view/title" />

    <ul class="l-menu">
    <tal:items tal:repeat="item view/menu_list">
      <li>
        <a tal:define="class python:item.getURL() in context.absolute_url() and 'on' or ''"
           tal:attributes="href item/getURL;
                           class class">
        <span tal:replace="item/pretty_title_or_id">Title</span>
        </a>
      </li>
    </tal:items>
    </ul>
    <div class="l-menu-footer"></div>
    </div>

</dl>

Ploneへのポートレット表示

プロダクトのプロファイルとして portlets.xml を次のように作成して、ポートレットとして追加できるようにする。

<?xml version="1.0"?>
<portlets>
 <portlet title="Side Menu" addview="portlets.lmenu"
    description="A portlet for side menu">
  <for interface="plone.app.portlets.interfaces.IColumn"/>
 </portlet>
</portlets>

グループメンバー変更テンプレート

各サイトの管理者用にサイト管理者グループを定義する。このグループには全ての権限(Managerロール)を与えず、Editor、 Contributor、Reviewerロールを与える。このグループメンバーは、サイトのすべてのコンテンツ編集に加え、主にグループメンバーの変更 (Manage users 権限要)、共有の変更ができ、ZMIへのアクセスはできないといった運用を想定する。

デフォルトのグループメンバー変更テンプレートを、少しカスタマイズしたものを別名で定義する。ビューレット名を site-admin-group-members、テンプレート名を site-admin-group-members.pt とする。

実際に利用する際は、次のURLを呼び出すことで利用できる。

http://(サイトURL)/@@site-admin-group-members?groupname=(グループID)

configure.zcmlの設定

プロダクトの browser ディレクトリの configure.zcml ファイルを次のように編集してビューレットを登録する。

+     <browser:page
+ name="site-admin-group-members"
+  for="Products.CMFPlone.interfaces.IPloneSiteRoot"
+  class="plone.app.controlpanel.usergroups.GroupMembershipControlPanel"
+ permission="zope2.ManageUsers"
+   template="site-admin-group-members.pt"
+  />

</configure>

site-admin-group-members.pt の定義

プロダクトの browser ディレクトリに usergroup site-admin-group-members.pt を plone.app.controlpanel 内の usergroups_groupmembership.pt をコピーする形で作成し、例えば次の点を修正してみる。

  • テンプレート名の修正
    次の点を修正しておく。
- tal:define="template_id string:@@usergroup-groupmembership;
+ tal:define="template_id string:@@site-admin-group-members;
  • ユーザIDを表示しない
    次の部分を2か所変更する。
- <tal:userid tal:condition="not:view/email_as_username">
+ <tal:userid tal:condition="nothing">
(<span tal:replace="this_user/getId | default" />)
</tal:userid>
  • 編集バーを削除
    次の部分を変更する。
- <div id="edit-bar">
+ <div id="edit-bar" tal:condition="nothing">
  • グループが存在しない場合のメッセージを削除
    次の部分を変更する。
- <tal:ifnogroups tal:condition="not:view/group | nothing">
+ <tal:ifnogroups tal:condition="nothing">
  • グループ概要に上がるリンクを削除
    次の部分を変更する。
  <a href=""
+ tal:condition="nothing"
  class="link-parent"
  tal:attributes="href string:$portal_url/@@usergroup-groupprefs"
  i18n:translate="label_up_to_groups_overview">
  Up to Groups Overview
</a>
  • グループの場合はリンクを張らない
    次の部分を2か所変更する。
- <a href="" tal:attributes="href python:'prefs_group_details?' + view.makeQuery(groupname=this_user.getGroupName())" >
+ <span>
:
- </a>
+ </span>