Jump to content

Hide publish button


Pete
 Share

Recommended Posts

Is there a way to hide the publish button for a user?

I've had a look around the forums and I can't see that this has come up before, but what I'd like to do is have it so that certain user groups can add pages, edit and save them but not publish them.

The idea is that the new pages then have to be approved by someone with higher permissions before the page appears on the site.

Linked into this, I'd also like the ability for the user not to be able to edit a page once it's published if that makes sense? So they can add a page (article in this case) tweak it and edit it, let someone with higher perms check over it and publish it, and then at that point the author wouldn't be able to edit the page.

I feel like this should be reasonably easy to accomplish with a module but just need a friendly shove in the right direction ;)

Something completely different that crossed my mind but would be useful in my situation (and maybe others?) would be the ability to hide a field depending on the user group and set a default value instead. The scenario for this is articles again - I've been using an autocomplete field to tag authors to articles (very occasionally it will have multiple authors), but for users of a certain group I'd like this field to be hidden instead and default the value to their user ID - not sure if that's actually possible? It's not 100% necessary, but again if there's a way to do it with a module I'd happily give it a shot :)

Just as an extra, yet not entirely relevant, piece of information, I was also considering adding a checkbox to the end of the Article temlpate so that the author could then tick the box to say it's ready for review by an editor, and then have a list of articles ready for review on the admin homepage. That might be of interest to someone else working on some sort of approval-based site section, so I'll happily share the code :)

Link to comment
Share on other sites

Pete, I've added support for page-publish permission. To use it, grab the latest commit and then create a new permission in Setup > Access > Permissions, called 'page-publish'. Once PW sees that there, it'll start to use it. So if you create a role that has page-edit but not page-publish permission, you should get behavior consistent with what you mentioned above. Please test it out and let me know how it works for you.

Field-level access is something that is planned, where you can limit edit access to a field by role. But probably not till version 2.3.

Link to comment
Share on other sites

Thanks - that looks awesome! I'll have a play with it tomorrow at some point :)

Like the sound of field-level access too - there's a lot of great stuff on the roadmap.

Keep up the good word!

Link to comment
Share on other sites

  • 5 months later...

I'm accessing PW at present and must say I'm really impressed with what I''ve seen so far.

+1 for field level access. I use this facility in modx for virtually every client-editable site (using modx plugins). Perhaps I'm stuck in a certain mode of thinking from using modx for so long, and there's more than one way to skin a cat, but I love in modx that I can have a field from which I can easily issue instructions to a template on a per page basis, which must not be visable/editable to the client. It allows me be reuse the same template for quite different pages.

For example, in my modx sites I have "content", "preContent" and "postContent" fields. Only the content field is available to the client, the pre and post content fields simply allow me to add instructions to output something specific on a page directly before or after the clients content. Sure, there are other ways to do this (how do you guys achieve this in PW?) but I love this method as it's so simple and easy to edit.

BTW, PW looks like an incredibly good piece of kit and the forums seem super-friendly - I love modx and it's been good to me but it doesn't quite feel right sometimes, whereas PW seems to have a nice clean feel to it. So far I think PW has covered all the bases for my needs, except for a form processor for simple validating and re-populating forms. It's possibly a little beyond my coding level but I might just have to have a dig at writing one. Well done PW team, beautiful work. :)

  • Like 2
Link to comment
Share on other sites

I think in this case you probably wouldn't have those two fields at all.

It almost sounds like a case for putting any pre and post content code in the template file instead if it's not going to change much? That's fine of course unless you want to use those fields to have slightly different content on a per page basis?

One of the things that is quite different coming from MODx that I found was that you learn that creating many templates for different content in PW is a great help whereas in MODx it became a bit of a chore I found as it just wasn't as easy to assign fields to templates.

Not sure if that was of any help :)

And then I re-read your post and you are trying to do it on a per page basis.

Ignore me ;)

Link to comment
Share on other sites

I'm accessing PW at present and must say I'm really impressed with what I''ve seen so far.

+1 for field level access. I use this facility in modx for virtually every client-editable site (using modx plugins). Perhaps I'm stuck in a certain mode of thinking from using modx for so long, and there's more than one way to skin a cat, but I love in modx that I can have a field from which I can easily issue instructions to a template on a per page basis, which must not be visable/editable to the client. It allows me be reuse the same template for quite different pages.

For example, in my modx sites I have "content", "preContent" and "postContent" fields. Only the content field is available to the client, the pre and post content fields simply allow me to add instructions to output something specific on a page directly before or after the clients content. Sure, there are other ways to do this (how do you guys achieve this in PW?) but I love this method as it's so simple and easy to edit.

There's no field access yet, but I've heard rumors that it will come sooner or later. ;)

However you can create a simple module that does hide/show fields on a condition, whether a custom permission, role or user.

Following is a simple autoload module that hooks the Inputfields and returns empty string, if condition aren't met. Actually very straight forward and powerful. There could be added some module configuration, to simply add fields via a textfield you want to hide for other users. Possibilities are endless.

Save the code as FieldHelper.module and put it in /site/modules/

Configure it to your needs and install it.

<?php

class FieldHelper extends WireData implements Module {

/**
 * getModuleInfo is a module required by all modules to tell ProcessWire about them
 *
 * @return array
 *
 */
public static function getModuleInfo() {

	return array(
		'title' => 'FieldHelper',
		'version' => 100,
		'summary' => 'Hide fields depending on permission, role, or user.',
		'singular' => true,
		'autoload' => true
		);
}

public function init() {
	// add after-hook to the inputfield render method
	$this->addHookAfter("Inputfield::render", $this, "renderField");
}

/**
 * Hide fields depending on permission or possibly role, user
 *
 */
public function renderField(HookEvent $event) {
	// get the current field
	$field = $event->object;

	// example 1permission
	if($field->name == "pre_content") {
		if(!$this->user->hasPermission("admin-fields")){
			$event->return = '';
		}
	}
	// example 2 role
	if($field->name == "after_content") {
		if(!$this->user->hasRole('superuser')){
			$event->return = '';
		}
	}
	// example 3 user
	if($field->name == "page_scripts") {
		if(!$this->user->name('admin')){
			$event->return = '';
		}
	}
}

}

I created a gist for this example here: https://gist.github.com/3122191

  • Like 4
Link to comment
Share on other sites

Pete is right that if you had fields you didn't want to be editable to your client, then you probably wouldn't keep them as fields at all. Instead, you'd handle such things from your template file. Though I think there is value in having field-level access, and so Soma is also right that it'll be coming to ProcessWire soon. In fact, it's a real simple fit with the existing system. I suppose the only reason we don't have it yet is just that it hasn't really come up as a common need, and we tend to be pretty cautious about adding too much (always balancing simplicity with capability). That's a great module example that Soma put together there too, seems like a good way to solve it at least until the capability is in the core.

Link to comment
Share on other sites

Thanks guys, beautiful module Soma, I'll be giving that some more thought and trying it out for sure.

Maybe I'm stuck in a modX way of thinking, I dunno. I do love the feel of PW so far and a big part of that is the simplicity you talked about Ryan, so I can understand you not wanting to complicate things too much by adding too many options/capabilities. It's an outstanding system and obviously really well thought out.

Ryan, I'm not sure I argee however that this should be done from a template; the reason I like an ability to inject data into any page in certain places (hence fields preContent, postContent etc) without having to write a different template for each page (or use lots of conditional coding in one template), is that for example, I can drop a call in to run a snip of php to insert a google map or other random stuff, or simply add some data to a page which I don't want the client to have access to edit - if the code is not editable by the client then they can't mess it up (which clients are awesome at doing given the opportunity!). Doing that from a template on a per-page basis seems messy and awkward to me - if I have one template that services 100 pages, and they each have different content which I don't want the client to be able to edit, managing this in the template file would be nightmarish. Or am I missing something? :-

Link to comment
Share on other sites

I think the thing we're missing in this discussion is a solid scenario.

The MODx way you mention is one I've used myself - sticking in a field where I can drop a bit of code in (in my case a field where I can add page-specific JavaScript but it was only on a tiny site and that could have been handled in an external JS file by tagging the body tag with the page name as an ID since the code would never change), but I only ever did that on one of my personal sites and I've not needed to do that in PW.

If you could give an example of where like you say you might have a hundred pages but want to add different code to each then we can possibly offer you a solution you may not have thought of :)

Link to comment
Share on other sites

In terms of a Google map page, you generally have one of these on a website so a different template would be the solution for that one. If you were building a real estate website and needed one map per property then you would have a property template and have the map code in that template file (presumably with the pin location being determined from an address the user has entered into an address field). Both of these scenarios would preent the user messing up the map code whilst still not requiring lots of different templates.

That said they're only specific examples.

I think that one solution here that might be something that could be built on top of Soma's example is to have a hidden tab of fields you want to keep away from the user. You may not be aware but you can create new tabs that are visible on the edit screen itself, so it seems like it should be reasonably easy to code something to hide a whole tab (would require some PHP for checking perms and probably a little JS to hide the tab). That said, Soma's solution would still leave the fields in place in the page flow if you prefer, but I was thinking a hidden tab for your fields would be more flexible as you can easily add more fields to it without tweaking any code.

Link to comment
Share on other sites

As a suggestion for how to implement 'per field' permissions, I like the idea of having an option in all fields created for 'use permissions for editing this field' (which is off by default - meaning that most fields don't bother with permissions checking and also helping with backward compatibility). If this is on then there should be a field to enter the permission name. It should default to something related to the field's name (maybe field-[name] or something) but can be changed if required in the same way a page alias can.

This would allow for both one-off permissions for fields (as mentioned above) and grouped permissions. As an example of what I mean, say that most site editors can edit certain customer info but not 'private' fields. The fields that are private may have the permission name set to 'edit-private-fields'. This means more than one field can now be controlled by one permission without making a complex interface, just like the page alias is usually out of the way and only changed if needed.

Sorry if that wasn't clear; I'm tired and my brain is rambling :)

Link to comment
Share on other sites

If this is on then there should be a field to enter the permission name. It should default to something related to the field's name (maybe field-[name] or something) but can be changed if required in the same way a page alias can.

I think these sound like good ideas.

I was initially thinking the fields permission would work very similar to how it does in the Template editor (for consistency). Something like this:

Setup>Fields>[field] editor would have an 'Access' tab or fieldset. It would say "Do you want to manage edit access for this field?". If No, it doesn't have anything else. If Yes, then you get a list of roles where you can check the box for the roles you want it to be editable for.

When you want to do grouped permissions, you'd use a role, as their purpose is to group permissions for users. (Roles are a many-to-one relationship with users). To reuse your example, you'd name the role 'edit-private-fields' if you wanted to isolate permissions for a group of fields.

I was also thinking the access could be a component of the field-template context modal dialog, so that you could grant a role access to edit the 'body' field in one template, and not in another. Though that may be going farther than we need to.

  • Like 1
Link to comment
Share on other sites

I don't think that's going too far with template specific field perms ryan - could be useful on larger sites where fields are more likely to get re-used many times.

  • Like 1
Link to comment
Share on other sites

  • 10 months later...

@Soma

I want to hide a field based on the id of the parent page, whoever the following does not work:

public function renderField(HookEvent $event) {
        // get the current field
        $field = $event->object;

        if($field->name == "product_category") {
            if($page->parent->id == 6) {
                $event->return = '';
            }
        }
        
    }
 
 
I guess my question is: How can I refer to the current page from within a module?
 
Cheers, 
 
Stefan
 
Link to comment
Share on other sites

Stefan,

From what I understand, In modules and in functions $page is always out of scope (?). In functions, use wire ('page') or $wire->page instead since is global. In modules use $this ->

//These two are equivalent, so what syntax you prefer to use is up to you:
//http://processwire.com/api/include/

$mypage = $wire->pages->get("/about/contact/"); 
$mypage = wire('pages')->get("/about/contact/"); 
See also http://processwire.com/talk/topic/3638-this-scope-in-modules/?p=35554

http://processwire.com/talk/topic/3056-cant-use-input-urlsegment1-in-a-function-is-this-my-php-weakling-status-showing/?p=30044

  • Like 1
Link to comment
Share on other sites

wire("page") in this context will give you the admin edit page and not the page editing.

In this case you can get the page edited through ProcessPageEdit.

if($this->process = "ProcessPageEdit") {
    $page = $this->process->getPage();
}
  • Like 2
Link to comment
Share on other sites

I updated the code and now everything is working:

public function renderField(HookEvent $event) {
        // get the current field
        $field = $event->object;
        // example 1permission
        if($field->name == "product_category") {
            if($this->process->getPage()->template == 'offer') {
                $event->return = '';
            }
        }
        
    }
 

Soma, thanks a lot for your help!

Cheers, 

Stefan

Link to comment
Share on other sites

@kongondo

It did not know the difference between $page and wire('page). Only a few days ago I ran into a situation where $page was not recognized. Now I think using wire('page') instead would have done the trick.

Cheers, 

Stefan

Link to comment
Share on other sites

  • 1 year later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...