hi every on
I have created paypal integration while registering i.e. paid registration.
my code is following in module
function paidregistration_user($op, &$edit, &$account, $category = NULL){
switch ($op) {
case 'validate': {
$paypal = array();
$paypal['cmd'] = '_xclick';
$paypal['business'] = 'sachin.acetechpvtltd#gmail.com'; // doing this here prevents email harvesting
$paypal['page_style'] = 'Primary';
$paypal['bn'] = 'PP-DonationsBF';
$paypal['item_name'] = 'Donation';
$paypal['amount'] = '200';
$paypal['currency_code'] = 'USD';
$paypal['no_shipping'] = '1';
$paypal['tax'] = '0';
$paypal['lc'] = 'US';
$paypal['rm'] = '1';
$paypal['return'] = 'http://localhost/drupaldemo/pay';
$paypal['cancel_return'] = 'http://localhost/drupaldemo/user/register';
// Append the Paypal data to the $form_values['submitted_tree']
$data = array_merge($edit, $paypal);
// Put the data in a query string
$query = http_build_query($data, '', '&');
// Set the URL to Paypal's processing site and append the query string
$url = 'https://www.sandbox.paypal.com/cgi-bin/webscr?' .$query;
drupal_goto($url);
print_r($_REQUEST);
// Set the webform's confirmation page to Paypal
//$node->webform['confirmation'] = $url;
//drupal_goto();exit;
}
case 'insert' :{
print_r($_REQUEST);
}
}
}
and for success return page
function imagemenu_menu()
{
$items['imagemenu'] = array(
'title' => 'Add Image',
'type' => MENU_NORMAL_ITEM,
);
$items['pay'] = array(
'title' => 'Add Image',
'access arguments' => array('all'),
'page callback' => 'pay',
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
function imagemenu_perm()
{
return array('all');
}
function pay()
{
print_r($_REQUEST);
}
here every thing is working fine but does not display data returned from paypal.
any help will be appriciated
Thanks
Why not just use the existing PayPal module for Drupal? You're re-inventing the wheel here.
Related
I have created a Wordpress plugin with an admin part displaying a table.
To accomplish this, I have created a class extending WP_List_Table all works perfectly but sorting.
When I see the header link, this is displayed:
https://example.com/wp-admin/admin.php?page=myplugin&order=asc
Notice that the orderby parameter is not present. Only the order parameter.
This the implementation of get_columns and get_sortable_columns method:
function get_columns() {
return $columns = array(
'col_alumno_id' => __('ID'),
'col_alumno_nombres' => __('Nombres'),
'col_alumno_apellidos' => __('Apellidos'),
'col_alumno_rut' => __('RUT'),
'col_alumno_curso' => __('Curso'),
'col_alumno_apoderados' => __('Apoderados')
);
}
public function get_sortable_columns() {
return $sortable = array(
'col_alumno_id' => 'ID',
'col_alumno_nombres' => 'alumno_nombres',
'col_alumno_apellidos' => 'alumno_apellidos',
'col_alumno_rut' => 'alumno_rut',
'col_alumno_curso' => 'curso_nombre'
);
}
Also, I have this at the end of prepare_items method:
$columns = $this->get_columns();
$hidden = array();
$sortable = $this->get_sortable_columns();
$_wp_column_headers[$screen->id] = $columns;
$this->_column_headers = array($columns, $hidden, $sortable);
/* -- Fetch the items -- */
$this->items = $wpdb->get_results($wpdb->prepare($query, $this->colegio));
What is missing here?
Assuming I have a CSV like this:
value1,value2
value1,value2
and a table with two columns
column1|column2
how can I programatically import the CSV into the table?
#erier's answer is really good and will get the job done.
As the question is tagged with Drupal 7 I thought I would submit a Drupal custom module method, adapting #erier's answer and prettifying it.
For the basics of a custom module, you can see this simple example.
function custom_module_form($form, &$form_state) {
$form['csv_upload'] = array(
'#type' => 'file',
'#title' => t('Choose a file'),
'#title_display' => 'invisible',
'#size' => 22,
'#upload_validators' => array('file_clean_name' => array()),
);
$form['upload'] = array(
'#type' => 'submit',
'#value' => 'Upload',
);
}
function custom_module_form_validate($form, &$form_state) {
$validators = array('file_validate_extensions' => array('csv'));
// Check for a new uploaded file.
$file = file_save_upload('csv_upload', $validators);
//$file = $form_state['values']['csv_upload'];
if (isset($file)) {
// File upload was attempted.
if ($file) {
// Put the temporary file in form_values so we can save it on submit.
$form_state['values']['csv_upload_file'] = $file;
}
else {
// File upload failed.
form_set_error('csv_upload', t('The file could not be uploaded.'));
}
}
}
function custom_module_submit($form, &$form_state) {
$file = $form_state['values']['csv_upload_file'];
$file->status = FILE_STATUS_PERMANENT;
$file->filename = str_replace(' ', '_', $file->filename);
file_save($file);
$csv_file = file_load($file->fid);
$file = fopen($csv_file->uri, "r");
while(! feof($file))
{
$customer = fgetcsv($file));
db_insert('your_db_table')
->fields(array(
'column1' => $customer[0],
'column2' => $customer[1]
))
->execute();
}
fclose($file);
drupal_set_message('CSV data added to the database');
}
function file_clean_name($file) {
$file->filename = str_replace(' ', '_', $file->filename);
}
That is assuming your question was about a database table.
If you meant into an html table, you can adapt the submit function after $csv_file = file_load($file->fid); like this:
$headers = array('column 1', 'column 2');
$rows = array();
$file = fopen("contacts.csv","r");
while(! feof($file))
{
$customer = fgetcsv($file));
$rows[] = array($customer[0], $customer[1]);
}
fclose($file);
return theme('table', array('header' => $headers, 'rows' => $rows);
Or adapt the two by adding the data to the database and displaying to the screen without a second database hit.
This is what I've come up with - I'm no PHP expert - and it doesn't seem pretty - but it works!
$handle = fopen('/path/to/file/filename.csv', 'r');
$row = fgetcsv($handle);
for ($e = 0; $row = fgetcsv($handle); $e++) {
$record = array();
foreach ($row as $field) {
$record[] = $field;
}
db_insert('your_db_table')
->fields(array(
'column1' => $record[0],
'column2' => $record[1]
))
->execute();
}
fclose($handle);
The table will then look like this:
column1|column2
---------------
value1|value2
value1|value2
This module may help you
https://www.drupal.org/sandbox/draenen/2442165
It requires Feeds but it extends it to work with custom tables (non drupal entities)
I am building a custom module which should display a calendar created by a third-part library. So far, so good. The only problem is, the calendar appears on top of page, even above header. It does not seems to be css-related.
This is the way it looks:
This is my module file:
require_once 'includes/apphp-calendar/calendar.class.php';
function calendario_menu(){
$items = array();
$items['eventos/calendario'] = array(
'title' => 'Calendario',
'description' => 'Calendario de Eventos.',
'page callback' => '_page_calendario',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
return $items;
}
function _page_calendario() {
$objCalendar = new Calendar();
$calendar = $objCalendar->Show();
return array(
'#markup' => $calendar
);
}
Seems to me like the Show function of the calendar class outputs rather than returning a string.
try this:
function _page_calendario() {
$objCalendar = new Calendar();
ob_start();
$objCalendar->Show();
$calendar = ob_get_contents();
ob_end_clean();
return array(
'#markup' => $calendar
);
}
I'm trying to setup a batch page for processing and I need an example. The example that's given in the Example module is within a form and I need a page that I can run independently of a form that will process batch requests.
For instance:
function mymodule_batch_2() {
$operations[] = array('mymodule_onefunction','mymodule_anotherfunction')
$batch = array(
'operations' => $operations,
'finished' => 'mymodule_finished',
// We can define custom messages instead of the default ones.
'title' => t('Processing batch 2'),
'init_message' => t('Batch 2 is starting.'),
'progress_message' => t('Processed #current out of #total.'),
'error_message' => t('Batch 2 has encountered an error.'),
);
batch_set($batch);
batch_process('');
}
Where the batch function would call other functions in the form of $operations.
You need to give batch process an id to work from. batch_process('mybatch')otherwise yourmexample is correct. are you having a particular problem with this strategy?
Here you can see my sample of batch relization with form that calls batch:
function my_module_menu() {
$items['admin/commerce/import'] = array(
'title' => t('Import'),
'page callback' => 'drupal_get_form',
'page arguments' => array('my_module_settings_form'),
'access arguments' => array('administer site settings'),
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
/**
* Import form
*/
function my_module_settings_form() {
$form = array();
$form['import'] = array(
'#type' => 'fieldset',
'#title' => t('Import'),
'#collapsible' => TRUE,
'#collapsed' => FALSE,
);
$form['import']['submit'] = array(
'#type' => 'submit',
'#value' => t('Import'),
);
return $form;
}
function my_module_settings_form_submit($form, &$form_state) {
batch_my_module_import_start();
}
/**
* Batch start function
*/
function batch_my_module_import_start() {
$batch = array(
'title' => t('Import products'),
'operations' => array(
array('_batch_my_module_import', array()),
),
'progress_message' => t('Import. Operation #current out of #total.'),
'error_message' => t('Error!'),
'finished' => 'my_module_batch_finished',
);
batch_set($batch);
}
/**
* Import from 1C operation. Deletes Products
*/
function _batch_my_module_import(&$context) {
// Your iterms. In my case select all products
$pids = db_select('commerce_product', 'p')
->fields('p', array('sku', 'product_id', 'title'))
->condition('p.type', 'product')
->execute()
->fetchAll();
// Get Count of products
if (empty($context['sandbox']['progress'])) {
$context['sandbox']['progress'] = 0;
$context['sandbox']['max'] = count($pids);
watchdog('import', 'import products');
}
// Create Iteration variable
if (empty($context['sandbox']['iteration'])) {
$context['sandbox']['iteration'] = 0;
}
// Check for the end of cycle
if ($context['sandbox']['iteration'] < $context['sandbox']['max']) {
// Count of operation in one batch step
$limit = 10;
// Counts completed operations in one batch step
$counter = 0;
if ($context['sandbox']['progress'] != 0) {
$context['sandbox']['iteration'] = $context['sandbox']['iteration'] + $limit;
}
// Loop all Product items in xml
for ($i = $context['sandbox']['iteration']; $i < $context['sandbox']['max'] && $counter < $limit; $i++) {
/* Loop items here */
/* ... */
/* ... */
$context['results']['added']['products'][] = $product_item->title;
// Update Progress
$context['sandbox']['progress']++;
$counter++;
// Messages
$context['message'] = t('Now processing product %name. Product %progress of %count', array('%name' => $product_item->title, '%progress' => $context['sandbox']['progress'], '%count' => $context['sandbox']['max']));
$context['results']['processed'] = $context['sandbox']['progress'];
}
}
if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
}
}
/**
* Finish of batch. Messagess
*/
function my_module_batch_finished($success, $results, $operations) {
if ($success) {
drupal_set_message(t('#count products added.', array('#count' => isset($results['added']) ? count($results['added']) : 0)));
}
else {
$error_operation = reset($operations);
drupal_set_message(t('An error occurred while processing #operation with arguments : #args', array('#operation' => $error_operation[0], '#args' => print_r($error_operation[0], TRUE))));
}
watchdog('import', 'import finished');
}
function module_name_import_form_submit($form, $form_state) {
// Check to make sure that the file was uploaded to the server properly
$uri = db_query("SELECT uri FROM {file_managed} WHERE fid = :fid", array(
':fid' => $form_state['input']['import']['fid'],
))->fetchField();
if(!empty($uri)) {
if(file_exists(drupal_realpath($uri))) {
// Open the csv
$handle = fopen(drupal_realpath($uri), "r");
// Go through each row in the csv and run a function on it. In this case we are parsing by '|' (pipe) characters.
// If you want commas are any other character, replace the pipe with it.
while (($data = fgetcsv($handle, 0, '|', '"')) !== FALSE) {
$operations[] = array(
'module_name_import_batch_processing', // The function to run on each row
array($data), // The row in the csv
);
}
// Once everything is gathered and ready to be processed... well... process it!
$batch = array(
'title' => t('Importing CSV...'),
'operations' => $operations, // Runs all of the queued processes from the while loop above.
'finished' => 'module_name_import_finished', // Function to run when the import is successful
'error_message' => t('The installation has encountered an error.'),
'progress_message' => t('Imported #current of #total products.'),
);
batch_set($batch);
fclose($handle);
}
}
else {
drupal_set_message(t('There was an error uploading your file. Please contact a System administator.'), 'error');
}
}
/**
* This function runs the batch processing and creates nodes with then given information
* #see
* module_name_import_form_submit()
*/
function module_name_import_batch_processing($data) {
// Lets make the variables more readable.
$title = $data[0];
$body = $data[1];
$serial_num = $data[2];
// Find out if the node already exists by looking up its serial number. Each serial number should be unique. You can use whatever you want.
$nid = db_query("SELECT DISTINCT n.nid FROM {node} n " .
"INNER JOIN {field_data_field_serial_number} s ON s.revision_id = n.vid AND s.entity_id = n.nid " .
"WHERE field_serial_number_value = :serial", array(
':serial' => $serial_num,
))->fetchField();
if(!empty($nid)) {
// The node exists! Load it.
$node = node_load($nid);
// Change the values. No need to update the serial number though.
$node->title = $title;
$node->body['und'][0]['value'] = $body;
$node->body['und'][0]['safe_value'] = check_plain($body);
node_save($node);
}
else {
// The node does not exist! Create it.
global $user;
$node = new StdClass();
$node->type = 'page'; // Choose your type
$node->status = 1; // Sets to published automatically, 0 will be unpublished
$node->title = $title;
$node->uid = $user->uid;
$node->body['und'][0]['value'] = $body;
$node->body['und'][0]['safe_value'] = check_plain($body);
$node->language = 'und';
$node->field_serial_number['und'][0]['value'] = $serial_num;
$node->field_serial_number['und'][0]['safe_value'] = check_plain($serial_num);
node_save($node);
}
}
/**
* This function runs when the batch processing is complete
*
* #see
* module_name_import_form_submit()
*/
function module_name_import_finished() {
drupal_set_message(t('Import Completed Successfully'));
}
I am adding some autocomplete on a form alter. The problem is that in the callback, only the string in the textfield The autocomplete is on, is available. I also want to access a value from another textfield in the callback. How is this possible ?
/**
* Implements hook_form_alter().
*/
function webform_conversion_jquery_form_webform_client_form_1_alter(&$form, &$form_state, $form_id) {
//Load some extra function to process data
module_load_include('inc', 'webform_conversion_jquery', '/includes/dataqueries');
//Add extra js files
drupal_add_js(drupal_get_path('module', 'webform_conversion_jquery') . '/js/conversionform.js');
$form['submitted']['correspondentadress']['cor_street']['#autocomplete_path'] = 'conversionform/conversion_street';
}
}
/**
* Implements hook_menu().
*/
function webform_conversion_jquery_menu() {
$items = array();
$items['conversionform/conversion_street'] = array(
'title' => 'Conversion street autocomplete',
'page callback' => 'conversion_street_autocomplete',
'access callback' => 'user_access',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
return $items;
}
/**
* Retrieve a JSON object containing autocomplete suggestions for streets depending on the zipcode.
*/
function conversion_street_autocomplete($street = '') {
$street = "%" . $street . "%";
$matches = array();
$result = db_select('conversion_adresslist')
->fields('conversion_adresslist', array('street'))
->condition('street', $street, 'like')
->execute();
foreach ($result as $street) {
$matches[$street->street] = $street->street;
}
drupal_json_output($matches);
}
I just want to be able to post extra information in the function:
conversion_street_autocomplete($street = '', $extraparameter)
I had the same problem and have figured out a way, which is not too strenuous. It involves overriding the textfield theme and then passing your parameter to the theme function.
First create declare your theme function:
function mymodule_theme() {
$theme_hooks = array(
'my_module_autocomplete' => array(
'render element' => 'element',
),
);
return $theme_hooks;
}
Next we need to add the theme and the variable to our form element. In my case, the form element is part of a field widget:
function my_module_field_widget_form($form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
if($instance['widget']['type'] == 'my_module_field_type') {
$element['my_module_field'] = array(
'#type' => 'textfield',
'#autocomplete_path' => 'my-module/autocomplete',
// THIS IS THE IMPORTANT PART - ADD THE THEME AND THE VARIABLE.
'#theme' => 'my_module_autocomplete',
'#my_module_variable' => $field['field_name'],
);
}
return $element;
}
Then implement the theme function. This is a copy of theme_textfield from includes/form.inc with one important difference - we append the variable to the autocomplete path:
function theme_my_module_autocomplet($variables) {
$element = $variables['element'];
$element['#attributes']['type'] = 'text';
element_set_attributes($element, array('id', 'name', 'value', 'size', 'maxlength'));
_form_set_class($element, array('form-text'));
$extra = '';
if ($element['#autocomplete_path'] && drupal_valid_path($element['#autocomplete_path'])) {
drupal_add_library('system', 'drupal.autocomplete');
$element['#attributes']['class'][] = 'form-autocomplete';
$attributes = array();
$attributes['type'] = 'hidden';
$attributes['id'] = $element['#attributes']['id'] . '-autocomplete';
// THIS IS THE IMPORTANT PART. APPEND YOUR VARIABLE TO THE AUTOCOMPLETE PATH.
$attributes['value'] = url($element['#autocomplete_path'] . '/' . $element['#my_module_variable'], array('absolute' => TRUE));
$attributes['disabled'] = 'disabled';
$attributes['class'][] = 'autocomplete';
$extra = '<input' . drupal_attributes($attributes) . ' />';
}
$output = '<input' . drupal_attributes($element['#attributes']) . ' />';
return $output . $extra;
}
Now the variable will be available as the first parameter on the autocomplete callback function:
function _my_module_autocomplete($my_module_variable, $search_string) {
// Happy days, we now have access to our parameter.
}
Just in case anyone is still having trouble with this I found a great solution while trying to figure out how to do this. I had a year select list and that dictated what data was displayed in the autocomplete field. The solution basically has an ajax callback function for the select list that can then update the autocomplete field with an extra parameter in the url. Anyways, it is really well explained in the following article.
http://complexdan.com/passing-custom-arguments-drupal-7-autocomplete/
*A note of caution, I was going crazy trying to figure out why it did not work and it turns out you can't have the same form on the page twice (I needed to because I was displaying it differently for mobile devices) because you are using an id for the ajax callback. I added an extra argument to accomplish that. It is called uniqueid in the below example.
function report_cards_comparison_form($form, &$form_state, $uniqueid) {
$curryear = t('2012');
$form['year_select'] = array(
'#title' => t('School Year'),
'#type' => 'select',
'#options' => array(
'2012' => t('2012'),
'2013' => t('2013'),
'2014' => t('2014'),
'2015' => t('2015'),
),
'#default_value' => $curryear,
'#ajax' => array(
'callback' => 'report_cards_comparison_form_callback',
'wrapper' => $uniqueid,
'progress' => array(
'message' => 'Updating Schools...',
'type' => 'throbber'
),
),
);
$form['choice'] = array(
//'#title' => t('Search By: School Name'),
'#type' => 'textfield',
'#attributes' => array(
'class' => array('school-choice'),
'placeholder' => t('Start Typing School Name...'),
),
'#required' => TRUE,
'#autocomplete_path' => 'reportcards/autocomplete/' . $curryear,
'#prefix' => '<div id="' . $uniqueid . '">',
'#suffix' => '</div>',
);
$form['submit'] = array(
'#type' => 'submit',
'#prefix' => '<div class="submit-btn-wrap">',
'#suffix' => '</div>',
'#value' => t('Search'),
'#attributes' => array('id' => 'add-school-submit'),
);
return $form;
}
/**
* Ajax Callback that updates the autocomplete ajax when there is a change in the Year Select List
*/
function report_cards_comparison_form_callback($form, &$form_state) {
unset($form_state['input']['choice'], $form_state['values']['choice']);
$curryear = $form_state['values']['year_select'];
$form_state['input']['choice'] = '';
$form['choice']['#value'] = '';
$form['choice']['#autocomplete_path'] = 'reportcards/autocomplete/' . $curryear;
return form_builder($form['#id'], $form['choice'], $form_state);
}
and I can call the form by doing this...
print render(drupal_get_form('report_cards_comparison_form', 'desktop-schoolmatches'));
You can do it by overriding methods from autocomplete.js in your own js. Here is example:
(function($) {
Drupal.behaviors.someModuleOverrideAC = {
attach: function(context, settings) {
// Next is copied and adjusted method from autocomplete.js
Drupal.jsAC.prototype.populatePopup = function() {
var $input = $(this.input);
var position = $input.position();
// Show popup.
if (this.popup) {
$(this.popup).remove();
}
this.selected = false;
this.popup = $('<div id="autocomplete"></div>')[0];
this.popup.owner = this;
$(this.popup).css({
top: parseInt(position.top + this.input.offsetHeight, 10) + 'px',
left: parseInt(position.left, 10) + 'px',
width: $input.innerWidth() + 'px',
display: 'none'
});
$input.before(this.popup);
// Do search.
this.db.owner = this;
if ($input.attr('name') === 'field_appartment_complex') {
// Overriden search
// Build custom search string for apartments autocomplete
var $wrapper = $('div.apartments-autocomplete');
var $elements = $('input, select', $wrapper);
var searchElements = {string: this.input.value};
$elements.each(function() {
searchElements[$(this).data('address-part')] = $(this).val();
});
var string = encodeURIComponent(JSON.stringify(searchElements));
this.db.search(string);
}
else {
// Default search
this.db.search(this.input.value);
}
};
}
};
}(jQuery));
In your server callback:
function some_module_autocomplete_ajax($string) {
// Decode custom string obtained using overriden autocomplete js.
$components = drupal_json_decode(rawurldecode($string));
// Do you search here using multiple params from $components
}
Ok, for as far as I can see it is not possible. maybe you can roll your own with the ajax functionality in fapi http://api.drupal.org/api/drupal/developer--topics--forms_api_reference.html/7#ajax
For now I solved it by implementing jquery.ui.autocomplete which is included in drupal 7