Drupal 7 - Hide 'remove' button on file field - drupal

I have a content type with an image field. Users can create the content and upload an image. I'd like to not allow users to change/remove the image once it was uploaded, but still show the image on the node edit form. So I only need to disable/remove the 'remove' button from the image field.
I tried the following (via hook_form_alter), but it didn't work:
$form['field_image']['#disabled'] = TRUE;
The below works, but it hides the image element completely, which is not what I'm after:
$form['field_image']['#access'] = FALSE;
Please help to find a workaround.

You have to use the hook_field_widget_form_alter function and inside there look for the variable details using dpm() and then alter the button using an attribute from the Forms API.
But I would suggest to make the widget field read only on the edit form and not remove the delete button.
// Hide remove button from an image field
function MYMODULE_field_widget_form_alter(&$element, &$form_state, $context) {
// If this is an image field type
if ($context['field']['field_name'] == 'MY_FIELD_NAME') {
// Loop through the element children (there will always be at least one).
foreach (element_children($element) as $key => $child) {
// Add the new process function to the element
$element[$key]['#process'][] = 'MYMODULE_image_field_widget_process';
}
}
}
function MYMODULE_image_field_widget_process($element, &$form_state, $form) {
//dpm($element);
// Hide the remove button
$element['remove_button']['#type'] = 'hidden';
// Return the altered element
return $element;
}
Useful issues:
Drupal 7: How to alter image field widget "alt" or title" label
How to disable a field or make it readonly in Drupal 7
https://drupal.stackexchange.com/q/32861/12163

You can also do it using hook_form_alter and after_build function
// hook_form_alter implementation
function yourmodule_form_alter(&$form, $form_state, $form_id) {
switch ($form_id) {
case 'your_form_id':
$form['your_file_field'][LANGUAGE_NONE]['#after_build'][] = 'yourmodule_hide_remove_button';
break;
}
}
// after_build function
function yourmodule_hide_remove_button($element, &$form_state) {
// if multiple files are allowed in the field, then there may be more than one remove button.
// and we have to hide all remove buttons, not just the one of the first file of the field
//
// Array
// (
// [0] => 0
// [1] => 1
// [2] => #after_build
// [3] => #field_name
// [4] => #language
// [5] => ...
// )
//
// the exemple above means we have 2 remove buttons to hide (2 files have been uploaded)
foreach ($element as $key => $value){
if (is_numeric($key)){
unset($element[$key]['remove_button']);
} else break;
}
return $element;
}

Related

Change field value and submit node with a custom button

I am attempting to write a module that adds a button to a node type that, when pressed, will change a value of a field in that node and submit the changes. Everything seems to be working, as the button appears correctly and the node submits when it's pressed, but the value of the field remains unchanged. I feel like I'm missing something obvious.
<?php
function iu_buttons_node_view($node, $view_mode, $langcode) {
if ($node->type == 'billing_entry') {
if ($node->field_status['und'][0]['value'] == 'open') {
$form = drupal_get_form('submit_button_form');
$node->content['submit_button'] = $form;
}
}
}
function submit_button_form($form, &$form_submit) {
$form['submit'] = array(
'#type' => 'button',
'#value' => ('Submit'),
'#submit' => array('submit_button_form_submit'),
);
return $form;
}
function submit_button_form_submit($form, &$form_state) {
$node->field_status['und'][0]['value']['#value'] = 'submitted';
}
It's probably worth noting that the field I'm trying to change is a select list. Should I be using a different function than hook_form_submit?
I am assuming you are writing this code in a custom module named iu_buttons and you want to display this button in the node page, not in the node edit form.
In this case, the problem is that you never saved the node in your submit function. Here is a version of your submit function that will save the node.
function submit_button_form_submit($form, &$form_state) {
$node = menu_get_object(); //get the current node
$node->field_status['und'][0]['value']['#value'] = 'submitted';
node_save($node); // save the changed node
}
I think you may be interested in saving only the field, without the need to save the whole node. In this case, you might use the following:
function submit_button_form_submit($form, &$form_state){
$node = new stdClass(); // Create empty object
$node->nid = intval(args(1)); // Include the nid so that Drupal saves the new value to the correct node
$node->field_status['und'][0]['value']['#value'] = 'submitted';
field_attach_update('node', $node); // Save the field
}

Add custom icon to orders' list view in Prestashop

I would like to add new button to order's list view, but I have no idea how to do it:
I want to do it in way that new upgrade will not delete it.
Edit: This new button will just open new browser window so it's completely independent of PrestaShop functionalities. But I would like to put it in this toolbar line.
Thank you for your help!
You could do it with overrides. Create a file called AdminOrdersController.php in your overrides/controllers/admin/ folder, and add the following:
<?php
class AdminOrdersController extends AdminOrdersControllerCore
{
public function initPageHeaderToolbar()
{
parent::initPageHeaderToolbar(); // this will assign native icons
// This is where you add you custom icon
$this->page_header_toolbar_btn['my_custom_icon'] = array(
'href' => self::$currentIndex.'&mycustomaction&token='.$this->token,
'desc' => $this->l('My custom action', null, null, false),
'icon' => 'process-icon-save'
);
}
public function initProcess()
{
parent::initProcess();
if (Tools::getIsset('mycustomaction')) {
if ($this->tabAccess['view'] === '1') {
$this->display = 'mycustomaction';
$this->action = 'mycustomaction';
}
else
$this->errors[] = Tools::displayError('You do not have permission to edit this.');
}
}
public function initContent()
{
parent::initContent();
if ($this->display == 'mycustomaction')
$this->content.= $this->renderMyCustomAction();
}
public function renderMyCustomAction()
{
// this is where you render your custom page.
}
}
Note that this is a quick mock up. It should work, though :)
UPDATE
If you just want the icon to open a new page, leave only the initPageHeaderToolbar method and provide the right href attribute, you can delete the initProcess, initContent and renderMyCustomAction methods. I'll leave them in my original reply in case someone else finds it useful.

How to add a body class for the current node's taxonomy to a Drupal 7 theme

Does anyone know how or can guide me in the right direction on how to add a body css class for the current node's taxonomy term? i.e. <body class="term-dogs"> where "dogs" is the taxonomy term name. It could also be just the term ID. Either way is fine I just need a solution. This will be for a Drupal 7 zen sub-theme
This answer took longer than I expected to figure out. The hard part was collecting the terms on the node, since All taxonomy functions relating to nodes have been removed or refactored. Ultimately, page 355 of Pro Drupal 7 Development saved the day with a snippet that does the job previously handled by taxonomy_node_get_terms.
Below is the code that worked for me (look for the part that says "MAGIC BEGINS HERE"). Assuming you're creating a sub-theme of Zen, you'll want to move this to your sub-theme's template.php file and rename it to YOURSUBTHEMENAME_preprocess_html:
/**
* Override or insert variables into the html template.
*
* #param $vars
* An array of variables to pass to the theme template.
* #param $hook
* The name of the template being rendered ("html" in this case.)
*/
function zen_preprocess_html(&$vars, $hook) {
// If the user is silly and enables Zen as the theme, add some styles.
if ($GLOBALS['theme'] == 'zen') {
include_once './' . drupal_get_path('theme', 'zen') . '/zen-internals/template.zen.inc';
_zen_preprocess_html($vars, $hook);
}
// Classes for body element. Allows advanced theming based on context
// (home page, node of certain type, etc.)
if (!$vars['is_front']) {
// Add unique class for each page.
$path = drupal_get_path_alias($_GET['q']);
// Add unique class for each website section.
list($section, ) = explode('/', $path, 2);
if (arg(0) == 'node') {
if (arg(1) == 'add') {
$section = 'node-add';
}
elseif (is_numeric(arg(1)) && (arg(2) == 'edit' || arg(2) == 'delete')) {
$section = 'node-' . arg(2);
}
// MAGIC BEGINS HERE
$node = node_load(arg(1));
$results = field_view_field('node', $node, 'field_tags', array('default'));
foreach ($results as $key => $result) {
if (is_numeric($key)) {
$vars['classes_array'][] = strtolower($result['#title']);
}
}
// MAGIC ENDS HERE
}
$vars['classes_array'][] = drupal_html_class('section-' . $section);
}
if (theme_get_setting('zen_wireframes')) {
$vars['classes_array'][] = 'with-wireframes'; // Optionally add the wireframes style.
}
// Store the menu item since it has some useful information.
$vars['menu_item'] = menu_get_item();
switch ($vars['menu_item']['page_callback']) {
case 'views_page':
// Is this a Views page?
$vars['classes_array'][] = 'page-views';
break;
case 'page_manager_page_execute':
case 'page_manager_node_view':
case 'page_manager_contact_site':
// Is this a Panels page?
$vars['classes_array'][] = 'page-panels';
break;
}
}
I needed to know how to do this and Matt V's solution worked perfectly. I made a couple of additions to his work. I called drupal_html_class which replaces spaces and invalid characters. And I added in the term ID to allow you to target a term even if the name of the term changes.
// MAGIC BEGINS HERE
$node = node_load(arg(1));
$results = field_view_field('node', $node, 'field_tags', array('default'));
foreach ($results as $key => $result) {
if (is_numeric($key)) {
// Call drupal_html_class to make safe for a css class (remove spaces, invalid characters)
$vars['classes_array'][] = "taxonomy-" . strtolower(drupal_html_class( $result['#title']) );
// Add taxonomy ID. This will allow targeting of the taxonomy class even if the title changes
$vars['classes_array'][] = "taxonomy-id-" . $result['#options']['entity']->tid ;
}
}
// MAGIC ENDS HERE
Not sure what you mean with that body tag, but the classes on the node are generated here:
http://api.drupal.org/api/drupal/modules--node--node.module/function/template_preprocess_node/7
You can add more by implementing yourmodule_preprocess_node($vars) and then add whatever you want to $vars['classes_array']

Drupal 6 Form Api adding an item to an existing form

I want to add a new item into an existing form. I have the ID of the form and I know I need to use hook form_alter but not sure how to add it.
function modulename_form_alter(&$form, $form_state, $form_id) {
switch ($form_id) {
case 'form id goes here':
// Need to do something here....
break;
}
}
Because the &$form variable is a reference, whatever you do to it changes the original value. so just add it to $form;
//After, need to do something here:
$form['my_new_field'] = array(
'#type' => 'select',
//etc..
);
//You can also add a new validation here:
$form['#validate'][] = 'my_valiation_callback';
See the drupal api ref for better details:

How do I alter the #weight of the content generated by the upload.module?

On my Drupal powered website, I want to list available downloads at the top of a node page (within a narrow float:right <div>), not at the bottom where they normally appear.
Within my theme, I've overridden the theme_upload_attachments() function to generate a <div> of width 40%, but this is showing up at the bottom of the page.
Within the upload.module file is code that controls where the attachments are listed on the page:
// function upload_nodeapi(), line #284 of upload.module
$node->content['files'] = array(
'#value' => theme('upload_attachments', $node->files),
'#weight' => 50,
);
If I manually hack this #weight to -1, my custom list of attachments shows where I want, floating at the righthand side of the top of the content area.
However, I don't want to manually hack the core file upload.module, as my changes will be lost next time I apply an upgrade (say, for a security patch).
How/Where do I modify the #weight of content['files'] within my theme code?
Or, am I going about this the wrong way?
You'll need a module to do this, not just a theme. A module can implement hook_nodeapi(), which will give it a chance to change the contents of that $node->content array before it's rendered. If your module is named 'upload_tweaker' for example, you'd use the following function:
function upload_tweaker_nodeapi(&$node, $op) {
if ($op == 'view') {
$node->content['files']['#weight'] = -1;
}
}
Each module gets a crack at changing the node during this 'nodeapi' event; if you want to change the stuff that's added by one module, you need to make sure that your module loads after it. This can be done by naming it something like 'zzz', or by changing its "weight" field in the system table of your site's database. Modules can be weighted just like form elements.
api.drupal.org has more information.
For those who uses CCK and want to alter body weight:
CCK module uses pre_render function
/**
* Pre-render callback to adjust weights of non-CCK fields.
*/
function content_alter_extra_weights($elements) {
if (isset($elements['#content_extra_fields'])) {
foreach ($elements['#content_extra_fields'] as $key => $value) {
// Some core 'fields' use a different key in node forms and in 'view'
// render arrays. Check we're not on a form first.
if (!isset($elements['#build_id']) && isset($value['view']) && isset($elements[$value['view']])) {
$elements[$value['view']]['#weight'] = $value['weight'];
}
elseif (isset($elements[$key])) {
$elements[$key]['#weight'] = $value['weight'];
}
}
}
return $elements;
}
So due to this callback you are not able to alter weight using normal behavior.
You should do this:
function YOUR_MODULE_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
// Only for node pages.
if ($op == 'view' && $a4) {
$body_weight = 15 // Any weight.
$node->content['#content_extra_fields']['body']['weight'] = $body_weight; // This value CCK module will use to alter body weight in the callback from above.
}
}

Resources