I want to export the "manage customers" grid, and also want to add the ip addresses of the customers at the end of the grid.
this is the code that is executed when the grid is loaded
protected function _prepareCollection()
{
$collection = Mage::getResourceModel('customer/customer_collection')
->addNameToSelect()
->addAttributeToSelect('email')
->addAttributeToSelect('created_at')
->addAttributeToSelect('group_id')
->joinAttribute('billing_postcode', 'customer_address/postcode', 'default_billing', null, 'left')
->joinAttribute('billing_city', 'customer_address/city', 'default_billing', null, 'left')
->joinAttribute('billing_telephone', 'customer_address/telephone', 'default_billing', null, 'left')
->joinAttribute('billing_region', 'customer_address/region', 'default_billing', null, 'left')
->joinAttribute('billing_country_id', 'customer_address/country_id', 'default_billing', null, 'left');
$this->setCollection($collection);
return parent::_prepareCollection();
}
i have also added a column
$this->addColumn('ip_address', array(
'header' => Mage::helper('customer')->__('IP Address'),
'default' => Mage::helper('customer')->__('n/a'),
'index' => 'remote_addr',
'renderer' => 'adminhtml/customer_online_grid_renderer_ip',
'filter' => false,
'sort' => false
));
but i dont get any data.
How can i get the customers ip address in the added column
To add ip addresses of the customers at the end of the grid :-
We've to create a custom module :-
I'm taking namespace as Wakar & Modulename as Customeripaddress :-
1-
app/etc/modules/Wakar_Customeripaddress.xml
So first of all we've to register this module :-
<?xml version="1.0"?>
<config>
<modules>
<Wakar_Customeripaddress>
<active>true</active>
<codePool>local</codePool>
<version>0.1.0</version>
</Wakar_Customeripaddress>
</modules>
</config>
2- app/code/local/Wakar/Customeripaddress/etc/config.xml :-
In this file we're defining module configuration(Block override,controller override etc).
<?xml version="1.0"?>
<config>
<modules>
<Wakar_Customeripaddress>
<version>0.1.0</version>
</Wakar_Customeripaddress>
</modules>
<frontend>
<routers>
<customeripaddress>
<use>standard</use>
<args>
<module>Wakar_Customeripaddress</module>
<frontName>customeripaddress</frontName>
</args>
</customeripaddress>
</routers>
</frontend>
<global>
<rewrite>
<wakar_customeripaddress_customer_accountcontroller>
<from><![CDATA[#^/customer/account/#]]></from> <!-- Mage_Customer_AccountController -->
<to>/customeripaddress/customer_account/</to> <!-- Wakar_Customeripaddress_Customer_AccountController -->
</wakar_customeripaddress_customer_accountcontroller>
</rewrite>
<helpers>
<customeripaddress>
<class>Wakar_Customeripaddress_Helper</class>
</customeripaddress>
</helpers>
<blocks>
<customeripaddress>
<class>Wakar_Customeripaddress_Block</class>
</customeripaddress>
<adminhtml>
<rewrite>
<customer_grid>Wakar_Customeripaddress_Block_Adminhtml_Customer_Grid</customer_grid>
</rewrite>
</adminhtml>
</blocks>
<models>
<customeripaddress>
<class>Wakar_Customeripaddress_Model</class>
<resourceModel>customeripaddress_mysql4</resourceModel>
</customeripaddress>
</models>
<resources>
<customerattribute1523689716_setup>
<setup>
<module>Wakar_Customeripaddress</module>
<class>Mage_Customer_Model_Entity_Setup</class>
</setup>
<connection>
<use>core_setup</use>
</connection>
</customerattribute1523689716_setup>
<customerattribute1523689716_write>
<connection>
<use>core_write</use>
</connection>
</customerattribute1523689716_write>
<customerattribute1523689716_read>
<connection>
<use>core_read</use>
</connection>
</customerattribute1523689716_read>
</resources>
</global>
<admin>
<routers>
<customeripaddress>
<use>admin</use>
<args>
<module>Wakar_Customeripaddress</module>
<frontName>admin_customeripaddress</frontName>
</args>
</customeripaddress>
</routers>
</admin>
</config>
3-app/code/local/Wakar/Customeripaddress/sql/customerattribute1523689716_setup/mysql4-install-0.1.0.php
Now we're going to create a customer custom column & during customer registration we'll use this column to save visitor ip address & later we'll fetch this ip address to show customer ip address via renderer.
<?php
$installer = $this;
$installer->startSetup();
$installer->addAttribute("customer", "customer_ip_address", array(
"type" => "varchar",
"backend" => "",
"label" => "IP Address",
"input" => "text",
"source" => "",
"visible" => true,
"required" => false,
"default" => "",
"frontend" => "",
"unique" => false,
"note" => "Customer Ip Address"
));
$attribute = Mage::getSingleton("eav/config")->getAttribute("customer", "customer_ip_address");
$used_in_forms=array();
$used_in_forms[]="adminhtml_customer";
$used_in_forms[]="checkout_register";
$used_in_forms[]="customer_account_create";
$used_in_forms[]="customer_account_edit";
$used_in_forms[]="adminhtml_checkout";
$attribute->setData("used_in_forms", $used_in_forms)
->setData("is_used_for_customer_segment", true)
->setData("is_system", 0)
->setData("is_user_defined", 1)
->setData("is_visible", 1)
->setData("sort_order", 100)
;
$attribute->save();
$installer->endSetup();
4-
app/code/local/Wakar/Customeripaddress/controllers/Customer/AccountController.php :-
Save Customer Ip address during registration:-
<?php
require_once "Mage/Customer/controllers/AccountController.php";
class Wakar_Customercontrolleroverride_Customer_AccountController extends Mage_Customer_AccountController{
public function postDispatch()
{
parent::postDispatch();
Mage::dispatchEvent('controller_action_postdispatch_adminhtml', array('controller_action' => $this));
}
public function createPostAction()
{
$errUrl = $this->_getUrl('*/*/create', array('_secure' => true));
if (!$this->_validateFormKey()) {
$this->_redirectError($errUrl);
return;
}
/** #var $session Mage_Customer_Model_Session */
$session = $this->_getSession();
if ($session->isLoggedIn()) {
$this->_redirect('*/*/');
return;
}
if (!$this->getRequest()->isPost()) {
$this->_redirectError($errUrl);
return;
}
$customer = $this->_getCustomer();
try {
$errors = $this->_getCustomerErrors($customer);
// Get Visitor Ip address
if (empty($errors)) {
if (!empty($_SERVER["HTTP_CLIENT_IP"]))
{
//check for ip from share internet
$ip = $_SERVER["HTTP_CLIENT_IP"];
}
elseif (!empty($_SERVER["HTTP_X_FORWARDED_FOR"]))
{
// Check for the Proxy User
$ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
}
else
{
$ip = $_SERVER["REMOTE_ADDR"];
}
$customer['customer_ip_address']=$ip;
$customer->cleanPasswordsValidationData();
$customer->save();
$this->_dispatchRegisterSuccess($customer);
$this->_successProcessRegistration($customer);
return;
} else {
$this->_addSessionError($errors);
}
} catch (Mage_Core_Exception $e) {
$session->setCustomerFormData($this->getRequest()->getPost());
if ($e->getCode() === Mage_Customer_Model_Customer::EXCEPTION_EMAIL_EXISTS) {
$url = $this->_getUrl('customer/account/forgotpassword');
$message = $this->__('There is already an account with this email address. If you are sure that it is your email address, click here to get your password and access your account.', $url);
} else {
$message = $this->_escapeHtml($e->getMessage());
}
$session->addError($message);
} catch (Exception $e) {
$session->setCustomerFormData($this->getRequest()->getPost());
$session->addException($e, $this->__('Cannot save the customer.'));
}
$this->_redirectError($errUrl);
}
}
5-
app/code/local/Wakar/Customeripaddress/Block/Adminhtml/Customer/Grid.php :-
Add Ip address in customer grid:-
<?php
class Wakar_Customeripaddress_Block_Adminhtml_Customer_Grid extends Mage_Adminhtml_Block_Customer_Grid
{
protected function _prepareCollection()
{
$collection = Mage::getResourceModel('customer/customer_collection')
->addNameToSelect()
->addAttributeToSelect('email')
->addAttributeToSelect('created_at')
->addAttributeToSelect('group_id')
->joinAttribute('billing_postcode', 'customer_address/postcode', 'default_billing', null, 'left')
->joinAttribute('billing_city', 'customer_address/city', 'default_billing', null, 'left')
->joinAttribute('billing_telephone', 'customer_address/telephone', 'default_billing', null, 'left')
->joinAttribute('billing_region', 'customer_address/region', 'default_billing', null, 'left')
->joinAttribute('billing_country_id', 'customer_address/country_id', 'default_billing', null, 'left');
$this->setCollection($collection);
return parent::_prepareCollection();
}
protected function _prepareColumns()
{
$this->addColumn('entity_id', array(
'header' => Mage::helper('customer')->__('ID'),
'width' => '50px',
'index' => 'entity_id',
'type' => 'number',
));
/*$this->addColumn('firstname', array(
'header' => Mage::helper('customer')->__('First Name'),
'index' => 'firstname'
));
$this->addColumn('lastname', array(
'header' => Mage::helper('customer')->__('Last Name'),
'index' => 'lastname'
));*/
$this->addColumn('name', array(
'header' => Mage::helper('customer')->__('Name'),
'index' => 'name'
));
$this->addColumn('email', array(
'header' => Mage::helper('customer')->__('Email'),
'width' => '150',
'index' => 'email'
));
$groups = Mage::getResourceModel('customer/group_collection')
->addFieldToFilter('customer_group_id', array('gt'=> 0))
->load()
->toOptionHash();
$this->addColumn('group', array(
'header' => Mage::helper('customer')->__('Group'),
'width' => '100',
'index' => 'group_id',
'type' => 'options',
'options' => $groups,
));
$this->addColumn('Telephone', array(
'header' => Mage::helper('customer')->__('Telephone'),
'width' => '100',
'index' => 'billing_telephone'
));
$this->addColumn('billing_postcode', array(
'header' => Mage::helper('customer')->__('ZIP'),
'width' => '90',
'index' => 'billing_postcode',
));
$this->addColumn('billing_country_id', array(
'header' => Mage::helper('customer')->__('Country'),
'width' => '100',
'type' => 'country',
'index' => 'billing_country_id',
));
$this->addColumn('billing_region', array(
'header' => Mage::helper('customer')->__('State/Province'),
'width' => '100',
'index' => 'billing_region',
));
$this->addColumn('customer_since', array(
'header' => Mage::helper('customer')->__('Customer Since'),
'type' => 'datetime',
'align' => 'center',
'index' => 'created_at',
'gmtoffset' => true
));
if (!Mage::app()->isSingleStoreMode()) {
$this->addColumn('website_id', array(
'header' => Mage::helper('customer')->__('Website'),
'align' => 'center',
'width' => '80px',
'type' => 'options',
'options' => Mage::getSingleton('adminhtml/system_store')->getWebsiteOptionHash(true),
'index' => 'website_id',
));
}
$this->addColumn('ip_address', array(
'header' => Mage::helper('customer')->__('IP Address'),
'default' => Mage::helper('customer')->__('N/A'),
'index' => 'remote_addr',
'renderer' => 'customeripaddress/adminhtml_renderer_location',
'filter' => false,
'sort' => false
));
$this->addColumn('action',
array(
'header' => Mage::helper('customer')->__('Action'),
'width' => '100',
'type' => 'action',
'getter' => 'getId',
'actions' => array(
array(
'caption' => Mage::helper('customer')->__('Edit'),
'url' => array('base'=> '*/*/edit'),
'field' => 'id'
)
),
'filter' => false,
'sortable' => false,
'index' => 'stores',
'is_system' => true,
));
$this->addExportType('*/*/exportCsv', Mage::helper('customer')->__('CSV'));
$this->addExportType('*/*/exportXml', Mage::helper('customer')->__('Excel XML'));
return parent::_prepareColumns();
}
}
6-
app/code/local/Wakar/Customeripaddress/Block/Adminhtml/Renderer/Location.php
Using renderer to show ip address in the customer grid:-
<?php
class Wakar_Customeripaddress_Block_Adminhtml_Renderer_Location extends Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract
{
public function render(Varien_Object $row)
{
// Instance of customer loaded by the given ID
$customer = Mage::getModel('customer/customer')->load($row->getData('entity_id'));
return $customer['customer_ip_address'] ;
}
}
Hope this will resolve your problem...!!!
Related
I am working on a Drupal module that provides a jvectormap node type.
Everything works fine except the drupal .load(). I use
jQuery("#content").load(Drupal.settings.jvectormapnode.url+'/'+ code +'?ajax=1');
The following happens i click a country on the map and this calls /content/institutes/BE
/content/institutes is an views page with a contextual filter witch grabs the last part of the url and displays some data.
The jvectormap node is included on this same page trough a mini-panel and blocks (the view resides in div #content and the jvectormap in a mini-panel block)
Up to this point everything is ok. Now when i click a second region the URL suddenly switches to /content/undefined.
Let me clarify with an example: I click on Belgium the URL changes to /content/institutes/BE and the view picks this up, then I click France and the URL changes to /content/undefined but the view still reacts correctly and shows the France info. Now I hit F5 to refresh the browser and drupal says that /content/undefined does not exist. If I hit F5 after the first click (Belgium) it reloads the page correctly. The problem seems to happen with consecutive ajax requests. I coud fix this with an url alias so this would handle the F5 refresh edge case seeing everything else works correctly, but if some one else needs more than one node they have a (small) problem.
I suspect the .load is the reason why this is happening.
Any help is welcome thanks.
jvectormapnode.js
(function ($)
{
Drupal.behaviors.jvectormapnode =
{
attach: function (context, settings)
{
$('#jvectormapnode').once('jvectormapnode', function() { //fix duplicating behavior when using ajax
highlighted=JSON.parse(Drupal.settings.jvectormapnode.coloredregions);
//console.log(Drupal.settings.jvectormapnode.coloredregions);
//console.log(highlighted);
//change color of clicked region ==> todo
/*
currentSelected = '';
defaultColor = '#00FF00';
selectedColor = '#FF00FF';
maphandle = $('#map-teste');
maphandle.vectorMap({
map: 'br_en',
onRegionClick: function(event, code){
if(currentSelected !== code) {
if(currentSelected !== ''){
// Deselect, then select new choice
maphandle.vectorMap('set', 'colors', currentSelected, defaultColor);
maphandle.vectorMap('set', 'colors', code, selectedColor);
currentSelected = code;
} else {
// Nothing currently selected, go ahead and select
maphandle.vectorMap('set', 'colors', code, selectedColor);
currentSelected = code;
}
} else {
// Deselect
maphandle.vectorMap('set', 'colors', code, defaultColor);
currentSelected = '';
}
alert(code); // return the state
}
});*/
$('#jvectormapnode').vectorMap({
map: 'world_mill_en',
focusOn: {
x: Drupal.settings.jvectormapnode.x,
y: Drupal.settings.jvectormapnode.y,
scale: Drupal.settings.jvectormapnode.scale
},
color: '#aaaaaa',
hoverColor: false,
hoverOpacity: 0.5,
backgroundColor: 'false',
onRegionClick: function (event, code) {
//if(typeof(afunctiontodo!='undefined') afunctiontodo();
//else
//{
//window.location = Drupal.settings.jvectormapnode.url+'/'+ code;
jQuery("#content").load(Drupal.settings.jvectormapnode.url+'/'+ code +'?ajax=1');
//$('#jvectormapnode').vectorMap('set', 'focus', code);
//showSelectedCountry;
//}
},
series: {
regions: [{
values: highlighted ,
attribute: 'fill'
}]
}
});
});
}
};
}(jQuery));
jvectormapnode.module
<?php
/**
* #file
*/
/**
* #defgroup jvectormapnode : Node
* #ingroup jvectormapnode
* #{
* 20130812 pieterm
* Integrates jvectormapnode into Drupal through the node type system
*/
/**
* Implements hook_libraries_info().
*/
function jvectormapnode_libraries_info() {
$libraries['jvectormap'] = array(
'name' => 'jVectorMap',
'vendor url' => 'http://jvectormap.com/',
'download url' => 'http://jvectormap.com/download/',
'version arguments' => array(
'file' => 'jquery.jvectormap.min.js',
'pattern' => '#jVectorMap version ([0-9\.]+)#',
'lines' => 2,
'cols' => 30,
),
'versions' => array(
'1.2.2' => array(
'files' => array(
'js' => array('jquery.jvectormap.min.js'),
'css' => array('jquery.jvectormap.css'),
),
),
),
);
return $libraries;
}
/**
* Implements hook_view().
*/
function jvectormapnode_view($node, $view_mode) {
$node->content['jvectormapnodebody'] = array(
'#markup' => _jvectormapnode_page($node),
'#weight' => 1,
);
return $node;
}
/**
* Implements hook_theme().
* Overriding the default node template for jvectormapnode pages
*/
function jvectormapnode_theme($existing, $type, $theme, $path) {
$items = array(
'node__jvectormapnode' => array(
// Don't specify the path in the template name.
// Unless you have your template inside a directory within this module.
'template' => 'templates/node--jvectormapnode',
'variables' => array('node' => (object)array()),
// If you want to put the tpl in another location, you can use this key.
//'theme path' => drupal_get_path('module', 'another_module'),
),
);
return $items;
}
/**
* Implements hook_node_info().
*
* We use hook_node_info() to define our node content type.
*/
function jvectormapnode_node_info() {
// We define the node type as an associative array.
return array(
'jvectormapnode' => array(
'name' => t('jvectormapnode'),
'base' => 'jvectormapnode', //function prefix hooks
'description' => t('This is the jvectormapnode node type. It can display interactive maps.'),
'title_label' => t('jvectormapnode page title'),
'locked' => FALSE, //TODO SET TRUE
),
);
}
/**
* Implements hook_node_type_insert().
* lets us know that a new content type has been inserted.
* this gives us a chance to add the fields we want. (called for all node isnert!==>check type)
*/
function jvectormapnode_node_type_insert($content_type) {
if ($content_type->type == 'jvectormapnode') {
// Add default body field
$body_instance = node_add_body_field($content_type, t('Information you want to show on each page before the content of the jvectormapnode module'));
$body_instance['display']['example_node_list'] = array(
'label' => 'hidden',
'type' => 'text_summary_or_trimmed',
);
// Save our changes to the body field instance.
field_update_instance($body_instance);
// Create all the fields we are adding to our content type.
foreach (_jvectormapnode_installed_fields() as $field) {
field_create_field($field);
}
// Create all the instances for our fields.
foreach (_jvectormapnode_installed_instances() as $instance) {
$instance['entity_type'] = 'node';
$instance['bundle'] = 'jvectormapnode';
field_create_instance($instance);
}
}
}
/**
* Define the fields for our content type.
*
* This big array is factored into this function for readability.
*
* #return
* An associative array specifying the fields we wish to add to our
* new node type.
*/
function _jvectormapnode_installed_fields() {
return array(
'jvectormapnode_field_color' => array(
'field_name' => 'jvectormapnode_field_color',
'cardinality' => 1,
'type' => 'text',
),
'jvectormapnode_field_url' => array(
'field_name' => 'jvectormapnode_field_url',
'cardinality' => 1,
'type' => 'text',
),
'jvectormapnode_field_width' => array(
'field_name' => 'jvectormapnode_field_width',
'cardinality' => 1,
'type' => 'text',
),
'jvectormapnode_field_height' => array(
'field_name' => 'jvectormapnode_field_height',
'cardinality' => 1,
'type' => 'text',
),
'jvectormapnode_field_regions' => array(
'field_name' => 'jvectormapnode_field_regions',
'cardinality' => 1,
'type' => 'text',
),
'jvectormapnode_field_scale' => array(
'field_name' => 'jvectormapnode_field_scale',
'cardinality' => 1,
'type' => 'text',
),
'jvectormapnode_field_x' => array(
'field_name' => 'jvectormapnode_field_x',
'cardinality' => 1,
'type' => 'text',
),
'jvectormapnode_field_y' => array(
'field_name' => 'jvectormapnode_field_y',
'cardinality' => 1,
'type' => 'text',
),
);
}
/**
* Define the field instances for our content type.
*
* The instance lets Drupal know which widget to use to allow the user to enter
* data and how to react in different view modes.
*
* This big array is factored into this function for readability.
*
* #return
* An associative array specifying the instances we wish to add to our new
* node type.
*/
function _jvectormapnode_installed_instances() {
return array(
'jvectormapnode_field_url' => array(
'field_name' => 'jvectormapnode_field_url',
'label' => t('URL, format http://www.vliz.be/en/...'),
'widget' => array(
'type' => 'text_textfield',
),
),
'jvectormapnode_field_width' => array(
'field_name' => 'jvectormapnode_field_width',
'label' => t('Map width, format px or %'),
'widget' => array(
'type' => 'text_textfield',
),
),
'jvectormapnode_field_height' => array(
'field_name' => 'jvectormapnode_field_height',
'label' => t('Map height, format px or %'),
'widget' => array(
'type' => 'text_textfield',
),
),
'jvectormapnode_field_regions' => array(
'field_name' => 'jvectormapnode_field_regions',
'label' => t('Regions to be highlighted'),
'widget' => array(
'type' => 'text_textfield',
),
),
'jvectormapnode_field_color' => array(
'field_name' => 'jvectormapnode_field_color',
'label' => t('Highlight color, HEX format #ffffff.'),
'widget' => array(
'type' => 'text_textfield',
),
),
'jvectormapnode_field_scale' => array(
'field_name' => 'jvectormapnode_field_scale',
'label' => t('Initial zoom, nummeric format.'),
'widget' => array(
'type' => 'text_textfield',
),
),
'jvectormapnode_field_x' => array(
'field_name' => 'jvectormapnode_field_x',
'label' => t('Initial x-axis focus, nummeric format.'),
'widget' => array(
'type' => 'text_textfield',
),
),
'jvectormapnode_field_y' => array(
'field_name' => 'jvectormapnode_field_y',
'label' => t('Initial y-axis focus, nummeric format.'),
'widget' => array(
'type' => 'text_textfield',
),
),
);
}
/**
* Implements hook_entity_info_alter().
*
* We need to modify the default node entity info by adding a new view mode to
* be used in functions like node_view() or node_build_content().
*/
function jvectormapnode_entity_info_alter(&$entity_info) {
// Add our new view mode to the list of view modes...
$entity_info['node']['view modes']['example_node_list'] = array(
'label' => t('Example Node List'),
'custom settings' => TRUE,
);
}
/**
* Implement hook_form().
*
* Drupal needs for us to provide a form that lets the user
* add content. This is the form that the user will see if
* they go to node/add/node-example.
*/
function jvectormapnode_form($node, $form_state) {
return node_content_form($node, $form_state);
}
/**
* Implements hook_field_formatter_info().
*/
function jvectormapnode_field_formatter_info() {
return array(
'jvectormapnode_field_color' => array(
'label' => t('jvectormapnode color Handle'),
'field types' => array('text'),
),
'jvectormapnode_field_url' => array(
'label' => t('jvectormapnode url Handle'),
'field types' => array('text'),
),
'jvectormapnode_field_width' => array(
'label' => t('jvectormapnode width Handle'),
'field types' => array('text'),
),
'jvectormapnode_field_height' => array(
'label' => t('jvectormapnode height Handle'),
'field types' => array('text'),
),
'jvectormapnode_field_regions' => array(
'label' => t('jvectormapnode regions Handle'),
'field types' => array('text'),
),
'jvectormapnode_field_scale' => array(
'label' => t('jvectormapnode scale Handle'),
'field types' => array('text'),
),
'jvectormapnode_field_x' => array(
'label' => t('jvectormapnode x Handle'),
'field types' => array('text'),
),
'jvectormapnode_field_y' => array(
'label' => t('jvectormapnode y Handle'),
'field types' => array('text'),
),
);
}
/**
* Implements hook_help().
*/
function jvectormapnode_help($path, $arg) {
switch ($path) {
case 'examples/jvectormapnode':
return "<p>" . t("The Node Example module provides a custom node type.
You can create new Example Node nodes using the <a href='!nodeadd'>node add form</a>.",
array('!nodeadd' => url('node/add/node-example'))) . "</p>";
}
}
/**
* Page callback to show jvectormapnode
*/
function _jvectormapnode_page($n) {
//get params from drupal entity created by user in add content
$dcolor= field_get_items('node', $n, 'jvectormapnode_field_color');
$dcolor=render(field_view_value('node', $n, 'jvectormapnode_field_color',$dcolor[0]));
$durl= field_get_items('node', $n, 'jvectormapnode_field_url');
$durl=render(field_view_value('node', $n, 'jvectormapnode_field_url',$durl[0]));
$dwidth= field_get_items('node', $n, 'jvectormapnode_field_width');
$dwidth=render(field_view_value('node', $n, 'jvectormapnode_field_width',$dwidth[0]));
$dheight= field_get_items('node', $n, 'jvectormapnode_field_height');
$dheight=render(field_view_value('node', $n, 'jvectormapnode_field_height',$dheight[0]));
$dregions= field_get_items('node', $n, 'jvectormapnode_field_regions');
$dregions=render(field_view_value('node', $n, 'jvectormapnode_field_regions',$dregions[0]));
$dscale= field_get_items('node', $n, 'jvectormapnode_field_scale');
$dscale=render(field_view_value('node', $n, 'jvectormapnode_field_scale',$dscale[0]));
$dx= field_get_items('node', $n, 'jvectormapnode_field_x');
$dx=render(field_view_value('node', $n, 'jvectormapnode_field_x',$dx[0]));
$dy= field_get_items('node', $n, 'jvectormapnode_field_y');
$dy=render(field_view_value('node', $n, 'jvectormapnode_field_y',$dy[0]));
//$coloredregions=array();
$exploderegions = explode(",", $dregions);
$coloredregions=array();
foreach ($exploderegions as $region)
{
$coloredregions[$region] = $dcolor ;
}
$coloredregions_object = json_encode($coloredregions);
$jvectormapnodebody.= '<div style="width: '.$dwidth.'; height: '.$dheight.'" id="jvectormapnode"></div>';
libraries_load('jvectormap');
drupal_add_js('/sites/all/modules/vliz/jvectormapnode/js/maps/jquery-jvectormap-world-mill-en.js');
drupal_add_js(array('jvectormapnode' => array('url' => $durl,'coloredregions'=> $coloredregions_object,'scale' => $dscale,'x' => $dx,'y' => $dy)), 'setting');
drupal_add_js('/sites/all/modules/vliz/jvectormapnode/js/jvectormapnode.js');
return $jvectormapnodebody;
}
/**
* #} End of "defgroup jvectormapnode".
*/
It seems that the code argument passed within the onRegionClick callback is undefined.
Can you do a console.log() of that argument to know the exact value? Normally this should be the region code as a string. (i.e.: 'BE', 'NL', ...)
onRegionClick: function (event, code) {
console.log(code);
}
I found out what was causing the undefined, here's the code that works
jQuery("#content").load(Drupal.settings.jvectormapnode.url+'/'+ code ,'ajax=1' ,
function() {Drupal.attachBehaviors('#content');});
hope this helps someone else
I am trying to create my first drupal module that creates a simple node type wcNames. This node type has two fields, firstname & lastname.
I could get my module create the DB table for node type and add it in node_type table, but when I open node/add/wc-name fields firstname and lastname don't appear.
Below is my code. Please suggest.
<?php
// wc_name.install file
/*
* hook_schema Implementation: Creates the DB and it's fields
*/
function wc_name_schema(){
$schema['wc_name_names'] = array(
'fields' => array(
'nmid' => array('type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE),
'firstname' => array('type' => 'varchar', 'length' => 50, 'not null' => FALSE),
'lastname' => array('type' => 'varchar', 'length' => 50, 'not null' => FALSE),
),
'primary key' => array('nmid'),
'unique keys' => array(),
'indexes' => array(
'nmid' => array('nmid'),
),
);
return $schema;
}
//function wc_name_install(){ } // Use this function to set variables for the module.
function wc_name_uninstall(){
//unset variables if any set
// Delete all wc_name nodes
db_delete('node')->condition('type', 'wc_name')->execute();
// Delete all wc_name tables
db_drop_table('wc_name_names');
}
?>
<?php
// wc_name.module
/*
* Implementation of _node_info(): define node
*/
function wc_name_node_info(){
return array(
'wc_name' => array(
'name' => t('wcName'),
'base' => 'wc_name',
'base' => 'page',
'description' => t("A smaple module to save names."),
'has_title' => TRUE,
'title_label' => t('Title'),
'has_body' => FALSE,
)
);
}
function wc_name_menu() {
$items = array();
$items['wc_name'] = array(
'title' => 'wcNames',
'page callback' => 'wc_name',
// 'access arguments' => array('access wcNames'),
);
}
?>
<?php
// wc_name_form.inc
function wc_name_form($node, &$form_state){
// Add fields
$form['first_name'] = array(
'#type' => 'textfield',
'#title' => t('First name'),
'#required' => FALSE,
'#default_value' => $node->wc_name['firstname'],
);
$form['last_name'] = array(
'#type' => 'textfield',
'#title' => t('Last name'),
'#required' => FALSE,
'#default_value' => $node->wc_name['lastname'],
);
return $form;
}
?>
What am I missing?
Try this:
function createTextFieldByName($type, $fieldname, $fieldlabel)
{
$field = field_info_field($fieldname);
if (empty($field)) {
$field = array(
'field_name' => $fieldname,
'type' => 'text',
'entity_types' => array('node'),
'translatable' => TRUE,
);
$field = field_create_field($field);
}
$instance = field_info_instance('node', $fieldname, $type);
if (empty($instance)) {
$instance = array(
'field_name' => $fieldname,
'entity_type' => 'node',
'bundle' => $type,
'label' => $fieldlabel,
);
$instance = field_create_instance($instance);
return $instance;
}
return null;
}
$type =
array(
'type' => 'MY_TYPE',
'name' => t('NAME'),
'base' => 'node_content',
'description' => t("DESCRIPTION"),
'custom' => 1,
'modified' => 1,
'locked' => 0,
);
$type = node_type_set_defaults($type);
node_type_save($type);
createTextFieldByName($type,'firstname','First name');
createTextFieldByName($type,'lastname','Last name');
This is my first module. I have been trying to successfully install my module since a week now.
I have gone through every line. Even the schema is being installed and entry is made at system table. But still after enabling the module It shows 500 Internal Server Error until I delete the entry from system table.
Please guide me what I am doing wrong.
Note: sisattribute table is already created in drupal database
My .install file
<?php
/**
* #file
*/
function sisinstitute_install() {
drupal_install_schema('sisinstitute');
variable_set('node_options_sisinstitute', array('status'));
$attributes = array();
$attributes['Country'] = array(
'US' => 'United States of America',
'AD' => 'Andorra',
'AE' => 'United Arab Emirates',
'AF' => 'Afghanistan',
);
$s = "INSERT INTO {sisattribute} (domain, akey, avalue, weight) VALUES ('%s', '%s', '%s', %d)";
$prevdomain = '';
$weight = 0;
foreach ($attributes as $domain => $attribute) {
if ($domain != $prevdomain) $weight=0;
foreach ($attribute as $key => $value) {
db_query($s, $domain, $key, $value, $weight);
$weight++;
}
$prevdomain = $domain;
}
}
function sisinstitute_disable() {
drupal_set_message(t('Please note that they will now have reduced functionality, and will not be protected by previous access controls.'), 'warning');
}
function sisinstitute_uninstall() {
drupal_uninstall_schema('sisinstitute');
db_query($s = "DELETE FROM {sisattribute} WHERE domain IN ('Country')");
}
function sisinstitute_schema() {
$schema['sisinstitute'] = array(
'fields' => array(
'vid' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
'nid' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
'country' => array('type' => 'varchar', 'length' => 100),
'www' => array('type' => 'varchar', 'length' => 100),
'phone' => array('type' => 'varchar', 'length' => 100),
'email' => array('type' => 'varchar', 'length' => 50),
'provstate' => array('type' => 'varchar', 'length' => 50),
'zip' => array('type' => 'varchar', 'length' => 10),
'city' => array('type' => 'varchar', 'length' => 100),
'address' => array('type' => 'varchar', 'length' => 100),
'orglanguage' => array('type' => 'varchar', 'length' => 100),
'isactive' => array('type' => 'int', 'default' => 1),
),
'primary key' => array('vid'),
'indexes' => array(
'nid' => array('nid')
),
);
return $schema;
}
And my .module file:
<?php
// $Id$
/**
*#File
*Module for Institution support in SIS package
*/
/**
*hook_help()
*/
/**
*hook_menu()
*/
/**
*hook_perm()
*/
function sisinstitute_perm() {
return array('access institute', 'create institute', 'edit institute', 'delete institute', 'view belonged institute', 'view all institutes');
}
/**
*hook_access()
*/
function sisinstitute_access($op, $node. $account=NULL) {
if (empty($account)) {
global $user;
$account = $user;
}
if (is_numeric($node)) $node = node_load($node);
if (!isset($account->sisinstitute_nid) && module_exists('sisstudent')) {
_sisstudent_load($account);
}
if (!isset($account->sisinstitute_nid) && module_exists('sisstaff')) {
_sisstaff_load($account);
}
switch($op) {
case 'create': return user_access('create institute', $account);
case 'update': return user_access('edit institute', $account);
case 'delete': return user_access('delete institute', $account);
case 'view' : {
if (user_access('view all institutes', $account))
return TRUE;
elseif (user_access('view belonged institute', $account) && $account->sisinstitute_nid == $node->nid)
return TRUE;
else return FALSE;
}
}
}
/**
*hook_node_info()
*/
function sisinstitute_node_info() {
return array(
'sisinstitute' => array(
'name' => t('Institute'),
'module' => 'sisinstitute',
'description' => t("Institute for SIS"),
'title_label' => t("Name"),
'body_label' => t("Note"),
)
);
}
/**
*hook_form()
*/
function sisinstitute_form(&$node) {
$type = node_get_types('type', $node);
//$form['#attributes']['class'] = 'sismcomponent_node_form';
$form['title'] = array(
'#type' => 'textfield',
'#title' => check_plain($type->title_label),
'#required' => TRUE,
'#default_value' => $node->title,
// '#weight' => module_exists('content') ? content_extra_field_weight($node->type, 'title') : -18,
);
$form['isactive'] = array(
'#type' => 'checkbox',
'#title' => t('Active'),
'#default_value' => $node->isactive,
);
return $form;
}
Hmm Got it:-)(after 8 hours)
function sisinstitute_access($op, $node. $account=NULL) {
has a period instead of a comma after $node
I'm building a module (my_module) in Drupal 7.
It has some functionality and also will create new content type.
In my_module.install I implemented the hook_install (my_module_install).
Can I use more one implementation of hook_install to create new content type (my_cck_install) in this module?
If (yes), how should I do this?
Else: have I do this in another module? :-)
You can't use more than one implementation of hook_install in the same module; in PHP you can't have 2 function with the same name which rules this out.
You would just need to add your new content type in the same hook_install anyway (have a look at how the standard installation profile does it at /profiles/standard/standard.install). This is how I always add new content types from the install file (using the example of a testimonials module):
function testimonial_install() {
// Make sure a testimonial content type doesn't already exist
if (!in_array('testimonial', node_type_get_names())) {
$type = array(
'type' => 'testimonial',
'name' => st('Testimonial'),
'base' => 'node_content',
'custom' => 1,
'modified' => 1,
'locked' => 0,
'title_label' => 'Customer / Client Name'
);
$type = node_type_set_defaults($type);
node_type_save($type);
node_add_body_field($type);
}
}
The following code will create a content type called "Event" with a machine name of 'event' and a title field -
//CREATE NEW CONTENT TYPE
function orderform_node_info() {
return array(
'event' => array(
'name' => t('Event'),
'base' => 'event',
'description' => t('A event content type'),
'has_title' => TRUE
),
);
}
function event_form($node,$form_state) {
$form['title'] = array(
'#type' => 'textfield',
'#title' => t('event Title'),
'#default_value' => !empty($node->title) ? $node->title : '',
'#required' => TRUE,
'#weight' => -5
);
return $form;
}
//END CONTENT TYPE
you should place it in your .module file... if you want do add additional fields to it, let me know and I'll patch you up with the code... good luck!
/**
* Implements hook_node_info()
*/
function mymodule_node_info() {
return array(
'news' => array(
'name' => t('News'),
'base' => 'news',
'description' => t('You can add News here'),
'has_title' => TRUE,
'title_label' => t('News title')
)
);
}
/**
* Implement hook_form()
*/
function mymodule_form($node, $form_state) {
return node_content_form($node, $form_state);
}
Add the implementation to mymodule.install is as follows:
/**
* Implements hook_install().
*/
function mymodule_install() {
node_types_rebuild();
$types = node_type_get_types();|
node_add_body_field($types['news']);
}
You can get a detailed description with code from here
/*
* Implementation in hook node info in .Module file
*/
function test_node_info() {
return array(
'product' => array(
'name' => t('Product'),
'base' => 'product',
'description' => t('Product Title'),
)
);
}
/**
* Implement hook_form()
*/
function product_form($node, $form_state) {
return node_content_form($node, $form_state);
}
/**
* Implements hook_install() in .install file.
*/
function test_install() {
node_types_rebuild();
$types = node_type_get_types();
node_add_body_field($types['product']);
//New way to implement to add fields in your content type
foreach (_test_installed_fields() as $field) {
field_create_field($field);
}
foreach (_test_installed_instances() as $fieldinstance) {
$fieldinstance['entity_type'] = 'node';
$fieldinstance['bundle'] = 'product';
field_create_instance($fieldinstance);
}
}
/*
* Define your fields
*/
function _test_installed_fields() {
$t = get_t();
return array(
'product_title123' => array(
'field_name' => 'product_title123',
'label' => $t('Product Title'),
'type' => 'text'
),
'description123' => array(
'field_name' => 'description123',
'label' => $t('Description'),
'type' => 'text'
),
);
}
/*
* Define your instance of fields
*/
function _test_installed_instances() {
$t = get_t();
return array(
'product_title123' => array(
'field_name' => 'product_title123',
'type' => 'text',
'label' => $t('Product Title'),
'widget' => array(
'type' => 'text_textfield'
),
'display' => array(
'example_node_list' => array(
'label' => $t('Product Title'),
'type' => 'text'
)
)
),
'description123' => array(
'field_name' => 'description123',
'type' => 'text',
'label' => $t('Description'),
'widget' => array(
'type' => 'text_textarea_with_summary'
),
'display' => array(
'example_node_list' => array(
'label' => $t('Description'),
'type' => 'text'
)
)
),
);
}
/**
* Implements hook_uninstall().
*/
function test_uninstall() {
$ournewtype = 'product';
$sql = 'SELECT nid FROM {node} n WHERE n.type = :type';
$result = db_query($sql, array(':type' => $ournewtype));
$nodeids = array();
foreach ($result as $row) {
$nodeids[] = $row->nid;
}
node_delete_multiple($nodeids);
node_type_delete($ournewtype);
}
That's it.
I created a custom module that has a Ctools multi step form. It's basically a copy of http://www.nicklewis.org/using-chaos-tools-form-wizard-build-multistep-forms-drupal-6.
The form works. I can see it if I got to the url i made for it.
For the life of me I can't get the multistep form to show up in a block.
Any clues?
/**
* Implementation of hook_block()
* */
function mycrazymodule_block($op='list', $delta=0, $edit=array()) {
switch ($op) {
case 'list':
$blocks[0]['info'] = t('SFT Getting Started');
$blocks[1]['info'] = t('SFT Contact US');
$blocks[2]['info'] = t('SFT News Letter');
return $blocks;
case 'view':
switch ($delta){
case '0':
$block['subject'] = t('SFT Getting Started Subject');
$block['content'] = mycrazymodule_wizard();
break;
case '1':
$block['subject'] = t('SFT Contact US Subject');
$block['content'] = t('SFT Contact US content');
break;
case '2':
$block['subject'] = t('SFT News Letter Subject');
$block['content'] = t('SFT News Letter cONTENT');
break;
}
return $block;
}
}
/**
* Implementation of hook_menu().
*/
function mycrazymodule_menu() {
$items['hellocowboy'] = array(
'title' => 'Two Step Form',
'page callback' => 'mycrazymodule_wizard',
'access arguments' => array('access content')
);
return $items;
}
/**
* menu callback for the multistep form
* step is whatever arg one is -- and will refer to the keys listed in
* $form_info['order'], and $form_info['forms'] arrays
*/
function mycrazymodule_wizard() {
$step = arg(1);
// required includes for wizard
$form_state = array();
ctools_include('wizard');
ctools_include('object-cache');
// The array that will hold the two forms and their options
$form_info = array(
'id' => 'getting_started',
'path' => "hellocowboy/%step",
'show trail' => FALSE,
'show back' => FALSE,
'show cancel' => false,
'show return' =>false,
'next text' => 'Submit',
'next callback' => 'getting_started_add_subtask_next',
'finish callback' => 'getting_started_add_subtask_finish',
'return callback' => 'getting_started_add_subtask_finish',
'order' => array(
'basic' => t('Step 1: Basic Info'),
'lecture' => t('Step 2: Choose Lecture'),
),
'forms' => array(
'basic' => array(
'form id' => 'basic_info_form'
),
'lecture' => array(
'form id' => 'choose_lecture_form'
),
),
);
$form_state = array(
'cache name' => NULL,
);
// no matter the step, you will load your values from the callback page
$getstart = getting_started_get_page_cache(NULL);
if (!$getstart) {
// set form to first step -- we have no data
$step = current(array_keys($form_info['order']));
$getstart = new stdClass();
//create cache
ctools_object_cache_set('getting_started', $form_state['cache name'], $getstart);
//print_r($getstart);
}
//THIS IS WHERE WILL STORE ALL FORM DATA
$form_state['getting_started_obj'] = $getstart;
// and this is the witchcraft that makes it work
$output = ctools_wizard_multistep_form($form_info, $step, $form_state);
return $output;
}
function basic_info_form(&$form, &$form_state){
$getstart = &$form_state['getting_started_obj'];
$form['firstname'] = array(
'#weight' => '0',
'#type' => 'textfield',
'#title' => t('firstname'),
'#size' => 60,
'#maxlength' => 255,
'#required' => TRUE,
);
$form['lastname'] = array(
'#weight' => '1',
'#type' => 'textfield',
'#title' => t('lastname'),
'#required' => TRUE,
'#size' => 60,
'#maxlength' => 255,
);
$form['phone'] = array(
'#weight' => '2',
'#type' => 'textfield',
'#title' => t('phone'),
'#required' => TRUE,
'#size' => 60,
'#maxlength' => 255,
);
$form['email'] = array(
'#weight' => '3',
'#type' => 'textfield',
'#title' => t('email'),
'#required' => TRUE,
'#size' => 60,
'#maxlength' => 255,
);
$form['newsletter'] = array(
'#weight' => '4',
'#type' => 'checkbox',
'#title' => t('I would like to receive the newsletter'),
'#required' => TRUE,
'#return_value' => 1,
'#default_value' => 1,
);
$form_state['no buttons'] = TRUE;
}
function basic_info_form_validate(&$form, &$form_state){
$email = $form_state['values']['email'];
$phone = $form_state['values']['phone'];
if(valid_email_address($email) != TRUE){
form_set_error('Dude you have an error', t('Where is your email?'));
}
//if (strlen($phone) > 0 && !ereg('^[0-9]{1,3}-[0-9]{3}-[0-9]{3,4}-[0-9]{3,4}$',
$phone)) {
//form_set_error('Dude the phone', t('Phone number must be in format xxx-xxx-
nnnn-nnnn.'));
//}
}
function basic_info_form_submit(&$form, &$form_state){
//Grab the variables
$firstname =check_plain ($form_state['values']['firstname']);
$lastname = check_plain ($form_state['values']['lastname']);
$email = check_plain ($form_state['values']['email']);
$phone = check_plain ($form_state['values']['phone']);
$newsletter = $form_state['values']['newsletter'];
//Send the form and Grab the lead id
$leadid = send_first_form($lastname, $firstname, $email,$phone, $newsletter);
//Put into form
$form_state['getting_started_obj']->firstname = $firstname;
$form_state['getting_started_obj']->lastname = $lastname;
$form_state['getting_started_obj']->email = $email;
$form_state['getting_started_obj']->phone = $phone;
$form_state['getting_started_obj']->newsletter = $newsletter;
$form_state['getting_started_obj']->leadid = $leadid;
}
function choose_lecture_form(&$form, &$form_state){
$one = 'event 1'
$two = 'event 2'
$three = 'event 3'
$getstart = &$form_state['getting_started_obj'];
$form['lecture'] = array(
'#weight' => '5',
'#default_value' => 'two',
'#options' => array(
'one' => $one,
'two' => $two,
'three' => $three,
),
'#type' => 'radios',
'#title' => t('Select Workshop'),
'#required' => TRUE,
);
$form['attendees'] = array(
'#weight' => '6',
'#default_value' => 'one',
'#options' => array(
'one' => t('I will be arriving alone'),
'two' =>t('I will be arriving with a guest'),
),
'#type' => 'radios',
'#title' => t('Attendees'),
'#required' => TRUE,
);
$form_state['no buttons'] = TRUE;
}
/**
* Same idea as previous steps submit
*
*/
function choose_lecture_form_submit(&$form, &$form_state) {
$workshop = $form_state['values']['lecture'];
$leadid = $form_state['getting_started_obj']->leadid;
$attendees = $form_state['values']['attendees'];
$form_state['getting_started_obj']->lecture = $workshop;
$form_state['getting_started_obj']->attendees = $attendees;
send_second_form($workshop, $attendees, $leadid);
}
//----PART 3 CTOOLS CALLBACKS -- these usually don't have to be very unique
/**
* Callback generated when the add page process is finished.
* this is where you'd normally save.
*/
function getting_started_add_subtask_finish(&$form_state) {
dpm($form_state);
$getstart = &$form_state['getting_started_obj'];
drupal_set_message('mycrazymodule '.$getstart->name.' successfully deployed' );
//Get id
// Clear the cache
ctools_object_cache_clear('getting_started', $form_state['cache name']);
$form_state['redirect'] = 'hellocowboy';
}
/**
* Callback for the proceed step
*
*/
function getting_started_add_subtask_next(&$form_state) {
dpm($form_state);
$getstart = &$form_state['getting_started_obj'];
$cache = ctools_object_cache_set('getting_started', $form_state['cache name'],
$getstart);
}
//PART 4 CTOOLS FORM STORAGE HANDLERS -- these usually don't have to be very unique
/**
* Remove an item from the object cache.
*/
function getting_started_clear_page_cache($name) {
ctools_object_cache_clear('getting_started', $name);
}
/**
* Get the cached changes to a given task handler.
*/
function getting_started_get_page_cache($name) {
$cache = ctools_object_cache_get('getting_started', $name);
return $cache;
}
//Salesforce Functions
function send_first_form($lastname, $firstname,$email,$phone, $newsletter){
$send = array("LastName" => $lastname , "FirstName" => $firstname, "Email" => $email
,"Phone" => $phone , "Newsletter__c" =>$newsletter );
$sf = salesforce_api_connect();
$response = $sf->client->create(array($send), 'Lead');
dpm($response);
return $response->id;
}
function send_second_form($workshop, $attendees, $leadid){
$send = array("Id" => $leadid , "Number_Of_Pepole__c" => "2" );
$sf = salesforce_api_connect();
$response = $sf->client->update(array($send), 'Lead');
dpm($response, 'the final response');
return $response->id;
}
Am assuming you have enabled the block from admin. To do a quick check that the block is indeed getting rendered on the page you are looking at, try returning a test string along with your rendered form, from your block callback.
If that doesn't work, try clearing your cache from admin/settings/performance and try again. If I am not wrong, blocks are cached by default. Let us see if it shows up then.