| 1 |
<?php
|
| 2 |
|
| 3 |
/**
|
| 4 |
* @file
|
| 5 |
* Provides all needed forms' alterations.
|
| 6 |
*/
|
| 7 |
|
| 8 |
define('QUOTA_EXCEED_USED_DATES', 1);
|
| 9 |
define('QUOTA_EXCEED_MAX_SELECTED', 2);
|
| 10 |
|
| 11 |
/**
|
| 12 |
* Implementation of hook_form_alter().
|
| 13 |
*/
|
| 14 |
function ad_ubercart_form_alter(&$form, &$form_state, $form_id) {
|
| 15 |
// Adding ad plans and date pickers to "Add to cart" form
|
| 16 |
if (strpos($form_id, 'add_to_cart_form') || strpos($form_id, 'add_product_form')) {
|
| 17 |
ad_ubercart_add_to_cart_form_alter($form, $form_state);
|
| 18 |
}
|
| 19 |
if (strpos($form_id, 'ad_product') === 0) {
|
| 20 |
ad_ubercart_form_ad_product_node_form_alter($form, $form_state);
|
| 21 |
}
|
| 22 |
if ($form_id === AD_CONTENT_TYPE .'_node_form') {
|
| 23 |
if (!user_access('administer advertisements')) {
|
| 24 |
unset($form['schedule']);
|
| 25 |
unset($form['adstatus']);
|
| 26 |
}
|
| 27 |
}
|
| 28 |
}
|
| 29 |
|
| 30 |
/**
|
| 31 |
* Implementation of hook_form_$form_id_alter().
|
| 32 |
*
|
| 33 |
* Removing useless things from product form.
|
| 34 |
*/
|
| 35 |
function ad_ubercart_form_ad_product_node_form_alter(&$form, &$form_state) {
|
| 36 |
$node = $form['#node'];
|
| 37 |
$form['base']['shippable']['#default_value'] = FALSE;
|
| 38 |
$form['base']['shippable']['#type'] = 'hidden';
|
| 39 |
unset($form['base']['weight']);
|
| 40 |
unset($form['base']['dimensions']);
|
| 41 |
unset($form['base']['pkg_qty']);
|
| 42 |
unset($form['base']['default_qty']);
|
| 43 |
unset($form['base']['ordering']);
|
| 44 |
|
| 45 |
$form['base']['prices']['cost']['#title'] = t('Cost per day');
|
| 46 |
$form['base']['prices']['cost']['#description'] = t('This will be used to calculate a refund amount.');
|
| 47 |
}
|
| 48 |
|
| 49 |
/**
|
| 50 |
* Adding Ad plans and calendar to cart adding form.
|
| 51 |
*/
|
| 52 |
function ad_ubercart_add_to_cart_form_alter(&$form, &$form_state) {
|
| 53 |
$product = node_load($form['nid']['#value']);
|
| 54 |
if (strpos($product->type, 'ad_product') === 0) {
|
| 55 |
if (empty($form_state['storage'])) {
|
| 56 |
add_to_cart_first_step_form($form, $form_state, $product);
|
| 57 |
}
|
| 58 |
else {
|
| 59 |
add_to_cart_second_step_form($form, $form_state, $product);
|
| 60 |
}
|
| 61 |
}
|
| 62 |
}
|
| 63 |
|
| 64 |
/**
|
| 65 |
* Add to cart: first step
|
| 66 |
*/
|
| 67 |
function add_to_cart_first_step_form(&$form, &$form_state, $product) {
|
| 68 |
$form['ad_plan'] = array(
|
| 69 |
'#type' => 'value',
|
| 70 |
'#value' => $product->type,
|
| 71 |
);
|
| 72 |
|
| 73 |
if ($product->type == 'ad_product_daily') {
|
| 74 |
// Qty should not be editable manually
|
| 75 |
$form['qty']['#type'] = 'hidden';
|
| 76 |
|
| 77 |
// Get all daily quota
|
| 78 |
$daily_quota = get_quota('daily');
|
| 79 |
|
| 80 |
// this will produce date in format YYYY-MM-DD from first array item
|
| 81 |
reset($daily_quota);
|
| 82 |
$startDate = key($daily_quota) .'-01';
|
| 83 |
|
| 84 |
// this will produce date in format YYYY-MM-DD from last array item
|
| 85 |
end($daily_quota);
|
| 86 |
list($y, $m) = explode('-', key($daily_quota));
|
| 87 |
$endDate = date('Y-m-d', mktime(0, 0, 0, $m + 1, 0, $y));
|
| 88 |
|
| 89 |
// Remove used quota from calendar
|
| 90 |
$used_quota = get_used_quota('daily');
|
| 91 |
foreach ($used_quota as $date) {
|
| 92 |
// this will produce YYYY-MM from date
|
| 93 |
$month = substr($date, 0, 7);
|
| 94 |
if (isset($daily_quota[$month])) {
|
| 95 |
$daily_quota[$month]--;
|
| 96 |
}
|
| 97 |
}
|
| 98 |
|
| 99 |
// Hatch already added dates
|
| 100 |
$in_cart = array();
|
| 101 |
if (isset($form['#order_id'])) {
|
| 102 |
// Look into opened order products
|
| 103 |
$order = uc_order_load($form['#order_id']);
|
| 104 |
$items = $order->products;
|
| 105 |
}
|
| 106 |
else {
|
| 107 |
// Look into user's cart and mark down items which are already selected
|
| 108 |
$items = uc_cart_get_contents();
|
| 109 |
}
|
| 110 |
foreach ($items as $item) {
|
| 111 |
if ($item->data['ad_plan'] == $product->type) {
|
| 112 |
foreach ($item->data['period'] as $key => $period) {
|
| 113 |
$in_cart[$key] = $period;
|
| 114 |
// we may only add description if something is really present in a cart
|
| 115 |
$description = t('<b>Note:</b> Hatched dates is already in your cart. If you select them, they will be removed from your old selections.');
|
| 116 |
}
|
| 117 |
}
|
| 118 |
}
|
| 119 |
|
| 120 |
$available = FALSE;
|
| 121 |
foreach ($daily_quota as $quota) {
|
| 122 |
if ($quota) {
|
| 123 |
$available = TRUE;
|
| 124 |
break;
|
| 125 |
}
|
| 126 |
}
|
| 127 |
|
| 128 |
if ($available) {
|
| 129 |
$form['period'] = array(
|
| 130 |
'#type' => 'date_picker',
|
| 131 |
'#title' => t('Period'),
|
| 132 |
'#description' => isset($description) ? $description : '',
|
| 133 |
'#multiple' => TRUE,
|
| 134 |
'#calendar_attributes' => array(
|
| 135 |
'inline' => TRUE,
|
| 136 |
'selectMultiple' => TRUE,
|
| 137 |
'endDate' => $endDate,
|
| 138 |
'sartDate' => $startDate,
|
| 139 |
'monthsToDisplay' => min(count($daily_quota), 3),
|
| 140 |
'maxSelected' => array('by_month' => $daily_quota),
|
| 141 |
'disabled_dates' => $used_quota,
|
| 142 |
'in_cart' => $in_cart,
|
| 143 |
),
|
| 144 |
'#attributes' => array('price' => $product->sell_price),
|
| 145 |
'#suffix' => '<p class="price-holder"></p>',
|
| 146 |
);
|
| 147 |
}
|
| 148 |
else {
|
| 149 |
$form['period'] = array(
|
| 150 |
'#value' => '<p>'. t('Sorry, there are no available quota.') .'</p>',
|
| 151 |
);
|
| 152 |
}
|
| 153 |
}
|
| 154 |
elseif ($product->type == 'ad_product_monthly') {
|
| 155 |
|
| 156 |
// Get all daily quota
|
| 157 |
$monthly_quota = get_available_quota('monthly');
|
| 158 |
// Generate options for a month select box.
|
| 159 |
if (!empty($monthly_quota)) {
|
| 160 |
foreach ($monthly_quota as $month => $quota) {
|
| 161 |
$options[$month] = ad_ubercart_format_month($month);
|
| 162 |
}
|
| 163 |
}
|
| 164 |
|
| 165 |
// Look into user's cart and mark down items which are already selected
|
| 166 |
if (isset($form['#order_id'])) {
|
| 167 |
// Look into opened order products
|
| 168 |
$order = uc_order_load($form['#order_id']);
|
| 169 |
$items = $order->products;
|
| 170 |
}
|
| 171 |
else {
|
| 172 |
// Look into user's cart and mark down items which are already selected
|
| 173 |
$items = uc_cart_get_contents();
|
| 174 |
}
|
| 175 |
foreach ($items as $item) {
|
| 176 |
if ($item->data['ad_plan'] == $product->type) {
|
| 177 |
foreach ($item->data['period'] as $key => $period) {
|
| 178 |
if (isset($options[$key])) {
|
| 179 |
$options[$key] .= '*';
|
| 180 |
// We may only add description if something is really present in a cart
|
| 181 |
$description = t('<b>Note:</b> * — this item is already in your cart. If you select them, they will be removed from your old selections.');
|
| 182 |
}
|
| 183 |
}
|
| 184 |
}
|
| 185 |
}
|
| 186 |
|
| 187 |
$available = !empty($options);
|
| 188 |
|
| 189 |
if ($available) {
|
| 190 |
$form['period'] = array(
|
| 191 |
'#type' => 'select',
|
| 192 |
'#title' => t('Period'),
|
| 193 |
'#description' => $description,
|
| 194 |
'#options' => $options,
|
| 195 |
'#multiple' => TRUE,
|
| 196 |
'#attributes' => array('price' => $product->sell_price),
|
| 197 |
'#suffix' => '<p class="price-holder"></p>',
|
| 198 |
);
|
| 199 |
}
|
| 200 |
else {
|
| 201 |
$form['period'] = array(
|
| 202 |
'#value' => '<p>'. t('Sorry, there are no available quota.') .'</p>',
|
| 203 |
);
|
| 204 |
}
|
| 205 |
}
|
| 206 |
|
| 207 |
// Handlers setup
|
| 208 |
|
| 209 |
// Add to Cart form
|
| 210 |
if (strpos($form['form_id']['#value'], 'uc_product_add_to_cart_form') !== FALSE) {
|
| 211 |
if ($available) {
|
| 212 |
$form['submit']['#weight'] = 100;
|
| 213 |
$form['#validate'][] = 'ad_ubercart_add_to_cart_validate';
|
| 214 |
}
|
| 215 |
else {
|
| 216 |
unset($form['submit']);
|
| 217 |
}
|
| 218 |
}
|
| 219 |
// Order administration form
|
| 220 |
else {
|
| 221 |
// Ad node selector for order administration form
|
| 222 |
$form['existing_node'] = array(
|
| 223 |
'#type' => 'textfield',
|
| 224 |
'#title' => t('Linked Advertisement\'s NID'),
|
| 225 |
'#autocomplete_path' => 'ad/autocomplete',
|
| 226 |
'#description' => t('You may search advertisement by typing <em>##</em> and first chars of ad\'s NID or <em>::</em> and piece of ad\'s title.')
|
| 227 |
);
|
| 228 |
|
| 229 |
$form['buttons']['submit']['#validate'][] = 'ad_ubercart_add_to_cart_validate';
|
| 230 |
array_unshift($form['buttons']['submit']['#submit'], 'ad_ubercart_add_to_cart_submit');
|
| 231 |
}
|
| 232 |
}
|
| 233 |
|
| 234 |
/**
|
| 235 |
* Menu callback; Retrieve a JSON object containing autocomplete suggestions for advertisiment nodes.
|
| 236 |
*/
|
| 237 |
function ad_autocomplete($string = '') {
|
| 238 |
$matches = array();
|
| 239 |
if ($string) {
|
| 240 |
// Allow searching by nid, just by typing "#nid"
|
| 241 |
$result = db_query_range("SELECT n.nid, CONCAT('##', n.nid, '::', n.title) as \"title\" FROM {node} n WHERE n.type = '%s' AND CONCAT('##', n.nid, '::', LOWER(n.title)) LIKE LOWER('%%%s%%')", AD_CONTENT_TYPE, $string, 0, 10);
|
| 242 |
while ($node = db_fetch_object($result)) {
|
| 243 |
$matches[$node->nid] = $node->title;
|
| 244 |
}
|
| 245 |
}
|
| 246 |
|
| 247 |
drupal_json($matches);
|
| 248 |
}
|
| 249 |
|
| 250 |
|
| 251 |
/**
|
| 252 |
* "Add to cart: first step" validator
|
| 253 |
*/
|
| 254 |
function ad_ubercart_add_to_cart_validate(&$form, &$form_state) {
|
| 255 |
if (!isset($form_state['values']['qty'])) {
|
| 256 |
form_set_error('qty', t('Qty should be greater zero.'));
|
| 257 |
}
|
| 258 |
$check_cart_contents = $form_state['values']['form_id'] != 'uc_order_edit_form';
|
| 259 |
if ($form_state['values']['ad_plan'] == 'ad_product_daily') {
|
| 260 |
// Check if any date selected
|
| 261 |
if (!isset($form_state['values']['period']) || empty($form_state['values']['period'])) {
|
| 262 |
form_set_error('period', t('Please, fill the period.'));
|
| 263 |
}
|
| 264 |
else {
|
| 265 |
$period = drupal_map_assoc(explode(',', $form_state['values']['period']));
|
| 266 |
validate_period($period, 'daily', $check_cart_contents);
|
| 267 |
}
|
| 268 |
}
|
| 269 |
elseif ($form_state['values']['ad_plan'] == 'ad_product_monthly') {
|
| 270 |
// Check if any month selected
|
| 271 |
if (!isset($form_state['values']['period']) || empty($form_state['values']['period'])) {
|
| 272 |
form_set_error('period', t('Please, fill the period.'));
|
| 273 |
}
|
| 274 |
else {
|
| 275 |
$period = $form_state['values']['period'];
|
| 276 |
validate_period($period, 'monthly', $check_cart_contents);
|
| 277 |
}
|
| 278 |
}
|
| 279 |
|
| 280 |
$errors = form_get_errors();
|
| 281 |
if (empty($errors) && ((strpos($form_state['values']['form_id'], 'uc_product_add_to_cart_form') !== FALSE) && empty($form_state['storage']))) {
|
| 282 |
$form_state['storage'] = $form_state['values'];
|
| 283 |
unset($form_state['values']);
|
| 284 |
$form_state['rebuild'] = true;
|
| 285 |
}
|
| 286 |
}
|
| 287 |
|
| 288 |
function validate_period($period, $type, $check_cart_contents) {
|
| 289 |
// Check quota amount
|
| 290 |
$result = is_exceed_quota($type, $period);
|
| 291 |
if ($result) {
|
| 292 |
form_set_error('period', t('You have exceeded available quota, please, check your selection.'));
|
| 293 |
}
|
| 294 |
if ($check_cart_contents) {
|
| 295 |
// Remove duplicates from a cart.
|
| 296 |
$items = uc_cart_get_contents();
|
| 297 |
foreach ($items as $item) {
|
| 298 |
if ($item->data['ad_plan'] == 'ad_product_'. $type) {
|
| 299 |
$period = array_merge($period, $item->data['period']);
|
| 300 |
}
|
| 301 |
}
|
| 302 |
$result = is_exceed_quota($type, $period);
|
| 303 |
if ($result) {
|
| 304 |
form_set_error('period', t('The sum of your cart items and current selection is exceeding available quota. Please, remove some of your cart items, to get free slots and than, try to submit the form again.'));
|
| 305 |
}
|
| 306 |
}
|
| 307 |
}
|
| 308 |
|
| 309 |
/**
|
| 310 |
* Add to cart: second step
|
| 311 |
*/
|
| 312 |
function add_to_cart_second_step_form(&$form, &$form_state, $product) {
|
| 313 |
global $user;
|
| 314 |
drupal_add_js('misc/collapse.js');
|
| 315 |
|
| 316 |
// Cleanup form from first step
|
| 317 |
unset($form['nid']);
|
| 318 |
// Also get rid of useless handlers from first step
|
| 319 |
$form['#fs_submit'] = $form['#submit'];
|
| 320 |
$form['#fs_validate'] = $form['#validate'];
|
| 321 |
unset($form['#submit']);
|
| 322 |
unset($form['#validate']);
|
| 323 |
// Get rid of useless buttons
|
| 324 |
unset($form['submit']);
|
| 325 |
|
| 326 |
// Give ability for regitered users to choose existing ads
|
| 327 |
if ($user->uid) {
|
| 328 |
$existing_ads = db_result(db_query('SELECT COUNT(*) FROM {node} n WHERE n.type = "%s" AND n.uid = %d', AD_CONTENT_TYPE, $user->uid));
|
| 329 |
|
| 330 |
// ...but only if they have ads
|
| 331 |
if ($existing_ads) {
|
| 332 |
$form['adnode_wrapper']['adnode'] = array(
|
| 333 |
'#type' => 'select',
|
| 334 |
'#title' => t('Advertisement'),
|
| 335 |
'#options' => array(
|
| 336 |
0 => t('Please, choose'),
|
| 337 |
1 => t('Existing...'),
|
| 338 |
2 => t('Create new...'),
|
| 339 |
),
|
| 340 |
'#default_value' => $form_state['values']['adnode'],
|
| 341 |
'#ahah' => array(
|
| 342 |
'path' => 'cart/ad_ubercart/ahah',
|
| 343 |
'wrapper' => 'ad-ubercart-wrapper',
|
| 344 |
'event' => 'change',
|
| 345 |
),
|
| 346 |
);
|
| 347 |
$form['adnode_wrapper']['adnode_submit'] = array(
|
| 348 |
'#type' => 'submit',
|
| 349 |
'#value' => 'Select',
|
| 350 |
'#suffix' => '<script type="text/javascript">$(\'#edit-adnode-submit\').css(\'display\', \'none\');</script>',
|
| 351 |
);
|
| 352 |
}
|
| 353 |
}
|
| 354 |
|
| 355 |
if (!isset($form['adnode_wrapper']['adnode']) || $form_state['values']['adnode'] == 2) {
|
| 356 |
$form['node'] = add_to_cart_second_step_form_create_node($form, $form_state);
|
| 357 |
// TODO: FileField: Ease integration
|
| 358 |
// Override default FileField's AHAH paths.
|
| 359 |
ad_ubercart_overide_filefield_ahah_path($form['node'], array('node'));
|
| 360 |
}
|
| 361 |
elseif ($form_state['values']['adnode'] == 1) {
|
| 362 |
$form['node'] = add_to_cart_second_step_form_existing_node($form, $form_state);
|
| 363 |
}
|
| 364 |
|
| 365 |
if (isset($form['node'])) {
|
| 366 |
$form['node']['#prefix'] = '<div id="ad-ubercart-wrapper">';
|
| 367 |
$form['node']['#suffix'] = '</div>';
|
| 368 |
}
|
| 369 |
else {
|
| 370 |
$form['node'] = array(
|
| 371 |
'#value' => '<div id="ad-ubercart-wrapper"></div>',
|
| 372 |
);
|
| 373 |
}
|
| 374 |
}
|
| 375 |
|
| 376 |
/**
|
| 377 |
* Add to cart: second step: AHAH callback
|
| 378 |
*/
|
| 379 |
function ad_ubercart_add_to_cart_ahah() {
|
| 380 |
$form_state = array('storage' => NULL, 'submitted' => FALSE);
|
| 381 |
$form_build_id = $_POST['form_build_id'];
|
| 382 |
$form = form_get_cache($form_build_id, $form_state);
|
| 383 |
switch ($_POST['adnode']) {
|
| 384 |
case 1:
|
| 385 |
$form['node'] = add_to_cart_second_step_form_existing_node($form, $form_state);
|
| 386 |
break;
|
| 387 |
case 2:
|
| 388 |
$form['node'] = add_to_cart_second_step_form_create_node($form, $form_state);
|
| 389 |
// TODO: FileField: Ease integration
|
| 390 |
// Override default FileField's AHAH paths.
|
| 391 |
ad_ubercart_overide_filefield_ahah_path($form['node'], array('node'));
|
| 392 |
break;
|
| 393 |
}
|
| 394 |
|
| 395 |
form_set_cache($form_build_id, $form, $form_state);
|
| 396 |
|
| 397 |
// Sanity check for form_builder values.
|
| 398 |
if (!empty($form_state['values'])) {
|
| 399 |
$_POST = array_merge($_POST, $form_state['values']);
|
| 400 |
}
|
| 401 |
|
| 402 |
$form += array(
|
| 403 |
'#post' => $_POST,
|
| 404 |
'#programmed' => FALSE,
|
| 405 |
);
|
| 406 |
|
| 407 |
// Rebuild and render the form.
|
| 408 |
$form = form_builder($_POST['form_id'], $form, $form_state);
|
| 409 |
$output = drupal_render($form['node']);
|
| 410 |
if ($output) {
|
| 411 |
$javascript = drupal_add_js(NULL, NULL);
|
| 412 |
if (isset($javascript['setting'])) {
|
| 413 |
$output .= '<script type="text/javascript">jQuery.extend(Drupal.settings, '. drupal_to_js(call_user_func_array('array_merge_recursive', $javascript['setting'])) .');Drupal.attachBehaviors("form");</script>';
|
| 414 |
}
|
| 415 |
|
| 416 |
drupal_json(array(
|
| 417 |
'status' => TRUE,
|
| 418 |
'data' => $output,
|
| 419 |
));
|
| 420 |
}
|
| 421 |
}
|
| 422 |
|
| 423 |
/**
|
| 424 |
* Add to cart: second step: Prepare existing Ad selection form
|
| 425 |
*/
|
| 426 |
function add_to_cart_second_step_form_existing_node($form, $form_state) {
|
| 427 |
global $user;
|
| 428 |
|
| 429 |
$existing_ads = array();
|
| 430 |
$result = db_query_range('SELECT nid FROM {node} WHERE type = "%s" AND uid = %d ORDER BY created DESC', AD_CONTENT_TYPE, $user->uid, 0, 10);
|
| 431 |
while ($nid = db_result($result)) {
|
| 432 |
$ad = node_load($nid);
|
| 433 |
$existing_ads[$nid] = theme('ad_in_cart', $ad);
|
| 434 |
}
|
| 435 |
|
| 436 |
$ad_form['existing_node'] = array(
|
| 437 |
'#type' => 'radios',
|
| 438 |
'#title' => t('Your Advertisements'),
|
| 439 |
'#options' => $existing_ads,
|
| 440 |
'#default_value' => $form_state['values']['existing_node'],
|
| 441 |
);
|
| 442 |
$ad_form['submit'] = array(
|
| 443 |
'#type' => 'submit',
|
| 444 |
'#value' => t('Submit'),
|
| 445 |
'#validate' => $form['#fs_validate'],
|
| 446 |
'#submit' => array_merge(array('ad_ubercart_add_to_cart_submit'), $form['#fs_submit']),
|
| 447 |
);
|
| 448 |
return $ad_form;
|
| 449 |
}
|
| 450 |
|
| 451 |
/**
|
| 452 |
* Add to cart: second step: Prepare Ad creation form
|
| 453 |
*/
|
| 454 |
function add_to_cart_second_step_form_create_node($form, &$form_state) {
|
| 455 |
global $user;
|
| 456 |
module_load_include('pages.inc', 'node');
|
| 457 |
|
| 458 |
// Create new node form
|
| 459 |
$node = new stdClass();
|
| 460 |
$node->type = AD_CONTENT_TYPE;
|
| 461 |
if ($user->uid) {
|
| 462 |
$node->uid = $user->uid;
|
| 463 |
$node->name = $user->name;
|
| 464 |
}
|
| 465 |
|
| 466 |
// Prefill other values from content type settings.
|
| 467 |
node_object_prepare($node);
|
| 468 |
if (empty($form_state['values'])) {
|
| 469 |
$form_state['values'] = array();
|
| 470 |
}
|
| 471 |
$form_state['values'] = array_merge($form_state['values'], (array)$node);
|
| 472 |
|
| 473 |
// Retrieve and prepare a node form.
|
| 474 |
$ad_form = drupal_retrieve_form($node->type .'_node_form', $form_state, $node);
|
| 475 |
drupal_prepare_form($node->type .'_node_form', $ad_form, $form_state);
|
| 476 |
|
| 477 |
// Strip out teaser field, as it useless and brings validation warnings.
|
| 478 |
// This code taken from Excerpt module.
|
| 479 |
if(isset($ad_form['body_field']['teaser_js'])) {
|
| 480 |
unset($ad_form['body_field']['teaser_js']);
|
| 481 |
unset($ad_form['body_field']['teaser_include']);
|
| 482 |
|
| 483 |
if(!empty($ad_form['body_field']['#after_build'])) {
|
| 484 |
if($id = array_search('node_teaser_js', $ad_form['body_field']['#after_build'])) {
|
| 485 |
unset($ad_form['body_field']['#after_build'][$id]);
|
| 486 |
}
|
| 487 |
if($id = array_search('node_teaser_include_verify', $ad_form['body_field']['#after_build'])) {
|
| 488 |
unset($ad_form['body_field']['#after_build'][$id]);
|
| 489 |
}
|
| 490 |
}
|
| 491 |
}
|
| 492 |
|
| 493 |
// Cut form's identity
|
| 494 |
unset($ad_form['form_id']);
|
| 495 |
unset($ad_form['form_token']);
|
| 496 |
$ad_form['#type'] = 'markup';
|
| 497 |
|
| 498 |
// TODO: FileField: Ease integration
|
| 499 |
// Override default FileField's validator.
|
| 500 |
foreach ($ad_form['#validate'] as $key => $validator) {
|
| 501 |
if ($validator == 'filefield_node_form_validate') {
|
| 502 |
$ad_form['#validate'][$key] = 'ad_ubercart_filefield_node_form_validate';
|
| 503 |
}
|
| 504 |
}
|
| 505 |
|
| 506 |
// Handlers setup
|
| 507 |
if (strpos($form['form_id']['#value'], 'uc_product_add_to_cart_form') !== FALSE) {
|
| 508 |
array_unshift($ad_form['#validate'], 'ad_ubercart_add_to_cart_second_step_validate');
|
| 509 |
$ad_form['buttons']['preview']['#validate'] = array_merge($ad_form['#validate'], $form['#fs_validate']);
|
| 510 |
$ad_form['buttons']['submit']['#validate'] = $ad_form['buttons']['preview']['#validate'];
|
| 511 |
|
| 512 |
$ad_form['buttons']['submit']['#submit'][] = 'ad_ubercart_add_to_cart_submit';
|
| 513 |
$ad_form['buttons']['submit']['#submit'] = array_merge($ad_form['buttons']['submit']['#submit'], $form['#fs_submit']);
|
| 514 |
|
| 515 |
unset($ad_form['buttons']['delete']);
|
| 516 |
unset($ad_form['buttons']['preview']);
|
| 517 |
}
|
| 518 |
|
| 519 |
return $ad_form;
|
| 520 |
}
|
| 521 |
|
| 522 |
|
| 523 |
/**
|
| 524 |
* "Add to cart: second step" validator
|
| 525 |
*/
|
| 526 |
function ad_ubercart_add_to_cart_second_step_validate($form, &$form_state) {
|
| 527 |
// Include Node module to get it's validator's implementations.
|
| 528 |
module_load_include('pages.inc', 'node');
|
| 529 |
}
|
| 530 |
|
| 531 |
/**
|
| 532 |
* "Add to cart" submit handler.
|
| 533 |
*/
|
| 534 |
function ad_ubercart_add_to_cart_submit($form, &$form_state) {
|
| 535 |
// Restore values from first step
|
| 536 |
if (!empty($form_state['storage'])) {
|
| 537 |
$form_state['values'] = array_merge($form_state['values'], $form_state['storage']);
|
| 538 |
unset($form_state['storage']);
|
| 539 |
}
|
| 540 |
|
| 541 |
// Add Advertisiment node to cart contents.
|
| 542 |
if ($form_state['values']['existing_node']) {
|
| 543 |
$form_state['values']['ad'] = ad_ubercart_clone_ad($form_state['values']['existing_node']);
|
| 544 |
}
|
| 545 |
else {
|
| 546 |
// By some weird reasons, correct nid is placing to the
|
| 547 |
// root of $forms_state array after new node creation.
|
| 548 |
$form_state['values']['ad'] = $form_state['nid'];
|
| 549 |
}
|
| 550 |
|
| 551 |
// Update quantity according to selected period
|
| 552 |
if ($form_state['values']['ad_plan'] == 'ad_product_daily') {
|
| 553 |
$form_state['values']['period'] = drupal_map_assoc(explode(',', $form_state['values']['period']));
|
| 554 |
$form_state['values']['qty'] = count($form_state['values']['period']);
|
| 555 |
}
|
| 556 |
elseif ($form_state['values']['ad_plan'] == 'ad_product_monthly') {
|
| 557 |
$form_state['values']['qty'] = count($form_state['values']['period']);
|
| 558 |
}
|
| 559 |
|
| 560 |
// Remove duplicates from a cart/order
|
| 561 |
if ($form_state['values']['form_id'] != 'uc_order_edit_form') {
|
| 562 |
remove_duplicates_from_cart($form_state['values']);
|
| 563 |
}
|
| 564 |
else {
|
| 565 |
remove_duplicates_from_order($form['#order_id'], $form_state['values']);
|
| 566 |
}
|
| 567 |
|
| 568 |
/************************************************************************
|
| 569 |
*** Here should be added additional submit handlers of the cart contents
|
| 570 |
***/
|
| 571 |
}
|
| 572 |
|
| 573 |
/**
|
| 574 |
* Clone existing node.
|
| 575 |
*/
|
| 576 |
function ad_ubercart_clone_ad($aid) {
|
| 577 |
global $user;
|
| 578 |
// Create a new node
|
| 579 |
$form_state = array();
|
| 580 |
module_load_include('inc', 'node', 'node.pages');
|
| 581 |
|
| 582 |
$form_state['values'] = (array)node_load($aid);
|
| 583 |
if ($user->uid) {
|
| 584 |
$form_state['values']['uid'] = $user->uid;
|
| 585 |
$form_state['values']['name'] = $user->name;
|
| 586 |
}
|
| 587 |
$form_state['values']['op'] = t('Save');
|
| 588 |
unset($form_state['values']['nid']);
|
| 589 |
$node = array('type' => AD_CONTENT_TYPE);
|
| 590 |
drupal_execute(AD_CONTENT_TYPE .'_node_form', $form_state, (object)$node);
|
| 591 |
|
| 592 |
return $form_state['nid'];
|
| 593 |
}
|
| 594 |
|
| 595 |
/**
|
| 596 |
* Remove duplicate items from cart.
|
| 597 |
*/
|
| 598 |
function remove_duplicates_from_cart($values) {
|
| 599 |
$items = uc_cart_get_contents();
|
| 600 |
foreach ($items as $item) {
|
| 601 |
if ($item->data['ad_plan'] == $values['ad_plan']) {
|
| 602 |
$diff = array_intersect_key($item->data['period'], $values['period']);
|
| 603 |
if (!empty($diff)) {
|
| 604 |
$old_data = $item->data;
|
| 605 |
$item->data['period'] = array_diff_key($item->data['period'], $diff);
|
| 606 |
|
| 607 |
$cid = uc_cart_get_id();
|
| 608 |
if (empty($item->data['period'])) {
|
| 609 |
uc_cart_remove_item($item->nid, $cid, $old_data);
|
| 610 |
|
| 611 |
// Remove linked node as well if it's temporary
|
| 612 |
if ($nid = $item->data['ad'] && $ad = node_load($nid) && $ad->uid == 0) {
|
| 613 |
node_delete($nid);
|
| 614 |
}
|
| 615 |
}
|
| 616 |
else {
|
| 617 |
$item->qty = count($item->data['period']);
|
| 618 |
db_query("UPDATE {uc_cart_products} SET qty = %d, changed = %d, data = '%s' WHERE nid = %d AND cart_id = '%s' AND data = '%s'", $item->qty, time(), serialize($item->data), $item->nid, $cid, serialize($old_data));
|
| 619 |
cache_clear_all();
|
| 620 |
}
|
| 621 |
drupal_set_message(t('Your previously added items were updated. Removed !periods.', array('!periods' => implode(', ', $diff))));
|
| 622 |
}
|
| 623 |
}
|
| 624 |
}
|
| 625 |
}
|
| 626 |
|
| 627 |
/**
|
| 628 |
* Remove duplicate items from order contents.
|
| 629 |
*/
|
| 630 |
function remove_duplicates_from_order($order_id, $values) {
|
| 631 |
$order = uc_order_load($order_id);
|
| 632 |
foreach ($order->products as $product) {
|
| 633 |
if ($product->data['ad_plan'] == $values['ad_plan']) {
|
| 634 |
$diff = array_intersect_key($product->data['period'], $values['period']);
|
| 635 |
if (!empty($diff)) {
|
| 636 |
$product->data['period'] = array_diff_key($product->data['period'], $diff);
|
| 637 |
// Remove product from a list if it's period exhaused
|
| 638 |
if (empty($product->data['period'])) {
|
| 639 |
db_query("DELETE FROM {uc_order_products} WHERE order_product_id = %d", $product->order_product_id);
|
| 640 |
if (variable_get('uc_order_logging', TRUE)) {
|
| 641 |
uc_order_log_changes($form['#order_id'], array('add' => 'Product removed from order.'));
|
| 642 |
}
|
| 643 |
// Remove linked node as well if it's temporary
|
| 644 |
if ($nid = $product->data['ad'] && $ad = node_load($nid) && $ad->uid == 0) {
|
| 645 |
node_delete($nid);
|
| 646 |
}
|
| 647 |
}
|
| 648 |
// or just update it's quantity
|
| 649 |
else {
|
| 650 |
$product->qty = count($product->data['period']);
|
| 651 |
uc_order_product_save($form['#order_id'], $product);
|
| 652 |
if (variable_get('uc_order_logging', TRUE)) {
|
| 653 |
uc_order_log_changes($form['#order_id'], array('add' => 'Order products were updated.'));
|
| 654 |
}
|
| 655 |
}
|
| 656 |
drupal_set_message(t('Order products were updated. Removed !periods from old products.', array('!periods' => implode(', ', $diff))));
|
| 657 |
}
|
| 658 |
}
|
| 659 |
}
|
| 660 |
}
|
| 661 |
|
| 662 |
|
| 663 |
/**
|
| 664 |
* Implementation of hook_form_$form_id_alter().
|
| 665 |
*
|
| 666 |
* Hide quantity from cart form.
|
| 667 |
*/
|
| 668 |
function ad_ubercart_form_uc_cart_view_form_alter(&$form, &$form_state) {
|
| 669 |
$only_ads_in_cart = TRUE;
|
| 670 |
foreach (element_children($form['items']) as $item) {
|
| 671 |
if ($form['items'][$item]['nid']) {
|
| 672 |
// determine if a row is ad
|
| 673 |
$data = unserialize($form['items'][$item]['data']['#value']);
|
| 674 |
if (isset($data['ad_plan'])) {
|
| 675 |
$form['items'][$item]['qty']['#type'] = 'hidden';
|
| 676 |
}
|
| 677 |
else {
|
| 678 |
// if not only ads in a cart, we should live entire column
|
| 679 |
$only_ads_in_cart = FALSE;
|
| 680 |
}
|
| 681 |
}
|
| 682 |
}
|
| 683 |
// if not only ads in a cart, we should live entire column
|
| 684 |
if ($only_ads_in_cart) {
|
| 685 |
//unset($form['items']['#columns']['qty']);
|
| 686 |
}
|
| 687 |
}
|
| 688 |
|
| 689 |
/**
|
| 690 |
* Implementation of hook_form_$form_id_alter().
|
| 691 |
*
|
| 692 |
* Output ad_product item's information to admin order form.
|
| 693 |
*/
|
| 694 |
function ad_ubercart_form_uc_order_edit_products_form_alter(&$form, &$form_state) {
|
| 695 |
foreach (element_children($form['products']) as $key) {
|
| 696 |
$item = new stdClass();
|
| 697 |
$item->data = unserialize($form['products'][$key]['data']['#value']);
|
| 698 |
$description = ad_ubercart_cart_item_description($item);
|
| 699 |
$form['products'][$key]['title']['#suffix'] = '<div id="prod_title_'. $key .'">'.$description.'</div>';
|
| 700 |
}
|
| 701 |
}
|
| 702 |
|
| 703 |
/**
|
| 704 |
* Gets all quota information.
|
| 705 |
*
|
| 706 |
* @param $type
|
| 707 |
* "daily" or "monthly"
|
| 708 |
*/
|
| 709 |
function get_quota($type = NULL) {
|
| 710 |
$result = db_query('SELECT * FROM {ad_quota} aq WHERE month >= "%s" ORDER BY aq.month ASC', date('Y-m'));
|
| 711 |
while ($data = db_fetch_array($result)) {
|
| 712 |
if ($type) {
|
| 713 |
if ($data[$type]) {
|
| 714 |
$quota[$data['month']] = $data[$type];
|
| 715 |
}
|
| 716 |
}
|
| 717 |
else {
|
| 718 |
$quota[$data['month']] = $data;
|
| 719 |
}
|
| 720 |
}
|
| 721 |
return $quota;
|
| 722 |
}
|
| 723 |
|
| 724 |
/**
|
| 725 |
* Gets used quota information.
|
| 726 |
*
|
| 727 |
* @param $type
|
| 728 |
* "daily" or "monthly"
|
| 729 |
*/
|
| 730 |
function get_used_quota($type) {
|
| 731 |
$result = db_query('SELECT * FROM {ad_used_quota} auq WHERE auq.type = "%s" AND date >= "%s"', $type, date('Y-m'));
|
| 732 |
$used_quota = array();
|
| 733 |
while ($data = db_fetch_array($result)) {
|
| 734 |
$used_quota[$data['date']] = $data['date'];
|
| 735 |
}
|
| 736 |
return $used_quota;
|
| 737 |
}
|
| 738 |
|
| 739 |
/**
|
| 740 |
* Gets available quota.
|
| 741 |
*
|
| 742 |
* @param $type
|
| 743 |
* "daily" or "monthly"
|
| 744 |
*/
|
| 745 |
function get_available_quota($type, $additional_period = NULL) {
|
| 746 |
// Get all daily quota
|
| 747 |
$avail_quota = get_quota($type);
|
| 748 |
$used_quota = get_used_quota($type);
|
| 749 |
foreach ($used_quota as $date => $d) {
|
| 750 |
// this will produce YYYY-MM from date
|
| 751 |
$month = substr($date, 0, 7);
|
| 752 |
$avail_quota[$month]--;
|
| 753 |
if ($avail_quota[$month] == 0) {
|
| 754 |
unset($avail_quota[$month]);
|
| 755 |
}
|
| 756 |
}
|
| 757 |
if (!empty($additional_period)) {
|
| 758 |
foreach ($additional_period as $date => $d) {
|
| 759 |
// avoid double checking
|
| 760 |
if (!isset($used_quota[$date])) {
|
| 761 |
$used_quota[$date] = $d;
|
| 762 |
// this will produce YYYY-MM from date
|
| 763 |
$month = substr($date, 0, 7);
|
| 764 |
$avail_quota[$month]--;
|
| 765 |
}
|
| 766 |
}
|
| 767 |
}
|
| 768 |
return $avail_quota;
|
| 769 |
}
|
| 770 |
|
| 771 |
/**
|
| 772 |
* Check quota exceeding. Returns FALSE, if quota was exceeded.
|
| 773 |
*/
|
| 774 |
function is_exceed_quota($type, $period) {
|
| 775 |
if ($type == 'daily') {
|
| 776 |
$used_quota = get_used_quota('daily');
|
| 777 |
foreach ($period as $date => $value) {
|
| 778 |
if (isset($used_quota[$date])) {
|
| 779 |
return QUOTA_EXCEED_USED_DATES;
|
| 780 |
}
|
| 781 |
}
|
| 782 |
}
|
| 783 |
|
| 784 |
$quota = get_available_quota($type, $period);
|
| 785 |
foreach ($quota as $date => $value) {
|
| 786 |
if ($value < 0) {
|
| 787 |
return QUOTA_EXCEED_MAX_SELECTED;
|
| 788 |
}
|
| 789 |
}
|
| 790 |
return FALSE;
|
| 791 |
}
|
| 792 |
|
| 793 |
|
| 794 |
|
| 795 |
|
| 796 |
|
| 797 |
|
| 798 |
|
| 799 |
|
| 800 |
|
| 801 |
|
| 802 |
|
| 803 |
|
| 804 |
|
| 805 |
|
| 806 |
|
| 807 |
// TODO: FileField: Ease integration
|
| 808 |
|
| 809 |
/**
|
| 810 |
* Override default FileField's AHAH paths.
|
| 811 |
*/
|
| 812 |
function ad_ubercart_overide_filefield_ahah_path(&$form, $parents) {
|
| 813 |
if (isset($form['#field_info'])) {
|
| 814 |
foreach ($form['#field_info'] as $field_name => $field) {
|
| 815 |
if ($form['#field_info'][$field_name]['type'] == 'filefield') {
|
| 816 |
$form[$field_name]['#after_build'] = array('ad_ubercart_filefield_widget_after_build');
|
| 817 |
$form[$field_name]['#upline'] = $parents;
|
| 818 |
}
|
| 819 |
}
|
| 820 |
}
|
| 821 |
}
|
| 822 |
|
| 823 |
/**
|
| 824 |
* Afterbuild callback which adds parental information for FileField in sub-forms.
|
| 825 |
*/
|
| 826 |
function ad_ubercart_filefield_widget_after_build($element, $form_state) {
|
| 827 |
foreach (element_children($element) as $key) {
|
| 828 |
// Change AHAH submit path
|
| 829 |
$element[$key]['filefield_upload']['#ahah']['path'] .= '/'. implode('][', $element['#upline']);
|
| 830 |
$element[$key]['filefield_remove']['#ahah']['path'] .= '/'. implode('][', $element['#upline']);
|
| 831 |
|
| 832 |
// Override currently set JS settings for both elements.
|
| 833 |
$element[$key]['filefield_upload']['#id'] .= '_changed';
|
| 834 |
form_expand_ahah($element[$key]['filefield_upload']);
|
| 835 |
$element[$key]['filefield_remove']['#id'] .= '_changed';
|
| 836 |
form_expand_ahah($element[$key]['filefield_remove']);
|
| 837 |
}
|
| 838 |
return $element;
|
| 839 |
}
|
| 840 |
|
| 841 |
/**
|
| 842 |
* Override default filefield's validator to validate only subform.
|
| 843 |
*/
|
| 844 |
function ad_ubercart_filefield_node_form_validate($form, &$form_state) {
|
| 845 |
return filefield_node_form_validate($form['node'], &$form_state);
|
| 846 |
}
|
| 847 |
|
| 848 |
/**
|
| 849 |
* Alternative FileField AHAH callback which supports sub-form elements.
|
| 850 |
*
|
| 851 |
* The only difference with original function is $form = $form[$parents];
|
| 852 |
*/
|
| 853 |
function ad_ubercart_filefield_js($type_name, $field_name, $delta) {
|
| 854 |
$field = content_fields($field_name, $type_name);
|
| 855 |
|
| 856 |
if (empty($field) || empty($_POST['form_build_id'])) {
|
| 857 |
// Invalid request.
|
| 858 |
drupal_set_message(t('An unrecoverable error occurred. The uploaded file likely exceeded the maximum file size (@size) that this server supports.', array('@size' => format_size(file_upload_max_size()))), 'error');
|
| 859 |
print drupal_to_js(array('data' => theme('status_messages')));
|
| 860 |
exit;
|
| 861 |
}
|
| 862 |
|
| 863 |
// Build the new form.
|
| 864 |
$form_state = array('submitted' => FALSE);
|
| 865 |
$form_build_id = $_POST['form_build_id'];
|
| 866 |
$form = form_get_cache($form_build_id, $form_state);
|
| 867 |
|
| 868 |
if (!$form) {
|
| 869 |
// Invalid form_build_id.
|
| 870 |
drupal_set_message(t('An unrecoverable error occurred. This form was missing from the server cache. Try reloading the page and submitting again.'), 'error');
|
| 871 |
print drupal_to_js(array('data' => theme('status_messages')));
|
| 872 |
exit;
|
| 873 |
}
|
| 874 |
|
| 875 |
// Build the form. This calls the file field's #value_callback function and
|
| 876 |
// saves the uploaded file. Since this form is already marked as cached
|
| 877 |
// (the #cache property is TRUE), the cache is updated automatically and we
|
| 878 |
// don't need to call form_set_cache().
|
| 879 |
$args = $form['#parameters'];
|
| 880 |
$form_id = array_shift($args);
|
| 881 |
$form['#post'] = $_POST;
|
| 882 |
$form = form_builder($form_id, $form, $form_state);
|
| 883 |
|
| 884 |
$parents = arg(5);
|
| 885 |
if (isset($parents)) {
|
| 886 |
$form = $form[$parents];
|
| 887 |
}
|
| 888 |
|
| 889 |
// Update the cached form with the new element at the right place in the form.
|
| 890 |
if (module_exists('fieldgroup') && ($group_name = _fieldgroup_field_get_group($type_name, $field_name))) {
|
| 891 |
if (isset($form['#multigroups']) && isset($form['#multigroups'][$group_name][$field_name])) {
|
| 892 |
$form_element = $form[$group_name][$delta][$field_name];
|
| 893 |
}
|
| 894 |
else {
|
| 895 |
$form_element = $form[$group_name][$field_name][$delta];
|
| 896 |
}
|
| 897 |
}
|
| 898 |
else {
|
| 899 |
$form_element = $form[$field_name][$delta];
|
| 900 |
}
|
| 901 |
|
| 902 |
if (isset($form_element['_weight'])) {
|
| 903 |
unset($form_element['_weight']);
|
| 904 |
}
|
| 905 |
|
| 906 |
$output = drupal_render($form_element);
|
| 907 |
|
| 908 |
// AHAH is not being nice to us and doesn't know the "other" button (that is,
|
| 909 |
// either "Upload" or "Delete") yet. Which in turn causes it not to attach
|
| 910 |
// AHAH behaviours after replacing the element. So we need to tell it first.
|
| 911 |
|
| 912 |
// Loop through the JS settings and find the settings needed for our buttons.
|
| 913 |
$javascript = drupal_add_js(NULL, NULL);
|
| 914 |
$filefield_ahah_settings = array();
|
| 915 |
if (isset($javascript['setting'])) {
|
| 916 |
foreach ($javascript['setting'] as $settings) {
|
| 917 |
if (isset($settings['ahah'])) {
|
| 918 |
foreach ($settings['ahah'] as $id => $ahah_settings) {
|
| 919 |
if (strpos($id, 'filefield-upload') || strpos($id, 'filefield-remove')) {
|
| 920 |
$filefield_ahah_settings[$id] = $ahah_settings;
|
| 921 |
}
|
| 922 |
}
|
| 923 |
}
|
| 924 |
}
|
| 925 |
}
|
| 926 |
|
| 927 |
// Add the AHAH settings needed for our new buttons.
|
| 928 |
if (!empty($filefield_ahah_settings)) {
|
| 929 |
$output .= '<script type="text/javascript">jQuery.extend(Drupal.settings.ahah, '. drupal_to_js($filefield_ahah_settings) .');</script>';
|
| 930 |
}
|
| 931 |
|
| 932 |
$output = theme('status_messages') . $output;
|
| 933 |
|
| 934 |
// For some reason, file uploads don't like drupal_json() with its manual
|
| 935 |
// setting of the text/javascript HTTP header. So use this one instead.
|
| 936 |
$GLOBALS['devel_shutdown'] = FALSE;
|
| 937 |
print drupal_to_js(array('status' => TRUE, 'data' => $output));
|
| 938 |
exit;
|
| 939 |
}
|