My Archetypes-based content type can't be viewed - plone

I have a little Plone extension which contains a simple Archetypes-based content type (the same which I had not been able to add TTW, see my previous question); the project setup is on GitHub.
After adding an object, I get a KeyError: 'view' during execution of the plone.abovecontenttitle content provider:
{'container': <MyType at /plone/test-for-new-types/a-mytype-object>,
'context': <MyType at /plone/test-for-new-types/a-mytype-object>,
'default': <object object at 0x7fc4f8ebe520>,
'here': <MyType at /plone/test-for-new-types/a-mytype-object>,
'loop': {},
'nothing': None,
'options': {'args': ()},
'repeat': <Products.PageTemplates.Expressions.SafeMapping object at 0x7fc4c9484db8>,
'request': <HTTPRequest, URL=https://my.testing.site/test-for-new-types/a-mytype-object/mytype_view>,
'root': <Application at >,
'template': <FSPageTemplate at /plone/test-for-new-types/a-mytype-object/mytype_view>,
'traverse_subpath': [],
'user': <PloneUser 'me'>}
It should be reproducible easily with my little extension installed in develop mode.
Edit:
I noticed that, in the "Installed Product" view (/portal_quickinstaller/MyCompany.MyProduct/manage_installationInfo), my product has Status: installed and Types MyType, but Content Type Registry entries is empty (None).

Content-providers call adapters, which expect a view-argument to be present[1] and skin-based templates don't provide, in contradiction to browser-based templates.
To fix that, we can use the global ##plone-var[2] like it's done in main_template, because ##plone is an instance of BrowserView, it provides the view-argument:
tal:define="view context/##plone;"
Which makes me think, the adapters the content-providers are using, should regard the case that no view is available.
In case you want to have the usual site-structure and just customize the content-part, you could also fill your template into the content-slot, then everything from main_template is inherited, also the view-var:
<metal:main metal:use-macro="context/main_template/macros/master">
<metal:content fill-slot="content">
Hey, a working content-provider:
<div tal:replace="structure provider:plone.abovecontenttitle" />
Oh, so much more much, here...
</metal:content>
</metal:main>
Which I would recommend, because then you don't need to worry about doing everything right in the header-part. E.g. using "raiseAnon" shouldn't be necessary, because the item's workflow-state is taking care of that and things like the current language will be evaluated, etc.
If you only want to customize the body-part of the content-item, change content to content-core, the usual content-providers will be rendered then anyways, you don't need to insert them, if you want them in the usual order.
[1]https://docs.plone.org/4/en/old-reference-manuals/portlets/rendered.html
[2]https://github.com/plone/Products.CMFPlone/blob/master/Products/CMFPlone/browser/ploneview.py

Related

How to configure PHP CodeSniffer to allow arrays with any indentation?

I have a custom rule set defined in an XML.
I am used to hit a tab after each => so that, if my array is multi-line, things will align nicely. It became a habit and I use that for single line arrays also. Therefore, a multi-line array might look like this
$array = array(
'something' => array(
'short' => 1,
'longer' => 1,
),
);
The problem is that PHP CodeSniffer is complaining that there is more than 1 space between => and the value (since I always hit tab, there will be more than one space most of the times - of course, depending on the length of the line so far, it can also be a single space sometimes)
I tried adding the T_ARRAY token to the Generic.WhiteSpace.ScopeIndent rule definition but it didn't help
<rule ref="Generic.WhiteSpace.ScopeIndent">
<properties>
<property name="indent" value="4"/>
<property name="ignoreIndentationTokens" type="array" value="T_COMMENT,T_DOC_COMMENT_OPEN_TAG,T_ARRAY"/>
</properties>
</rule>
Is there a solution for this?
UPDATE
Ok, I realised that Generic.WhiteSpace.ScopeIndent has nothing to do with this because it's the Squiz.WhiteSpace.OperatorSpacing that is enforcing this rule. Now, according to the docs I can't configure this property to exclude the => operator. Is there any other way of doing this?
Unfortunately, that sniff does not have any config options to ignore this specific case. Besides adding an option to the sniff, you really only have two ways to solve this. Neither are great.
1. You can exclude the Squiz.WhiteSpace.OperatorSpacing.SpacingAfter error code in your ruleset. This will still allow the sniff to produce errors for spacing before operators and around bitwise operators, but you wont get any errors for when you have multiple spaces after a standard operator.
To exclude the error code, you would add this to your ruleset:
<exclude name="Squiz.WhiteSpace.OperatorSpacing.SpacingAfter"/>
2. You can write a custom sniff that extends PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\OperatorSpacingSniff and overrides the isOperator() method. Your overridden method would detect the T_DOUBLE_ARROW token and return false, which will cause the main sniff code to stop checking double arrows. If it's not a double arrow, you can throw the request back to the parent class.
If you do this, you need to maintain your own standard with sniffs, which means putting a directory somewhere, with a Sniffs sub-directory structure to hold your sniff.

How add a plugin with data to a page using the add_plugin (API)?

i'm trying to add a plugin in a placeholder of a page when i save a model. But i don't know how to pass the parameter "data" to add_plugin() function of the API.
This is how i'm calling the function
page = create_page(self.title, 'page.html', 'es', parent=query_pages[0])
placeholder = page.placeholders.get(slot='News Header')
add_plugin(placeholder, 'ArticlePluginPublisher', 'es', **query_art[0].article)
And when i call add_plugin appears the next error
add_plugin() argument after ** must be a mapping, not Article
Did you check the docs? **query_art[0].article doesn't match the expected arguments as it's an instance;
placeholder (cms.models.placeholdermodel.Placeholder instance) – Placeholder to add the plugin to
plugin_type (string or cms.plugin_base.CMSPluginBase sub-class, must be a valid plugin) – What type of plugin to add
language (string) – Language code for this plugin, must be in LANGUAGES
position (string) – Position to add this plugin to the placeholder, must be a valid django-mptt position
target – Parent plugin. Must be plugin instance
data (kwargs) – Data for the plugin type instance
Data is expected to be something like a dictionary, or something that supports the ** unpacking syntax;
add_plugin(placeholder, 'ArticlePluginPublisher', 'es', **{'article': query_art[0].article})
Check out this example of data or kwargs in a function call;
https://stackoverflow.com/a/1769475/1199464

Remove custom type in Alfresco

In Alfresco, if a type name is removed/changed all nodes of that type will disappears but still exists.
Using alfresco 5.0.c I've added some custom types:
eg:
<type name="my:test">
<title>Test folder</title>
<parent>cm:folder</parent>
</type>
now i deploy it and create a folder of this type (a simple folder, then change type)
Now i edit the type like this:
<type name="my:test2"> <!-- from my:test to my:test2 -->
<title>Test folder</title>
<parent>cm:folder</parent>
</type>
Deploying this: any "my:test" folder will disappear, but, if I try to create another folder with the same name I get an error becouse the node still exists.
These nodes will not be not even listed within the folder child:
print(document.getChildren());
How can I recover (if possible using the the javascript console) all the "broken" nodes and be able to change the type?
A little preface: as widely stated by Alfresco, if you want to change your custom content model you should change it only incrementally.
This means that you can't remove any properties, types or aspect at definition level of the model, you only can add new definitions in the content model of Alfresco.
So it is a very bad practice to change types "on the fly".
A good practice is to always start with a model as small as you can and then add features as long as you need them.
In your case you should have deleted all nodes referencing my:test type BEFORE changing the model and then safely remove it and finally you should have performed a full reindex. This could be the reason why the repository tells you that the folder exists even if you cannot see it anymore.
As far as I know it is not possible to delete this inconsistent nodes through the console, so my advice is to perform a full reindex. If the issues come up again then you should consider to start again from scratch.
Another approach next time is to add the new type and programmatically hide the older one.

How to override template “folder_full_view_item.pt”?

This question is a reformulation of this question which had evolved in a confusing way. Please refer to this question if you search some in depth details or are interested in workarounds and alternative solutions.
This question is about the call to template folder_full_view_item.pt in folder_full_view.pt, not about other templates in general!
Please avoid workarounds like skin layers, editskinswitcher, etc. I don't want to solve a particular use case here. What I want is to really understand how this actually works.
I present this question in three parts: scenario, result, questions.
scenario
Have a Folder with a Document. The layout of the Folder is folder_full_view. The layout of the Document is document_view:
Folder (layout=folder_full_view)
Document (layout=document_view)
The template folder_full_view.pt calls template folder_full_view_item.pt via item.getObject().folder_full_view_item().
folder_full_view_item.pt calls (e.g. for a Document content type ) the template document_view.pt via use-macro="item_macro" (item_macro being something like here/document_view/macros/content-core). Schematically as follows:
folder_full_view.pt :: item.getObject().folder_full_view_item()
folder_full_view_item.pt :: use-macro="here/document_view/macros/content-core"
document_view.pt
In a plone3_theme have overriden versions of the templates folder_full_view.pt, folder_full_view_item.pt, and document_view.pt. These templates are registered as follows in configure.zcml.
<browser:page
for="*"
name="folder_full_view_item"
template="folder_full_view_item.pt"
layer="example.theme.browser.interfaces.IThemeSpecific"
permission="zope2.View"
/>
<browser:page
for="Products.ATContentTypes.content.folder.ATFolder"
name="folder_full_view"
template="folder_full_view.pt"
layer="example.theme.browser.interfaces.IThemeSpecific"
permission="zope2.View"
/>
<browser:page
for="Products.ATContentTypes.content.document.ATDocument"
name="document_view"
template="document_view.pt"
layer="example.theme.browser.interfaces.IThemeSpecific"
permission="zope2.View"
/>
results
With the theme installed the results are:
Document and Folder get their templates (I guess) via traversal. The (sub)templates though don't go through the traversal.
Folder: uses overriden folder_full_view.pt, original folder_full_view_item.pt, and original document_view.pt
Document: uses overriden document_view.pt
questions
is it the case that item.getObject().folder_full_view_item() doesn't go through traversal? If yes why?
what can be modified (in folder_full_view.pt!) to force a traversal to the overriden folder_full_view_item.pt(!) and subsequently to the overriden document_view.pt? Is this possible?
Again, please avoid workarounds like skin layers, editskinswitcher, etc. I don't want to solve a particular use case here. What I want is to really understand how this actually works.

Can not activate discussions on Plone Dexterity types (folderish)

I have been working on a dexterity based plone application.
I have created a couple of new types. This is what I did to activate comments on a specific dexterity content type named "activity_report":
In Plone Control Panel
In the Discussion section I enabled the following:
globally enable comments
enable anonymous comments
In the Types Section
I chose the "Activity Report" type from the drop down and enabled the "Allow comments" option.
On the file system
In the FTI file activityreport.xml:
<property name="allow_discussion">True</property>
I have restarted the instance and even reinstalled the product, but I can not activate the comments section in the dexterity type.
It is worth mentioning that a standard type (ex. Page) can have the discussion module activated.
Is there something I am missing?
plone.app.discussion currently disables commenting for all containers (see https://dev.plone.org/ticket/11245 for discussion).
I used a monkey patch like the following in one project to short-circuit the normal check and make sure that commenting was enabled for my folderish content type:
from Acquisition import aq_inner
from Products.highcountrynews.content.interfaces import IHCNNewsArticle
from plone.app.discussion.conversation import Conversation
old_enabled = Conversation.enabled
def enabled(self):
parent = aq_inner(self.__parent__)
if parent.portal_type == 'my_portal_type':
return True
return old_enabled(self)
Conversation.enabled = enabled
where 'my_portal_type' is, of course, the portal_type you want commenting enabled for.
The David response is not accurate. The class to be monkeypatched is plone.app.discussion.browser.conversation.ConversationView :
from Acquisition import aq_inner
from plone.app.discussion.browser.conversation import ConversationView
old_enabled = ConversationView.enabled
def enabled(self):
parent = aq_inner(self.__parent__)
if parent.portal_type == 'My_type':
return True
return old_enabled(self)
It works for Plone 4.2 at least. However, thanks David for the hint.
As David and Victor already pointed out, you can just override the enable method of the conversation class. I would recommend using the following approach which is a bit cleaner than monkey patching the conversation class:
https://github.com/plone/plone.app.discussion/blob/master/docs/source/howtos/howto_override_enable_conversation.txt
I also added support for dexterity types to plone.app.discussion recently, so as soon as there is a new release you won't need to customize the conversation class any longer:
https://github.com/plone/plone.app.discussion/commit/0e587a7d8536125acdd3bd385e880b60d6aec28e
Note that this method supports commenting ON folderish objects. There is no support to enable/disable commenting for objects INSIDE a folderish object yet.
In case you want to be able to switch on/off commenting with a behavior field/widget:
https://github.com/plone/plone.app.dexterity/commit/0573df4f265a39da9efae44e605e3815729457d7
This will hopefully make it into the next plone.app.dexterity release as well.
I solved in configure.zcml:
<interface interface="Products.CMFPlone.interfaces.INonStructuralFolder" />
<class class="Products.PloneHelpCenter.types.Definition.HelpCenterDefinition">
<implements interface="Products.CMFPlone.interfaces.INonStructuralFolder" />
</class>
UPDATE: this is not a good idea. I had problems with missing Add menu for each content type having this fix.

Resources