drupal - Change the view in the module - php

I want to change the view of the module depending on the Url. All in php.
I created two views putting this data:
function config_services_block_info() {
$blocks['config_services'] = array(
// The name that will appear in the block list.
'info' => t('Services'),
// Default setting.
'cache' => DRUPAL_CACHE_PER_ROLE, );
$blocks['orderservices'] = array(
// The name that will appear in the block list.
'info' => t('Order Services'),
// Default setting.
'cache' => DRUPAL_CACHE_PER_ROLE, );
return $blocks;
}
function config_services_block_view($delta = '') { switch ($delta) {
case 'config_services':
...
block[content] = ...;
return block;
break;
case 'orderservices':
...
block[content] = ...;
return block;
break; } }
function config_services_menu() { $items = array();
$items['config_services/orderservices'] = array(
'title' => t('Order Services'),
'page callback' => array('_config_services_orderservices_page'),
'access arguments' => array('order config_services content'),
'type' => MENU_CALLBACK, //Will appear in block. ); return $items; }
In _config_services_orderservices_page() I think this but no work:
function _config_services_orderservices_page() {
config_services_block_view('orderservices');
}
The first view works, the problem is when I want the second view. How I change the view for the url: http:(slash)(slash)name-web/config_services/orderservices

Depending on the condition you want to change the view, the condition could be checked inside _config_services_orderservices_page() function, and specific block could be displayed.
function _config_services_orderservices_page() {
if (your_condition == 'orderservices') {
config_services_block_view('orderservices');
}
if (other_condition == 'config_services') {
config_services_block_view('config_services');
}
}
On a side note, view in Drupal means something totally different. It is the most popular and most used module overall. Please visit the project page, and the documentation.
And what you refer to is about blocks.

Related

Trying to remove/hide fields in custom tab in SilverStripe

I am trying to figure out a way (if possible) to remove or hide certain fields in a custom tab. The custom tab is labeled "Rotator" and it holds images that can be used for a rotating banner on a page. The home page banner is a little different in that it has 2 extra fields that aren't needed on the subpages: BackgroundImage and Body(which is meant to hold a variety of text). I want to make things simple for the content manager, so I want to hide these fields on the subpages.
I am aware of removeFieldFromTab and how it works, and I was thinking of using it on the Page.php file (since that is basically the main template for all page types in my SilverStripe file):
public function getCMSFields() {
$fields = parent::getCMSFields();
$gridFieldConfig = GridFieldConfig_RecordEditor::create();
$gridFieldConfig->addComponent(new GridFieldBulkImageUpload());
$gridFieldConfig->addComponent(new GridFieldSortableRows('SortOrder'));
$gridFieldConfig->getComponentByType('GridFieldDataColumns')->setDisplayFields(array(
// field from drawer class => label in UI
'ID' => 'ID',
'Title' => 'Title',
'Thumbnail' => 'Thumbnail',
'InternalURL.Link' => 'Internal URL',
));
$gridfield = new GridField(
"Rotator",
"Rotator",
$this->Rotator()->sort("SortOrder"),
$gridFieldConfig
);
$fields->addFieldToTab('Root.Rotator', $gridfield);
$fields->addFieldToTab("Root.Main", new TextField("H1"), "Content");
$fields->addFieldToTab("Root.Main", new TextField("Subheader"), "Content");
$fields->addFieldToTab('Root.Main', new TextField('PageTitle', 'Page Title'), 'MetaDescription');
$fields->removeFieldFromTab('Root.Rotator', 'Body');
$fields->removeFieldFromTab('Root.Rotator', 'BackgroundImage');
return $fields;
}
Here is the code for the Rotator class:
<?php
class RotatorImage extends DataObject {
public static $db = array(
'SortOrder' => 'Int',
'Header' => 'varchar',
'Body' => 'HTMLText',
);
// One-to-one relationship with gallery page
public static $has_one = array(
'Image' => 'Image',
'BackgroundImage' => 'Image',
'Page' => 'Page',
'InternalURL' => 'SiteTree',
);
// tidy up the CMS by not showing these fields
public function getCMSFields() {
$fields = parent::getCMSFields();
$fields->removeFieldFromTab("Root.Main","PageID");
$fields->removeFieldFromTab("Root.Main","SortOrder");
return $fields;
}
// Tell the datagrid what fields to show in the table
public static $summary_fields = array(
'ID' => 'ID',
'Title' => 'Title',
'Thumbnail' => 'Thumbnail',
'InternalURLID' => 'Internal URL',
);
// this function creates the thumnail for the summary fields to use
public function getThumbnail() {
return $this->Image()->CMSThumbnail();
}
public function canEdit() {
return true;
}
public function canDelete() {
return true;
}
public function canCreate(){
return true;
}
public function canPublish(){
return true;
}
public function canView(){
return true;
}
}
However this does not work, and I am sure that I have the fields names correct. I tried 'Root.Rotator.Main' and 'Root.Rotator.Content' just to see what would happen and those also did not work. What am I missing? Is it possible to hide fields on a custom tab this way, or do I need to try something else?
well, you want to hide the fields in the gridfield detail form? that cannot be done in your pages getCMSFields(), as the grid is responsible for generating the detail form. Two possible solutions:
1) tell the grid to hide that fields with a custom component. I dunno how to do it
2) tell your Rotator class to show the fields ONLY if the related page is a homepage:
public function getCMSFields() {
$fields = parent::getCMSFields();
//...other stuff....
$isOnHomePage = ($this->Page() && $this->Page()->ClassName == 'HomePage'); //put in your own classname or conditions
if(!$isOnHomePage) {
//remove the fields if you're not on the HomePage
$fields->removeByName('Body');
//we need to suffix with "ID" when we have a has_one relation!
$fields->removeByName('BackGroundImageID');
}
return $fields;
}
This will work...
$fields->removeByName('FieldName');

Drupal custom modules and cache issue

We created a few custom custom modules for a Drupal site and we have the following issue : each time we create or update a content (whatever it is), the content generated by the custom modules disappears. We have to clear all caches to get this content to appear again.
As it is our first experience with Drupal, we are certainly missing something but we don't know what.
Any help would be greatly appreciated!
Below is the code of one of these custom modules:
File website_actualites.module
<?php
/**
* Implements hook_block_info().
*/
function website_actualites_block_info() {
$blocks['website_actualites'] = array(
'info' => t('website_actualites'),
'cache' => DRUPAL_CACHE_PER_ROLE,
);
return $blocks;
}
/**
* Implements hook_block_view().
*/
function website_actualites_block_view($delta = '') {
$aDelta = explode('+', $delta);
$nbActualite = 2;
if (!empty($aDelta[1])) {
$nbActualite = $aDelta[1];
}
$block = null;
switch ($aDelta[0]) {
case 'website_actualites':
$block['content'] = _website_actualites_sweet_block_content($nbActualite);
break;
}
return $block;
}
/**
* Callback implemented by hook_block_view().
*/
function _website_actualites_sweet_block_content($nbActualite=2) {
$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
->entityCondition('bundle', 'article')
->propertyCondition('status', 1)
->fieldCondition('field_mise_en_avant', 'value', 1)
->propertyOrderBy('created', 'DESC')
->range(0, $nbActualite)
->addMetaData('account', user_load(1));
$result = $query->execute();
// width col pour nb actu=2 : 4,8
// width col pour nb actu=4: 2,4,2,4
$colWidthEven=4;
$colWidthOdd=8;
if (4 == $nbActualite) {
$colWidthEven=2;
$colWidthOdd=4;
}
$data = array();
if (isset($result['node'])) {
$nids = array_keys($result['node']);
$items = entity_load('node', $nids);
$i=0;
foreach ($items as $item) {
$colWidth=$colWidthOdd;
if (0 == $i%2) {
$colWidth = $colWidthEven;
}
$i++;
$data[$item->nid] = array(
'title' => $item->title,
'tags' => isset($item->fielsTags['und'][0]) ? $item->fielsTags['und'][0] : '',
'body' => isset($item->body['und'][0]['value']) ? $item->body['und'][0]['value'] : '',
'image' => isset($item->field_image['und'][0]) ? $item->field_image['und'][0] : '',
'nid' => $item->nid,
'col-width' => $colWidth,
'alias' => drupal_get_path_alias('node/'.$item->nid)
);
}
}
$static_title = t('Static Title');
$static_content = 'static content';
return theme('website_actualites_output', array(
'title' => $static_title,
'content' => $static_content,
'data' => $data
)
);
}
File website_actualite-sweet--block.tpl.php
<?php
foreach ($data as &$row) {
$url = drupal_get_path_alias('node/' . $row['nid']);
$imageWrapper = file_stream_wrapper_get_instance_by_uri($row['image']['uri']);
if (is_object($imageWrapper) && is_callable(array($imageWrapper, 'getExternalUrl'))) {
$imageUrl = $imageWrapper->getExternalUrl();
print '<div class="col-sm-'.$row['col-width'].'">
<div class="img">
<img src="' . $imageUrl . '" class="img-responsive" alt="image description">
</div>
<p>' . $row['title'] . '</p>
</div>';
}
}
first of all there are several problems with this code. If you're going to use Drupal then you need to stick to Drupal coding standards. Avoid using camel casing for variables, instead you should use underscores. Also you should use 2 spaces for indentation.
In your block info function you define a single block however you assign it to an unassigned variable:
// Define $blocks first.
$blocks = array();
$blocks['website_actualites'] = array(
Next issue is that you call hook_block_view($delta), this call will be fired for every block delta, and regardless of the block delta you are setting it to null (also for future reference should be NULL):
$block = null;
So Drupal is building the render array for each block, and you are wiping all the data. You are doing this because you are trying to use the block delta as a way to pass a parameter into your block with a delta like website_actualites+10. Blocks aren't designed to work this way and delta's are meant to be static so that Drupal can keep track of them in the database and perform the correct caching according to your cache flag. You've defined the delta website_actualites in your hook_block_info() but Drupal has no knowledge or configuration information for any other block delta.
If you have a need for the same block to display varying quantities, then just define several blocks (in your hook_block_info()) and call the same helper function as you are now. If there is a requirement to configure the block then you should use the hook_block_configure() API
Now the data you are passing into your theme function, you are extracting field data from the node object using: $item->field_image['und'][0]. A couple of things here: fields are provided by the field module which has an extensive API to retrieve field data. You should use field_get_items() instead, which will return an array of all items associated with that field for that entity (as fields can be multi-valued) and handles the language for you. The other thing is never use 'und' use the constant LANGUAGE_NONE.
$body = field_get_items('node', $item, 'body');
$field_image = field_get_items('node', $item, 'field_image');
$field_tags = field_get_items('node', $item, 'field_tags');
$data[$item->nid] = array(
'title' => $item->title,
'tags' => $field_tags ? $field_tags : FALSE,
'body' => $body ? $body[0] : FALSE,
'image' => $field_image ? $field_image[0] : FALSE,
'nid' => $item->nid,
'col-width' => $colWidth,
'alias' => drupal_get_path_alias('node/'.$item->nid)
);
Another problem is that you set the $block['content'] to the result of theme('website_actualites_output', ...). Now this function will return markup, Drupal has many more calls in the chain before we need to render any markup, and the problem with calling this now is that you can't mutate your data at any point now in the build process.
In order to call theme('website_actualites_output', ...); You need to have defined this theme function in a hook_theme() call, presumably you have done this in another module, which is perfectly fine but remember to add a dependency on that module in your module.info file. What you really want to be doing is just adding instructions to the Drupal build, not markup:
return array(
'#theme' => 'website_actualites_output',
'#title' => $static_title,
'#content' => $static_content,
'#data' => $data
);
So then we come to your template, you have a lot of logic in your template and they are only intended for displaying content with markup, with ideally no, or minimal computation if any. A theme function has a hook_preprocess() call before hook_process(), and then the variables are passed into the template.
You are using this theme function to loop over the $data variable to display markup - ideally a theme function would be just that markup with the variables already processed and passed into it:
website-actualites-output--child.tpl.php
<div class="col-sm-<?php print $col_width; ?>">
<?php if ($image): ?>
<div class="img">
<?php print render($image); ?>
</div>
<?php endif; ?>
<?php if ($title): ?>
<p><?php print render($title); ?></p>
<?php endif; ?>
</div>
In this example your best bet would be to have a second theme function website_actualites_output__child with the above template.
/**
* Implements hook_theme().
*/
function website_actualites_theme() {
$templates = drupal_get_path('module', 'website_actualites') . '/templates';
return array(
'website_actualites_output__child' => array(
'path' => $templates,
'template' => 'website-actualites-output--child',
'variables' => array(
'col_width' => 4, // Default col width.
'image' => NULL,
'title' => NULL,
),
),
);
}
Then preprocess your current theme function:
/**
* Implements hook_preprocess_HOOK().
*/
function website_actualites_preprocess_website_actualites_output($variables) {
$processed_output = array();
$data = $variables['data'];
foreach ($data as $row) {
$image = array(
'#theme' => 'image',
'#path' => file_create_url($row['image']['uri']),
'#alt' => $image['alt'],
'#attributes' => array('class' => array('img-responsive')),
);
$processed_output[] = array(
'#theme' => 'website_actualites_output__child',
'#col_width' => $row['col-width'],
'#image' => array(
'#theme' => 'link',
'#path' => 'node/' . $row['nid'],
'#text' => $image,
'#options' => array('HTML' => TRUE),
),
'#title' => array(
'#theme' => 'link',
'#path' => 'node/' . $row['nid'],
'#text' => $row['title'],
),
);
}
// Reassign the $data variable so that we can just render() it.
// var_dump($processed_output) to get a better idea what's going on here.
$variables['data'] = $processed_output;
}
Then all you need to do in your current template is to:
<?php if ($data): ?>
<?php print render($data); ?>
<?php endif; ?>
And you can wrap this is whatever markup you like.
The Drupal learning curve is high, but remember that if someone else were to maintain this code after you, they would expect that you adhere to Drupal coding standards and followed the process upon which Drupal is built.
Further reading: Render Arrays in Drupal 7
Hope this information helps and makes it a bit clearer.

Problems with a form in SocialEngine/Zend

I have created a module in SocialEngine(*which is built on Zend framework v1.9) that contains an admin form with a few options.
The problem I have with it is that it seems to no get the values of the fields from database after I refresh the page and it shows me the default values.
It shows the correct values immediately after I save(*but I am not sure if the page is refreshed after saving), but not after I refresh.
controller /application/modules/Mymodule/controllers/AdminSomesettingsController.php :
class Mymodule_AdminSomesettingsController extends Core_Controller_Action_Admin
{
public function indexAction()
{
$this->view->form = $form = new Mymodule_Form_Admin_Someform();
$settings = Engine_Api::_()->getApi('settings', 'core');
if(!$form->isValid($settings->mymodule))
{ return $form->populate($settings->mymodule); }
if( !$this->getRequest()->isPost() ) { return; }
if( !$form->isValid($this->getRequest()->getPost()) ) { return; }
$db = Engine_Api::_()->getDbTable('settings','core')->getAdapter();
$db->beginTransaction();
try {
$values = $form->getValues();
$settings->mymodule = $values;
$db->commit();
} catch( Exception $e ) {
$db->rollback();
throw $e;
}
$form->saveValues();
$form->addNotice('Your changes have been saved.');
}
}
form /application/modules/Mymodule/Form/Admin/Someform.php :
class Mymodule_Form_Admin_Someform extends Engine_Form
{
public function init()
{
$this
->setTitle('My Settings')
->setDescription('Settings');
$this->addElement('Radio', 'some_setting', array(
'label' => 'Some Setting',
'description' => '',
'multiOptions' => array(
0 => 'Option One',
1 => 'Option Two',
2 => 'Option Three',
),
'value' => 1,
'escape' => false,
));
// Add submit button
$this->addElement('Button', 'submit', array(
'label' => 'Save Changes',
'type' => 'submit',
'ignore' => true
));
}
public function saveValues()
{
}
}
I have checked with other plugins and it seems to me that $form->populate($settings->mymodule); repopulates the form after refresh, but it does not work for me.
Any idea how I could make it show the values from the database(*when these values exist) instead of the default values?
I myself am new to socialengine and zend.My understanding of socialengine says, make a function saveValues() inside ur form class, then call it from controller action as $form->saveValues(),passing parameter as needed.This is the convention that socialengine seems to follow, and inside the saveValues() of form class,u can save valus as needed.Ur form shud be populated only if validation fails
(!$form->isValid($formData ))
{ return $form->populate($formData); }
Instead of default adapter,U should try this-
$db =Engine_Api::_()->getDbTable('settings','core')->getAdapter(),
$db->beginTransaction();
If u want to set the value of a particular field try - $form->populate(array('formField'=>'urValue')); in ur case maybe -
$val=$settings->mymodule,
$form->populate('formField'=>$val);
You can add the code in controller $form->some_setting->setValue('1');

Undefined property - Symfony2

I'm using Symfony2. My controller finds some values - like categories, created by the and gives them to the template. The problem is that if the user hasn't any created categories yet, I want to display a massage to invite him to create categories.
Here is the code:
if($number_of_categories == 0){
$newcommer = true;
//Here the template doesn't need any variables, because it only displays
// "Please first add some categories"
} else {
$newcommer = false;
//Here the variables, which I give to the template
//are filled with meaningfull values
}
return $this->render('AcmeBudgetTrackerBundle:Home:index.html.twig', array(
'newcommer' => $newcommer,
'expenses' => $expenses_for_current_month,
'first_category' => $first_category,
'sum_for_current_month' => $sum_for_current_month,
'budget_for_current_month' => $budget_for_current_month
));
The problem is that if the user doesn't have categories I don't have with what to fill the variables, so I have to write something like this:
//What I want to avoid is this:
$expenses_for_current_month = null;
$first_category = null;
$sum_for_current_month = null;
$budget_for_current_month = null;
just to avoid Notice: Undefined variable ...
Is there a cleaner solution to achieve this? There isn't a way to dynamically generate the count of variables, given to the template, is there? Thanks in advance!
Here a simple solution (if I understood your problem) :
$template = 'AcmeBudgetTrackerBundle:Home:index.html.twig';
if ($number_of_categories == 0){
//Here the template doesn't need any variables, because it only displays
// "Please first add some categories"
return $this->render($template, array(
'newcommer' => true,
));
} else {
//Here the variables, which I give to the template
//are filled with meaningfull values
return $this->render($template, array(
'newcommer' => false,
'expenses' => $expenses_for_current_month,
'first_category' => $first_category,
'sum_for_current_month' => $sum_for_current_month,
'budget_for_current_month' => $budget_for_current_month
));
}
And if you want a cleaner solution to manage your Template, you cna use the annotation #Template() (You just have to return an array to pass to the view) :
// ...
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
class MyController extends Controller
{
/**
* #Route("/my_route.html")
* #Template("AcmeBudgetTrackerBundle:Home:index.html.twig")
*/
public function indexAction()
{
// ...
if ($number_of_categories == 0){
return array(
'newcommer' => true,
);
} else {
//Here the variables, which I give to the template
//are filled with meaningfull values
return array(
'newcommer' => false,
'expenses' => $expenses_for_current_month,
'first_category' => $first_category,
'sum_for_current_month' => $sum_for_current_month,
'budget_for_current_month' => $budget_for_current_month
);
}
}
}

Why am I getting a "skipping broken view error"?

This is Drupal 6.x and am having a nightmare of a time to modify a simple drupal form. This is a module file.
function modulename_menu() {
$items = array();
$items['school/registration'] = array(
'title' => 'Registration Form',
'page callback' =>'drupal_get_form',
'type' => MENU_CALLBACK
);
return $items;
}//end of the function
function modulename_school_form_alter(&$form, $form_state, $form_id)
{
// dsm($form_id);
if ($form_id == 'user_registration_form')
{
// modify the "#submit" form property by prepending another submit handler arra
$form['#submit'] = array_merge(
array('_modulename_registration_submit' => array()),
$form['#submit']
);
}
}
For what it's worth a few months afterwards - I just had the same problem. Check out
http://drupal.org/node/626834#comment-2393090
You probably have an install file with your custom module that doesn't contain all the necessary information.

Categories