Projet

Général

Profil

Paste
Télécharger (17,9 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / commerce / modules / product / commerce_product_ui.module @ dbb0c974

1
<?php
2

    
3
/**
4
 * @file
5
 */
6

    
7
/**
8
 * Implements hook_menu().
9
 */
10
function commerce_product_ui_menu() {
11
  $items = array();
12

    
13
  // Note: admin/commerce/products is defined by a default View.
14

    
15
  // Add a product.
16
  $items['admin/commerce/products/add'] = array(
17
    'title' => 'Add a product',
18
    'description' => 'Add a new product for sale.',
19
    'page callback' => 'commerce_product_ui_add_page',
20
    'access callback' => 'commerce_product_ui_product_add_any_access',
21
    'weight' => 10,
22
    'file' => 'includes/commerce_product_ui.products.inc',
23
  );
24
  foreach (commerce_product_types() as $type => $product_type) {
25
    $items['admin/commerce/products/add/' . strtr($type, array('_' => '-'))] = array(
26
      'title' => 'Create !name',
27
      'title arguments' => array('!name' => $product_type['name']),
28
      'description' => $product_type['description'],
29
      'page callback' => 'commerce_product_ui_product_form_wrapper',
30
      'page arguments' => array(commerce_product_new($type)),
31
      'access callback' => 'commerce_product_access',
32
      'access arguments' => array('create', commerce_product_new($type)),
33
      'file' => 'includes/commerce_product_ui.products.inc',
34
    );
35
  }
36

    
37
  $items['admin/commerce/products/%commerce_product'] = array(
38
    'title callback' => 'commerce_product_ui_product_title',
39
    'title arguments' => array(3),
40
    'page callback' => 'commerce_product_ui_product_form_wrapper',
41
    'page arguments' => array(3),
42
    'access callback' => 'commerce_product_access',
43
    'access arguments' => array('update', 3),
44
    'weight' => 0,
45
    'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
46
    'file' => 'includes/commerce_product_ui.products.inc',
47
  );
48
  $items['admin/commerce/products/%commerce_product/edit'] = array(
49
    'title' => 'Edit',
50
    'type' => MENU_DEFAULT_LOCAL_TASK,
51
    'weight' => -10,
52
    'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
53
  );
54
  $items['admin/commerce/products/%commerce_product/delete'] = array(
55
    'title' => 'Delete',
56
    'page callback' => 'commerce_product_ui_product_delete_form_wrapper',
57
    'page arguments' => array(3),
58
    'access callback' => 'commerce_product_access',
59
    'access arguments' => array('delete', 3),
60
    'type' => MENU_LOCAL_TASK,
61
    'weight' => 20,
62
    'context' => MENU_CONTEXT_INLINE,
63
    'file' => 'includes/commerce_product_ui.products.inc',
64
  );
65

    
66
  $items['admin/commerce/products/types'] = array(
67
    'title' => 'Product types',
68
    'description' => 'Manage products types for your store.',
69
    'page callback' => 'commerce_product_ui_types_overview',
70
    'access arguments' => array('administer product types'),
71
    'type' => MENU_LOCAL_TASK,
72
    'weight' => 0,
73
    'file' => 'includes/commerce_product_ui.types.inc',
74
  );
75
  $items['admin/commerce/products/types/add'] = array(
76
    'title' => 'Add product type',
77
    'page callback' => 'commerce_product_ui_product_type_form_wrapper',
78
    'page arguments' => array(commerce_product_ui_product_type_new()),
79
    'access arguments' => array('administer product types'),
80
    'type' => MENU_LOCAL_ACTION,
81
    'file' => 'includes/commerce_product_ui.types.inc',
82
  );
83
  foreach (commerce_product_types() as $type => $product_type) {
84
    // Convert underscores to hyphens for the menu item argument.
85
    $type_arg = strtr($type, '_', '-');
86

    
87
    $items['admin/commerce/products/types/' . $type_arg] = array(
88
      'title' => $product_type['name'],
89
      'page callback' => 'commerce_product_ui_product_type_form_wrapper',
90
      'page arguments' => array($type),
91
      'access arguments' => array('administer product types'),
92
      'file' => 'includes/commerce_product_ui.types.inc',
93
    );
94

    
95
    if ($product_type['module'] == 'commerce_product_ui') {
96
      $items['admin/commerce/products/types/' . $type_arg . '/edit'] = array(
97
        'title' => 'Edit',
98
        'access callback' => 'commerce_product_ui_product_type_update_access',
99
        'access arguments' => array($type),
100
        'type' => MENU_DEFAULT_LOCAL_TASK,
101
        'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
102
      );
103
      $items['admin/commerce/products/types/' . $type_arg . '/delete'] = array(
104
        'title' => 'Delete',
105
        'page callback' => 'commerce_product_ui_product_type_delete_form_wrapper',
106
        'page arguments' => array($type),
107
        'access callback' => 'commerce_product_ui_product_type_update_access',
108
        'access arguments' => array($type),
109
        'type' => MENU_LOCAL_TASK,
110
        'context' => MENU_CONTEXT_INLINE,
111
        'weight' => 10,
112
        'file' => 'includes/commerce_product_ui.types.inc',
113
      );
114
    }
115
  }
116

    
117
  return $items;
118
}
119

    
120
/**
121
 * Menu item title callback: returns the SKU of a product for its pages.
122
 *
123
 * @param $product
124
 *   The product object as loaded via the URL wildcard.
125
 * @return
126
 *   A page title of the format "Product: [SKU]".
127
 */
128
function commerce_product_ui_product_title($product) {
129
  return t('Product: @sku', array('@sku' => $product->sku));
130
}
131

    
132
/**
133
 * Access callback: determines if the user can create any type of product.
134
 */
135
function commerce_product_ui_product_add_any_access() {
136
  // Grant automatic access to users with administer products permission.
137
  if (user_access('administer commerce_product entities')) {
138
    return TRUE;
139
  }
140

    
141
  // Check the user's access on a product type basis.
142
  foreach (commerce_product_types() as $type => $product_type) {
143
    if (commerce_product_access('create', commerce_product_new($type))) {
144
      return TRUE;
145
    }
146
  }
147

    
148
  return FALSE;
149
}
150

    
151
/**
152
 * Access callback: determines if the user can edit or delete a product type.
153
 *
154
 * @param $type
155
 *   The machine-name of the product type to be edited or deleted.
156
 */
157
function commerce_product_ui_product_type_update_access($type) {
158
  $product_type = commerce_product_type_load($type);
159

    
160
  if ($product_type['module'] == 'commerce_product_ui') {
161
    return user_access('administer product types');
162
  }
163

    
164
  return FALSE;
165
}
166

    
167
/**
168
 * Implements hook_menu_alter().
169
 */
170
function commerce_product_ui_menu_alter(&$items) {
171
  // Transform the field UI tabs into contextual links.
172
  foreach (commerce_product_types() as $type => $product_type) {
173
    // Convert underscores to hyphens for the menu item argument.
174
    $type_arg = strtr($type, '_', '-');
175

    
176
    $items['admin/commerce/products/types/' . $type_arg . '/fields']['context'] = MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE;
177
    $items['admin/commerce/products/types/' . $type_arg . '/display']['context'] = MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE;
178
  }
179
}
180

    
181
/**
182
 * Implements hook_menu_local_tasks_alter().
183
 */
184
function commerce_product_ui_menu_local_tasks_alter(&$data, $router_item, $root_path) {
185
  // Add action link 'admin/commerce/products/add' on 'admin/commerce/products'.
186
  if ($root_path == 'admin/commerce/products') {
187
    $item = menu_get_item('admin/commerce/products/add');
188
    if ($item['access']) {
189
      $data['actions']['output'][] = array(
190
        '#theme' => 'menu_local_action',
191
        '#link' => $item,
192
      );
193
    }
194
  }
195
}
196

    
197
/**
198
 * Implements hook_admin_menu_map().
199
 */
200
function commerce_product_ui_admin_menu_map() {
201
  // Add awareness to the administration menu of the various product types so
202
  // they are included in the dropdown menu.
203
  $type_args = array();
204

    
205
  foreach (array_keys(commerce_product_types()) as $type) {
206
    $type_args[] = strtr($type, '_', '-');
207
  }
208

    
209
  $map['admin/commerce/products/types/%'] = array(
210
    'parent' => 'admin/commerce/products/types',
211
    'arguments' => array(
212
      array('%' => $type_args),
213
    ),
214
  );
215

    
216
  return $map;
217
}
218

    
219
/**
220
 * Implements hook_help().
221
 */
222
function commerce_product_ui_help($path, $arg) {
223
  switch ($path) {
224
    case 'admin/commerce/products/types/add':
225
      return '<p>' . t('Individual product types can have different fields assigned to them.') . '</p>';
226
  }
227

    
228
  // Return the user defined help text per product type when adding or editing products.
229
  if ($arg[1] == 'commerce' && $arg[2] == 'products' && $arg[3] == 'add' && $arg[4]) {
230
    $product_type = commerce_product_type_load($arg[4]);
231
    return (!empty($product_type['help']) ? '<p>' . filter_xss_admin($product_type['help']) . '</p>' : '');
232
  }
233
  elseif ($arg[1] == 'commerce' && $arg[2] == 'products' && is_numeric($arg[3])) {
234
    $product = commerce_product_load($arg[3]);
235
    $product_type = commerce_product_type_load($product->type);
236
    return (!empty($product_type['help']) ? '<p>' . filter_xss_admin($product_type['help']) . '</p>' : '');
237
  }
238
}
239

    
240
/**
241
 * Implements hook_theme().
242
 */
243
function commerce_product_ui_theme() {
244
  return array(
245
    'product_add_list' => array(
246
      'variables' => array('content' => array()),
247
      'file' => 'includes/commerce_product_ui.products.inc',
248
    ),
249
    'product_type_admin_overview' => array(
250
      'variables' => array('type' => NULL),
251
      'file' => 'includes/commerce_product_ui.types.inc',
252
    ),
253
  );
254
}
255

    
256
/**
257
 * Implements hook_entity_info_alter().
258
 */
259
function commerce_product_ui_entity_info_alter(&$entity_info) {
260
  // Add a URI callback to the product entity.
261
  $entity_info['commerce_product']['uri callback'] = 'commerce_product_ui_product_uri';
262

    
263
  // Add callbacks and urls for administer translations.
264
  $entity_info['commerce_product']['translation']['entity_translation'] += array(
265
    'base path' => 'admin/commerce/products/%commerce_product',
266
  );
267

    
268
  // Expose the admin UI for product fields.
269
  foreach ($entity_info['commerce_product']['bundles'] as $type => &$bundle) {
270
    $bundle['admin'] = array(
271
      'path' => 'admin/commerce/products/types/' . strtr($type, '_', '-'),
272
      'access arguments' => array('administer product types'),
273
    );
274
  }
275
}
276

    
277
/**
278
 * Entity uri callback: points to the edit form of the given product if no other
279
 *   URI is specified.
280
 */
281
function commerce_product_ui_product_uri($product) {
282
  // First look for a return value in the default entity uri callback.
283
  $uri = commerce_product_uri($product);
284

    
285
  // If a value was found, return it now.
286
  if (!empty($uri)) {
287
    return $uri;
288
  }
289

    
290
  // Otherwise return an admin URI if the user has permission.
291
  if (commerce_product_access('update', $product)) {
292
    return array(
293
      'path' => 'admin/commerce/products/' . $product->product_id,
294
    );
295
  }
296

    
297
  return NULL;
298
}
299

    
300
/**
301
 * Implements hook_commerce_product_type_info().
302
 */
303
function commerce_product_ui_commerce_product_type_info() {
304
  return db_query('SELECT * FROM {commerce_product_type}')->fetchAllAssoc('type', PDO::FETCH_ASSOC);
305
}
306

    
307
/**
308
 * Returns an initialized product type array.
309
 */
310
function commerce_product_ui_product_type_new() {
311
  return array(
312
    'type' => '',
313
    'name' => '',
314
    'description' => '',
315
    'help' => '',
316
    'revision' => 1,
317
  );
318
}
319

    
320
/**
321
 * Saves a product type.
322
 *
323
 * This function will either insert a new product type if $product_type['is_new']
324
 * is set or attempt to update an existing product type if it is not. It does
325
 * not currently support changing the machine-readable name of the product type,
326
 * nor is this possible through the form supplied by the Product UI module.
327
 *
328
 * @param $product_type
329
 *   The product type array containing the basic properties as initialized in
330
 *     commerce_product_ui_product_type_new().
331
 * @param $configure
332
 *   Boolean indicating whether or not product type configuration should be
333
 *     performed in the event of a new product type being saved.
334
 * @param $skip_reset
335
 *   Boolean indicating whether or not this save should result in product types
336
 *     being reset and the menu being rebuilt; defaults to FALSE. This is useful
337
 *     when you intend to perform many saves at once, as menu rebuilding is very
338
 *     costly in terms of performance.
339
 *
340
 * @return
341
 *   The return value of the call to drupal_write_record() to save the product
342
 *     type, either FALSE on failure or SAVED_NEW or SAVED_UPDATED indicating
343
 *     the type of query performed to save the product type.
344
 */
345
function commerce_product_ui_product_type_save($product_type, $configure = TRUE, $skip_reset = FALSE) {
346
  $op = drupal_write_record('commerce_product_type', $product_type, empty($product_type['is_new']) ? 'type' : array());
347

    
348
  // If this is a new product type and the insert did not fail...
349
  if (!empty($product_type['is_new']) && $op !== FALSE) {
350
    // Notify the field API that a new bundle has been created.
351
    field_attach_create_bundle('commerce_product', $product_type['type']);
352

    
353
    // Add the default price field to the product type.
354
    if ($configure) {
355
      commerce_product_configure_product_type($product_type['type']);
356
    }
357

    
358
    // Notify other modules that a new product type has been created.
359
    module_invoke_all('commerce_product_type_insert', $product_type, $skip_reset);
360
  }
361
  elseif ($op !== FALSE) {
362
    // Notify other modules that an existing product type has been updated.
363
    module_invoke_all('commerce_product_type_update', $product_type, $skip_reset);
364
  }
365

    
366
  // Rebuild the menu to add this product type's menu items.
367
  if (!$skip_reset) {
368
    commerce_product_types_reset();
369
    variable_set('menu_rebuild_needed', TRUE);
370
  }
371

    
372
  return $op;
373
}
374

    
375
/**
376
 * Deletes a product type.
377
 *
378
 * @param $type
379
 *   The machine-readable name of the product type.
380
 * @param $skip_reset
381
 *   Boolean indicating whether or not this delete should result in product
382
 *     types being reset and the menu being rebuilt; defaults to FALSE. This is
383
 *     useful when you intend to perform many saves at once, as menu rebuilding
384
 *     is very costly in terms of performance.
385
 */
386
function commerce_product_ui_product_type_delete($type, $skip_reset = FALSE) {
387
  $product_type = commerce_product_type_load($type);
388

    
389
  db_delete('commerce_product_type')
390
    ->condition('type', $type)
391
    ->execute();
392

    
393
  // Rebuild the menu to get rid of this product type's menu items.
394
  if (!$skip_reset) {
395
    commerce_product_types_reset();
396
    variable_set('menu_rebuild_needed', TRUE);
397
  }
398

    
399
  // Notify the field API that this bundle has been destroyed.
400
  field_attach_delete_bundle('commerce_product', $type);
401

    
402
  // Notify other modules that this product type has been deleted.
403
  module_invoke_all('commerce_product_type_delete', $product_type, $skip_reset);
404
}
405

    
406
/**
407
 * Checks to see if a given product type already exists.
408
 *
409
 * @param $type
410
 *   The string to match against existing types.
411
 *
412
 * @return
413
 *   TRUE or FALSE indicating whether or not the product type exists.
414
 */
415
function commerce_product_ui_validate_product_type_unique($type) {
416
  // Look for a match of the type.
417
  if ($match_id = db_query('SELECT type FROM {commerce_product_type} WHERE type = :type', array(':type' => $type))->fetchField()) {
418
    return FALSE;
419
  }
420

    
421
  return TRUE;
422
}
423

    
424
/**
425
 * Implements hook_forms().
426
 */
427
function commerce_product_ui_forms($form_id, $args) {
428
  $forms = array();
429

    
430
  // Define a wrapper ID for the product add / edit form.
431
  $forms['commerce_product_ui_product_form'] = array(
432
    'callback' => 'commerce_product_product_form',
433
  );
434

    
435
  // Define a wrapper ID for the product delete confirmation form.
436
  $forms['commerce_product_ui_product_delete_form'] = array(
437
    'callback' => 'commerce_product_product_delete_form',
438
  );
439

    
440
  return $forms;
441
}
442

    
443
/**
444
 * Implements hook_form_FORM_ID_alter().
445
 *
446
 * The Product UI module instantiates the Product add/edit form at particular
447
 * paths in the Commerce IA. It uses its own form ID to do so and alters the
448
 * form here to add in appropriate redirection and an additional button.
449
 *
450
 * @see commerce_product_ui_product_form()
451
 */
452
function commerce_product_ui_form_commerce_product_ui_product_form_alter(&$form, &$form_state) {
453
  $product = $form_state['commerce_product'];
454

    
455
  // Add a submit handler to the save button to add a redirect.
456
  $form['actions']['submit']['#submit'][] = 'commerce_product_ui_product_form_submit';
457

    
458

    
459
  // Add the save and continue button for new products.
460
  if (empty($product->product_id)) {
461
    $form['actions']['save_continue'] = array(
462
      '#type' => 'submit',
463
      '#value' => t('Save and add another'),
464
      '#submit' => $form['actions']['submit']['#submit'],
465
      '#suffix' => l(t('Cancel'), 'admin/commerce/products'),
466
      '#weight' => 45,
467
    );
468
  }
469
  else {
470
    $form['actions']['submit']['#suffix'] = l(t('Cancel'), 'admin/commerce/products');
471
  }
472
}
473

    
474
/**
475
 * Submit callback for commerce_product_ui_product_form().
476
 *
477
 * @see commerce_product_ui_form_commerce_product_ui_product_form_alter()
478
 */
479
function commerce_product_ui_product_form_submit($form, &$form_state) {
480
  // Set the redirect based on the button clicked.
481
  $array_parents = $form_state['triggering_element']['#array_parents'];
482
  $submit_element = array_pop($array_parents);
483

    
484
  if ($submit_element == 'save_continue') {
485
    $form_state['redirect'] = 'admin/commerce/products/add/' . strtr($form_state['commerce_product']->type, array('_' => '-'));
486
  }
487
  elseif (arg(2) == 'products' && arg(3) == 'add') {
488
    $form_state['redirect'] = 'admin/commerce/products';
489
  }
490
}
491

    
492
/**
493
 * Implements hook_form_FORM_ID_alter().
494
 *
495
 * The Product UI module instantiates the Product delete form at a particular
496
 * path in the Commerce IA. It uses its own form ID to do so and alters the
497
 * form here to add in appropriate redirection.
498
 *
499
 * @see commerce_product_ui_product_delete_form()
500
 */
501
function commerce_product_ui_form_commerce_product_ui_product_delete_form_alter(&$form, &$form_state) {
502
  $form['actions']['cancel']['#href'] = 'admin/commerce/products';
503
  $form['#submit'][] = 'commerce_product_ui_product_delete_form_submit';
504
}
505

    
506
/**
507
 * Submit callback for commerce_product_ui_product_delete_form().
508
 *
509
 * @see commerce_product_ui_form_commerce_product_ui_product_delete_form_alter()
510
 */
511
function commerce_product_ui_product_delete_form_submit($form, &$form_state) {
512
  $form_state['redirect'] = 'admin/commerce/products';
513
}
514

    
515
/**
516
 * Implements hook_views_api().
517
 */
518
function commerce_product_ui_views_api() {
519
  return array(
520
    'api' => 3,
521
    'path' => drupal_get_path('module', 'commerce_product_ui') . '/includes/views',
522
  );
523
}
524

    
525
/**
526
 * Sets the breadcrumb for administrative product pages.
527
 *
528
 * @param $product_types
529
 *   TRUE or FALSE indicating whether or not the breadcrumb should include the
530
 *     product types administrative page.
531
 *
532
 * @deprecated since 7.x-1.4
533
 */
534
function commerce_product_ui_set_breadcrumb($product_types = FALSE) {
535
  // This function used to manually set a breadcrumb that is now properly
536
  // generated by Drupal itself.
537
}