How can I ask the state for a content object? - plone

At the end of this tutorial several object attributes are listed. But I need access to the state (published, private,...). I also search that attribute using dir() but I don't see an attribute named as state or something similar. i.e, I need something like this:
>>> app.Plone.foo.bar.state
"published"

Or to keep your code more readable and not having to remember strange method names, you can use plone.api to do this:
from plone import api
api.content.get_state(obj=your_object)
Of course, you need to add plone.api to your eggs first, and re-run buildout.

You can always use the plone_workflow to determine current status:
workflowTool = getToolByName(self.portal, "portal_workflow")
status = workflowTool.getStatusOf("plone_workflow", object)
# where "object" is your content object
print (status)

Unfortunately there is no "state" attribute. Instead, check review_state using the workflow tool e.g.:
>>> app.Plone.portal_workflow.getInfoFor(app.Plone.foo.bar, "review_state")

Related

Programmatically add key mappings in Atom

I'm creating several commands programmatically and want to avoid having to add key mappings for them explicitly in keymap.cson.
The Flight Manual page for Keymap Manager shows an add method. It doesn't give an example of how to actually use this method, so my guess is that this should work:
atom.keymaps.add('atom-text-editor',{'alt-1':'custom:my-command'});
However, this does not appear to work. When I run this in the developer console, I get this message:
Encountered an invalid key binding when adding key bindings from 'atom-text-editor' 'custom:my-command'.
I got this message even if I changed alt to ctrl.
What does the correct method call on atom.keymaps look like.
I agree, the docs are not detailed enough. However, through trial and error, I managed to figure it out:
atom.keymaps.add('foo', {
'atom-text-editor' : {
'alt-1': 'custom:my-command',
'#': 'application:about'
// etc
}
});
Explanation:
atom.keymaps.add(source, bindings, priority);
The source argument is not the same as what is referred to as the selector in Atom speak. Instead, it's an identifier that can be used to remove the keybindings, should you wish to (except it seems they haven't actually implemented a remove method!).
Instead, the selector should go inside the bindings argument, as shown above.

How to loop a "Multiple String" from a ProductBO object in an ISML-Template?

How can I loop a Multiple String from a ProductBO object? What is the best way to do this?
As long as you know the name of the attribute you may use the following method on ProductBO from within an ISML:
public AttributeValue getAttributeValue(String aName);
The storefront app comes with a convenient albeit not extremely flexible module that is able to display AV-s. It works for multiple attributes too. The name of the module is ISCustomAttribute.
Sample usage:
<isCustomAttribute
attributelabel="#AttributeDescriptor:DisplayName#"
attributevalue="#ProductBO:AttributeValue(AttributeDescriptor:ID)#"
attributeseparator=", ">
The best would be if you use this module. You may see it in action. Custom ProductBO attributes are printed on the product details page in the storefront as the next image shows (#see DetailsTab.isml):
If this does not fit, you will have to retrieve the attribs as something iterable. The way I think fits best is to use the BO extension BusinessObjectAttributes. You will be able retrieve a BusinessObjectAttribute by name from it and loop through its value.
<isloop iterator="BusinessObjectAttribute:Value" alias="AValue" counter="counter">
<!--- Do something gorgeous here --->
</isloop>

Ploneinfo (as in phpinfo)

What is the most sraightforward (but not very hackish - unPlonish) way to create a "page" in Plone (v 4.x), which would show some Plone internals info? I'd like to generate a page document, which would paste dir() (or whatever my own function) result to <pre/> or something like that. Straightforward.. i mean, without having to create a Plone product or having to modify server files directly - just using ZMI..
You want to install plone.app.debugtoolbar
http://pypi.python.org/pypi/plone.app.debugtoolbar/
which gives you access to the most imporant informations about the current context object, request data etc.
Products.DocFinderTab adds a "Doc" tab in the ZMI that allows you to explore the current object and its methods. If you installed with the Unified Installer and use the "develop" configuration, it's already loaded.
Products.Clouseau may still work with recent Plone's, though it's aging. It gives you an AJAX interface to explore the context from within Plone.
Finally, to explore the request object, you may just add:
<div tal:replace="structure request" />
to a template. That will allow you to check all the HTTP and form variables as well as what's stored in the request.
Go to the ZMI, add a "Script (Python)", and define your function dir() and print the result like this :
print dir()
return printed

Why does my content object not show up in the portal_catalog?

I am trying to implement a basic Zope2 content type directly without using dexterity or Archetypes because I need this to be extremely lean.
from OFS.SimpleItem import SimpleItem
from Products.ZCatalog.CatalogPathAwareness import CatalogAware
from persistent.list import PersistentList
class Doculite(SimpleItem, CatalogAware):
""" implement our class """
meta_type = 'Doculite'
def __init__(self, id, title="No title", desc=''):
self.id = id
self.title = title
self.desc = desc
self.tags = PersistentList()
self.default_catalog = 'portal_catalog'
def add_tags(self, tags):
self.tags.extend(tags)
def Subject(self):
return self.tags
def indexObject(self):
self.reindex_object()
From an external method I am doing this:
def doit(self):
pc = self.portal_catalog
res1 = pc.searchResults()
o1 = self['doc1']
o1.add_tags(['test1', 'test2'])
o1.reindex_object()
res2 = pc.searchResults()
return 'Done'
I clear the catalog and run my external method. My object does not get into the catalog. But from the indexes tab, when I browse the Subject index, I can see my content item listed with the values. Both res1 and res2 and empty.
Why is my content item not showing up inside the searchResuts() of the catalog?
Plone is a full-fat content management system, if you're after something lean it's probably not the right choice (perhaps try Pyramid.)
For your content type to be a full part of a Plone site it has to fulfil a number of requirements across the Zope2, CMF and Plone layers. plone.app.content.item.Item is about the simplest base class you can get for a content item for a Plone site, though a simpler base class in itself will not really make instances of your content type any more 'lean' - an instance of a class in Python is basically just a dict and a pointer to it's class.
Most of the work on a page view will be rendering the various user interface features of a site. Rendering the schema based add/edit forms of frameworks like Archetypes and Dexterity is also relatively expensive.
I'd spend a little time profiling your application using one of the supported content type systems before putting time into building your own.
In order to see your objects in the "Catalog" tab of the portal_catalog your objects need to have a "getPhysicalPath()" method that returns a tuple representing their path (ex. ('','Plone','myobject')).
Also try to use this:
from Products.CMFCore.CMFCatalogAware import CMFCatalogAware
as base class.
You need to register your type with the catalog multiplexer. Look at the configuration in the zmi -> archetypes_tool.
I'm not sure, but you may also need a portal_type registration also...
Like Lawrence said though, you're better off just using one of the current content type frameworks if you want to be able to catalog your data with plone's portal catalog. If you can deal with a separate catalog, take a look at repoze.catalog.
Plone needs every content object to provide an "allowedRolesAndUsers" index to return the object in searchResults.
There is probably a zcml snippet that will enable this for my content type. But I was able to get things working by adding another method as follows:
def allowedRolesAndUsers(self):
return ['Manager', 'Authenticated', 'Anonymous']
CatalogAware will be removed in Zope 4 and then can't be used any more.
cf https://github.com/zopefoundation/Products.ZCatalog/issues/26

Custom date format (callback with php logic)

I want to create a dynamic php date format. Example: show the time of the node if it was published today and only the day/month when older then today. I want this format to be available throughout Drupal like the other predefined date formats in Drupal (not just on theme level).
I found the (D7 only) hook for hook_date_format_types but even that one doesn't seem to allow for a callback where I could define this PHP logic.
Does anyone know which hook would make this possible? Or a module which does this?
In Drupal6, format_date() has the dates and times hardcoded. Also, format_date() does not allow callbacks, but it does allow a custom string. That is where you can apply a trick: instead of hardcoding the string in there, you call a function that returns a string.
function mydate_format($timestamp) {
$now = time();
if (($now - $timestamp) < (60*60*24)) {
return "H:i";
}
else {
return "d:m:Y";
}
}
print format_date($timestamp, 'custom', mydate_format($timestamp));
The second option is to re-define a date-timestamp, but that is both hackish and limited. Date-formats are defined with variable_get(), but don't pass the timestamp along; so your example of switching formats based on the value of timestamp is not possible this way.
In settings.php:
$conf['date_format_long'] = $conf['debug'] ? 'r' : 'l, F j, Y - H:i';
This will switch from one value to another, based on whether your settings.php has a flag "debug" set to TRUE or not. As mentioned: the use for this is limited, since you cannot get any context.
The third alternative is to use Date API which offers onlinle configurable time-formats. But that is both clumsy and insecure (inputting executable PHP in your database). It also depends on a very large module-set. And has the same downside as the first solution: you cannot use format_date, but must use a modified function call, instead of format_date(). See all the options at The Drupal.org date themeing handbook.
GOTCHA In all cases Drupal will not call this function for cached content. If you want to have the dates really dynamic you either need to avoid caching alltogether, or implement the date-formatting in clientside javascript.
TL;DR: You cannot have dynamic date-formats without changing some of the code on theme-level. Using a callback-function to generate the "custom" dateformat is the simplest, working solution.
You can use Date API module to add your custom date formatting. Date API module is inside the Date module. After enabling the Date API module you can go the path "admin/settings/date-time/formats/add" to add your custom format.
"admin/settings/date-time/formats/configure" is the path to configure date formats.
Have a look at these. Happy coding.
Thanks
RT
You can go to node.tpl.php(possibly in sites/all/themes/theme_name/node.tpl.php). Here yo can find $created variable, to reformat date you can use your custom function and change the $created as you want.After this all nodes will use your formatted dates.
Regatds,
Chintan.
Use the features module. Create a feature.
In the resulting feature module, on the [feature].module file, create a hook_nodeapi function and format the field with a conditional statement that takes into account the current date() for how the date will be displayed and feed it into the $node->content var.
And that is the way rockstars would do it (-;

Resources