Exposing a module's data to Views2 using its API - php

I'm forking the filefield_stats module to provide it with the ability of exposing data into the Views module via the API.
The filefield_stats schema is as follow:
function filefield_stats_schema() {
$schema['filefield_stats'] = array(
'fields' => array(
'fid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'description' => 'Primary Key: the {files}.fid'),
'vid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'description' => 'Primary Key: the {node}.vid'),
'uid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'description' => 'The {users}.uid of the downloader'),
'timestamp' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'description' => 'The timestamp of the download'),
'hostname' => array('type' => 'varchar', 'length' => 128, 'not null' => TRUE, 'default' => '', 'description' => 'The hostname downloading the file (usually IP)'),
'referer' => array('type' => 'text', 'not null' => FALSE, 'description' => 'Referer for the download'),
),
'indexes' => array('fid_vid' => array('fid', 'vid')),
);
return $schema;
}
Well, so I implemented the hook_views_api() in filefield_stats.module & added a filefield_stats.views.inc file in the module's root directory, here it is:
// $Id$
/**
* #file
* Provide the ability of exposing data to Views2, for filefield_stats module.
*/
function filefield_stats_views_data() {
$data = array();
$data['filefield_stats']['table']['group'] = t('FilefieldStats');
// Referencing the {node_revisions} table.
$data['filefield_stats']['table']['join'] = array(
'node_revisions' => array(
'left_field' => 'vid',
'field' => 'vid',
),
'files' => array(
'left_field' => 'fid',
'field' => 'fid',
),
'users' => array(
'left_field' => 'uid',
'field' => 'uid',
),
);
// Introducing filefield_stats table fields to Views2.
// vid: The node's revision ID which wrapped the downloaded file
$data['filefield_stats']['vid'] = array(
'title' => t('Node revision ID'),
'help' => t('The node\'s revision ID which wrapped the downloaded file'),
'relationship' => array(
'base' => 'node_revisions',
'field' => 'vid',
'handler' => 'views_handler_relationship',
'label' => t('Node Revision Reference.'),
),
);
// uid: The ID of the user who downloaded the file.
$data['filefield_stats']['uid'] = array(
'title' => t('User ID'),
'help' => t('The ID of the user who downloaded the file.'),
'relationship' => array(
'base' => 'users',
'field' => 'uid',
'handler' => 'views_handler_relationship',
'label' => t('User Reference.'),
),
);
// fid: The ID of the downloaded file.
$data['filefield_stats']['fid'] = array(
'title' => t('File ID'),
'help' => t('The ID of the downloaded file.'),
'relationship' => array(
'base' => 'files',
'field' => 'fid',
'handler' => 'views_handler_relationship',
'label' => t('File Reference.'),
),
);
// hostname: The hostname which the file has been downloaded from.
$data['filefield_stats']['hostname'] = array(
'title' => t('The Hostname'),
'help' => t('The hostname which the file has been downloaded from.'),
'field' => array(
'handler' => 'views_handler_field',
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_string',
),
'argument' => array(
'handler' => 'views_handler_argument_string',
),
);
// referer: The referer address which the file download link has been triggered from.
$data['filefield_stats']['referer'] = array(
'title' => t('The Referer'),
'help' => t('The referer which the file download link has been triggered from.'),
'field' => array(
'handler' => 'views_handler_field',
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_string',
),
'argument' => array(
'handler' => 'views_handler_argument_string',
),
);
// timestamp: The time of the download.
$data['filefield_stats']['timestamp'] = array(
'title' => t('Download Time'),
'help' => t('The time of the download.'),
'field' => array(
'handler' => 'views_handler_field_date',
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort_date',
),
'filter' => array(
'handler' => 'views_handler_filter_date',
),
);
return $data;
} // filefield_stats_views_data()
According to the Views2 documentations this should work as a minimum, I think. But it doesn't! Also there is no error of any kind, when I come through the views UI, there's nothing about filefield_stats data. Any idea?

I think your problem is in the function name: hook_views_data(), it should be filefield_stats_views_data().
hook_views_api() should also be filefield_stats_views_api().
You always replace hook with your module name when implementing them in your own modules.

Missing field definitions in the code above and also wrong hook_views_api() implementation. A working API implementation example can be found here: http://drupalcode.org/sandbox/sepehr/1073868.git/tree/refs/heads/master:/modules/sms_panel_views

Related

ZF2 EmailAddress validator

I am creating ZF2 email address validator via factory that has 2 parts, one checks if emaill is already in DB, two: validate the email.
Prblem is that my NoObjectExists validator works just fine, but the acatual Email address validator does not (validator recognises "dsfsfhsadjkfnaskl" as valid email). Here is my code, maybe you guys can spot what is wrong with it?
$factory = new \Zend\InputFilter\Factory();
$input = $factory->createInput(array(
'name' => 'email',
'required' => false,
'filters' => array(
0 => array(
'name' => 'Zend\Filter\StringTrim',
'options' => array(),
),
),
'validators' => array(
0 => array(
'name' => '\DoctrineModule\Validator\NoObjectExists',
'options' => array(
'object_repository' => $this,
'fields' => array('email'),
),
1 => array(
'name' => '\Zend\Validator\EmailAddress',
'options' => array(
'allow' => \Zend\Validator\Hostname::ALLOW_DNS,
'domain' => true,
),
),
),
),
));
return $input;
You have an error in your array nesting. You aren't closing off the containing the NoObjectExists validator so the Email validator is nested inside.
Try the following:
$factory = new \Zend\InputFilter\Factory();
$input = $factory->createInput(array(
'name' => 'email',
'required' => false,
'filters' => array(
0 => array(
'name' => 'Zend\Filter\StringTrim',
'options' => array(),
),
),
'validators' => array(
0 => array(
'name' => '\DoctrineModule\Validator\NoObjectExists',
'options' => array(
'object_repository' => $this,
'fields' => array('email'),
),
),
1 => array(
'name' => '\Zend\Validator\EmailAddress',
'options' => array(
'allow' => \Zend\Validator\Hostname::ALLOW_DNS,
'domain' => true,
),
),
),
));
return $input;

ZF2's custom validator's $context suddenly gives 'bar'=>array() when posting bar[0][foo]='xyz'

I have a custom validator using $context that has been working for over a year.
The $context contains all posted parameters except for "bar" which is an empty array although it is posted as bar[0][description]. The array used to contain one or more arrays with key-value-pairs.
This seems to be the case since updating from version 2.3.2 to 2.5.1
I can't even check the 2.5 documentation since it's not available, Google didn't turn up anything close to the issue, ... was the behaviour changed or is this a bug?
Edit:
In .../Lorem/Form/FooForm.php I include a fieldset:
public function __construct() {
// ...
$this->add(array(
'type' => 'Collection',
'name' => 'bar',
'options' => array(
'label'=> '',
'count' => 1,
'should_create_template' => TRUE,
'allow_add' => TRUE,
'use_as_base_fieldset' => TRUE,
'target_element' => array(
'type' => 'Lorem\Fieldset\BarFieldset'
)
)
));
}
In .../Lorem/Fieldset/BarFieldset.php I have:
public function __construct() {
parent::__construct('bar');
$this->setHydrator(new ReflectionHydrator())
->setObject(new Bar());
$this->add(array(
'name' => 'description',
'type' => 'Textarea',
'attributes' => array(
'rows' => 3,
'cols' => 40,
),
));
$this->add(array(
'name' => 'amount',
'attributes' => array(
'type' => 'Text',
'class' => 'input-bar-amount',
'maxlength' => 9,
),
));
// ...
}
public function getInputFilterSpecification()
{
return array(
'description' => array(
'required' => TRUE,
'filters' => array(
array('name' => 'StripTags'),
),
'validators' => array(
array(
'name' => 'NotEmpty',
'break_chain_on_failure' => TRUE,
'options' => array(
'messages' => array(
'isEmpty' => 'Please enter a description.',
),
),
),
),
),
'amount' => array(
'required' => TRUE,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'NotEmpty',
'break_chain_on_failure' => TRUE,
'options' => array(
'messages' => array(
'isEmpty' => 'Please enter amount.',
),
),
),
array(
'name' => 'Float',
'break_chain_on_failure' => TRUE,
'options' => array(
'locale' => 'de',
'messages' => array(
'floatInvalid' => 'Invalid input. String, Integer oder Float expected.',
'notFloat' => 'Input ist not a floating point number.',
),
),
),
array(
'name' => 'Between',
'break_chain_on_failure' => TRUE,
'options' => array(
'min' => -1000000,
'max' => 1000000,
'messages' => array(
'notBetween' => "Only values between '%min%' and '%max%' EUR are allowed.",
'notBetweenStrict' => "Only values between '%min%' and '%max%' EUR are allowed.",
),
),
),
),
),
// ...
);
}

How to configure ObjectMultiCheckBox to persist an empty element?

I have the following element in my form, and I tried all possible options found in the web to allow empty value for element:
$this->add(array(
'type' => 'DoctrineModule\Form\Element\ObjectMultiCheckbox',
'name' => 'directPractice',
'options' => array(
'label' => 'A. Check all direct practice field education assignments',
'label_attributes' => array(
'class' => 'label-multicheckbox-group'
),
'required' => false,
'allow_empty' => true,
'continue_if_empty' => false,
'object_manager' => $this->getObjectManager(),
'target_class' => 'OnlineFieldEvaluation\Entity\FieldEducationAssignments', //'YOUR ENTITY NAMESPACE'
'property' => 'directPractice', //'your db collumn name'
'disable_inarray_validator' => true,
'value_options' => array(
'1' => 'Adults',
'2' => 'Individuals',
'3' => 'Information and Referral',
'4' => 'Families',
array(
'value' => 'Other',
'label' => 'Other (specify)',
'label_attributes' => array(
'class' => 'bindto',
'data-bindit_id' => 'otherDirectPracticeTxt_ID'
),
'attributes' => array(
'id' => 'otherDirectPractice_ID',
),
)
),
),
'attributes' => array(
'value' => '1', //set checked to '1'
'multiple' => true,
)
));
And I am always getting the same error message when it is empty:
Validation failure 'directPractice':Array
(
[isEmpty] => Value is required and can't be empty
)
Ok, this is a best what I could come up after researching on it. Solution is inspired by these question.
Form: hidden field and ObjectMultiCheckBox
public function init()
{
$this->setAttribute('method', 'post');
$this->setAttribute('novalidate', 'novalidate');
//hidden field to return empty value. If checkbox selected, checkbox values will be stored with empty value in Json notation
$this->add(array(
'type' => 'Hidden',
'name' => 'otherLearningExperiences[]', // imitates checkbox name
'attributes' => array(
'value' => null
)
));
$this->add(array(
// 'type' => 'Zend\Form\Element\MultiCheckbox',
'type' => 'DoctrineModule\Form\Element\ObjectMultiCheckbox',
'name' => 'otherLearningExperiences',
'options' => array(
'label' => 'C. Check other learning experiences',
'object_manager' => $this->getObjectManager(),
'target_class' => 'OnlineFieldEvaluation\Entity\FieldEducationAssignments',
'property' => 'otherLearningExperiences',
'label_attributes' => array(
'id' => 'macro_practice_label',
'class' => 'control-label label-multicheckbox-group'
),
'value_options' => array(
array(
'value' => 'seminars',
'label' => 'Seminars, In-Service Training/Conferences',
'label_attributes' => array(
'class' => 'bindto',
'data-bindit_id' => 'seminarsTxt_ID'
),
'attributes' => array(
'id' => 'seminars_ID',
),
),
array(
'value' => 'other',
'label' => 'Other (specify)',
'label_attributes' => array(
'class' => 'bindto',
'data-bindit_id' => 'otherLeaningExperiencesTxt_ID'
),
'attributes' => array(
'id' => 'otherLeaningExperiences_ID',
),
)
),
),
'attributes' => array(
//'value' => '1', //set checked to '1'
'multiple' => true,
'empty_option' => '',
'required' =>false,
'allow_empty' => true,
'continue_if_empty' => false,
)
));
Validator
$inputFilter->add($factory->createInput(array(
'name' => 'otherLearningExperiences',
'required' => false,
'allow_empty' => true,
'continue_if_empty' => true,
)));
}
View
//hidden field to be posted for empty value in multicheckbox
echo $this->formHidden($form->get('otherLearningExperiences[]'));
$element = $form->get('otherLearningExperiences');
echo $this->formLabel($element);
echo $this->formMultiCheckbox($element, 'prepend');

"Could not install module" error in PyroCMS

I have been building a module in PyroCMS and have made its structure. I am using Streams API to build forms and perform my actions and also performed a dummy install to check if everything looks ok. Then I went on modifying the contents of the dummy and completing my structure. However, in the details.php file, I made a change where I created a foreign key (relationship type of field, if u know the API jargon) to retrieve a field from another stream(the other stream being defined after my current stream) and now when I install the module, it shows 'Could not install the module' error, but I can see the module has been installed. I have tried to comment out the foreign key reference, but the problem still persists.
Here's my details.php file:
class Module_Employer extends Module
{
public $version = '1.0';
public function info()
{
return array(
'name' => array(
'en' => 'Employer'
),
'description' => array(
'en' => 'Module for Employer'
),
'frontend' => true,
'backend' => true,
'menu' => 'content',
'shortcuts' => array(
'create' => array(
'name' => 'Employer:new',
'uri' => 'admin/employer/create',
'class' => 'add'
)
)
);
}
public function install()
{
// We're using the streams API to
// do data setup.
$this->load->driver('Streams');
$this->load->language('employer/emp');
// Add streams
if ( ! $this->streams->streams->add_stream(lang('Employer:employers'), 'employers', 'employer', null, 'This is the Employer Stream')) return false;
if ( ! $this->streams->streams->add_stream(lang('Employer:company'), 'company', 'company', null, 'This is the Company Stream')) return false;
if ( ! $this->streams->streams->add_stream(lang('Employer:job'), 'jobs', 'job', null, 'This is the Job Stream')) return false;
// Fields for employers table
$employer_fields = array(
array(
'name' => 'Name',
'slug' => 'name',
'namespace' => 'employer',
'type' => 'text',
'extra' => array('max_length' => 100),
'assign' => 'employers',
'title_column' => true,
'required' => true,
'unique' => true
),
array(
'name' => 'Username',
'slug' => 'username',
'namespace' => 'employer',
'type' => 'text',
'extra' => array('max_length' => 100),
'assign' => 'employers',
'title_column' => true,
'required' => true,
'unique' => true
),
array(
'name' => 'Password',
'slug' => 'password',
'namespace' => 'employer',
'type' => 'encrypt',
'extra' => array('hide_typing' => 'yes'),
'assign' => 'employers',
'title_column' => true,
'required' => true,
'unique' => true
),
array(
'name' => 'Credits',
'slug' => 'credits',
'namespace' => 'employer',
'type' => 'integer',
'extra' => array('max_length' => 10),
'assign' => 'employers',
'title_column' => true,
'required' => true,
'unique' => true
),
array(
'name' => 'Company name',
'slug' => 'company_name',
'namespace' => 'employer',
'type' => 'relationship',
'extra' => array('choose_stream' => 'company'),
'assign' => 'employers',
'title_column' => true,
'required' => false,
'unique' => false
)
);
$this->streams->fields->add_fields($employer_fields);
//Fields for company stream
$company_fields = array(
array(
'name' => 'Username',
'slug' => 'username',
'namespace' => 'company',
'type' => 'relationship',
'extra' => array('choose_stream' => 'employers'),
'assign' => 'company',
'title_column' => true,
'required' => false,
'unique' => false
),
array(
'name' => 'E-mail',
'slug' => 'email',
'namespace' => 'company',
'type' => 'email',
'assign' => 'company',
'title_column' => true,
'required' => true,
'unique' => false
),
array(
'name' => 'Company Name',
'slug' => 'company_name',
'namespace' => 'company',
'type' => 'text',
'extra' => array('max_length' => 100),
'assign' => 'company',
'title_column' => true,
'required' => true,
'unique' => true
),
array(
'name' => 'Logo',
'slug' => 'logo',
'namespace' => 'company',
'type' => 'image',
'extra' => array('folder' => 'upload'),
'assign' => 'company',
'title_column' => true,
'required' => false,
'unique' => false
),
array(
'name' => 'Designation',
'slug' => 'designation',
'namespace' => 'company',
'type' => 'text',
'extra' => array('max_length' => 100),
'assign' => 'company',
'title_column' => true,
'required' => false,
'unique' => false
),
array(
'name' => 'Contact No.1',
'slug' => 'contact1',
'namespace' => 'company',
'type' => 'integer',
'extra' => array('max_length' => 10),
'assign' => 'company',
'title_column' => true,
'required' => true,
'unique' => false
),
array(
'name' => 'Contact No.2',
'slug' => 'contact2',
'namespace' => 'company',
'type' => 'integer',
'extra' => array('max_length' => 10),
'assign' => 'company',
'title_column' => true,
'required' => false,
'unique' => false
),
array(
'name' => 'Contact No.3',
'slug' => 'contact3',
'namespace' => 'company',
'type' => 'integer',
'extra' => array('max_length' => 10),
'assign' => 'company',
'title_column' => true,
'required' => false,
'unique' => false
),
array(
'name' => 'Address',
'slug' => 'address',
'namespace' => 'company',
'type' => 'textarea',
'assign' => 'company',
'title_column' => true,
'required' => true,
'unique' => false
),
array(
'name' => 'Billing ddress',
'slug' => 'billing_address',
'namespace' => 'company',
'type' => 'textarea',
'assign' => 'company',
'title_column' => true,
'required' => true,
'unique' => false
),
);
$this->streams->fields->add_fields($company_fields);
//Fields for company stream
$job_desc_fields = array(
array(
'name' => 'Username',
'slug' => 'username',
'namespace' => 'company',
'type' => 'relationship',
'extra' => array('choose_stream' => 'employers'),
'assign' => 'jobs',
'title_column' => true,
'required' => false,
'unique' => false
),
array(
'name' => 'Key Skills',
'slug' => 'keyskills',
'namespace' => 'company',
'type' => 'textarea',
'assign' => 'jobs',
'title_column' => true,
'required' => true,
'unique' => false
),
array(
'name' => 'Position Summary',
'slug' => 'position_summary',
'namespace' => 'company',
'type' => 'textarea',
'assign' => 'jobs',
'title_column' => true,
'required' => false,
'unique' => false
),
array(
'name' => 'Experience',
'slug' => 'experience',
'namespace' => 'company',
'type' => 'text',
'assign' => 'jobs',
'title_column' => true,
'required' => true,
'unique' => false
),
array(
'name' => 'Industry',
'slug' => 'industry',
'namespace' => 'company',
'type' => 'text',
'assign' => 'jobs',
'title_column' => true,
'required' => false,
'unique' => false
),
array(
'name' => 'Functional Area',
'slug' => 'functional_area',
'namespace' => 'company',
'type' => 'text',
'assign' => 'jobs',
'title_column' => true,
'required' => false,
'unique' => false
),
array(
'name' => 'Salary',
'slug' => 'salary',
'namespace' => 'company',
'type' => 'text',
'assign' => 'jobs',
'title_column' => true,
'required' => false,
'unique' => false
),
array(
'name' => 'Start Date',
'slug' => 'start_date',
'namespace' => 'company',
'type' => 'datetime',
'assign' => 'jobs',
'extra' => array('input_type' => 'datepicker'),
'title_column' => true,
'required' => false,
'unique' => false
),
array(
'name' => 'Job Type',
'slug' => 'job_type',
'namespace' => 'company',
'type' => 'choice',
'assign' => 'jobs',
'extra' => array('input_type' => 'datepicker'),
'title_column' => true,
'required' => false,
'unique' => false
),
);
return true;
}
public function uninstall()
{
$this->load->driver('Streams');
$this->streams->utilities->remove_namespace('employer');
return true;
}
public function upgrade($old_version)
{
// Your Upgrade Logic
return true;
}
public function help()
{
// Return a string containing help info
// You could include a file and return it here.
return "No documentation has been added for this module.<br />Contact the module developer for assistance.";
}
}
I had earlier "installed" the module, but under the uninstall() function, I forgot to add the code for removing all the streams(P.S: I had 3 streams with separate namespaces defined in the install() function). I only had the following:
$this->streams->utilities->remove_namespace('employer');
Due to this, the other streams were 'existing' in the system although on the face of it, the module was uninstalled, and whenever I tried to reinstall the module, I got the error Could not install module, since while creating tables/streams in the database, the query returned FALSE as the tables already existed.
However, I then added the code to remove all the other streams, by simply including their namespaces in the call for example:
$this->streams->utilities->remove_namespace('employer');
$this->streams->utilities->remove_namespace('job');
$this->streams->utilities->remove_namespace('company');
..and the problem was fixed!

Convert to an array

I have a variable $code which contains the following data. I want the contents of $feeds_importer to an array. How can I do this?
$feeds_importer = new stdClass;
$feeds_importer->disabled = FALSE;
/* Edit this to true to make a default feeds_importer disabled initially */
$feeds_importer->api_version = 1;
$feeds_importer->id = 'feed';
$feeds_importer->config = array(
'name' => 'Feed',
'description' => 'Import RSS or Atom feeds, create nodes from feed items.',
'fetcher' => array(
'plugin_key' => 'FeedsHTTPFetcher',
'config' => array(
'auto_detect_feeds' => FALSE,
'use_pubsubhubbub' => FALSE,
'designated_hub' => '',
),
),
'parser' => array(
'plugin_key' => 'FeedsSyndicationParser',
'config' => array(),
),
'processor' => array(
'plugin_key' => 'FeedsNodeProcessor',
'config' => array(
'content_type' => 'feed_item',
'update_existing' => 0,
'expire' => '-1',
'mappings' => array(
array(
'source' => 'title',
'target' => 'title',
'unique' => FALSE,
),
array(
'source' => 'description',
'target' => 'body',
'unique' => FALSE,
),
array(
'source' => 'timestamp',
'target' => 'created',
'unique' => FALSE,
),
array(
'source' => 'url',
'target' => 'url',
'unique' => TRUE,
),
array(
'source' => 'guid',
'target' => 'guid',
'unique' => TRUE,
),
),
'input_format' => 0,
'author' => 0,
),
),
'content_type' => 'feed',
'update' => 0,
'import_period' => '1800',
'expire_period' => 3600,
'import_on_create' => 1,
);
i want the contents of feeds_importer to an array how can i do this?
$array = (array) $feeds_importer;

Categories