Creating an artist entity (Part 2)

Public

Get raw version
php
  1. <?php
  2.  
  3. #artwork.module
  4.  
  5. /**
  6.  * Implements hook_entity_info().
  7.  */
  8. function artwork_entity_info() {
  9. $return['artwork'] = array(
  10. 'label' => t('Artwork'),
  11. 'controller class' => 'ArtworkController',
  12. 'base table' => 'artwork',
  13. 'revision table' => 'artwork_revision',
  14. 'uri callback' => 'artwork_uri',
  15. 'fieldable' => TRUE,
  16. 'entity keys' => array(
  17. 'id' => 'aid',
  18. 'revision' => 'vid',
  19. 'bundle' => 'type',
  20. 'label' => 'title',
  21. ),
  22. 'bundle keys' => array(
  23. 'bundle' => 'type',
  24. ),
  25. 'static cache' => TRUE,
  26. 'bundles' => array(),
  27. 'view modes' => array(
  28. 'full' => array(
  29. 'label' => t('Full content'),
  30. 'custom settings' => FALSE,
  31. ),
  32. 'teaser' => array(
  33. 'label' => t('Teaser'),
  34. 'custom settings' => FALSE,
  35. ),
  36. ),
  37. );
  38.  
  39. foreach (artwork_types() as $type => $info) {
  40. $return['artwork']['bundles'][$type] = array(
  41. 'label' => $info->name,
  42. 'admin' => array(
  43. 'path' => 'admin/structure/artworks/manage/%artwork_type',
  44. 'real path' => 'admin/structure/artworks/manage/' . str_replace('_', '-', $type),
  45. 'bundle argument' => 4,
  46. 'access arguments' => array('administer artworks'),
  47. ),
  48. );
  49. }
  50.  
  51. return $return;
  52. }
  53.  
  54. /**
  55.  * Entity uri callback.
  56.  */
  57. function artwork_uri($artwork) {
  58. return array(
  59. 'path' => 'artwork/' . $artwork->aid,
  60. );
  61. }
  62.  
  63. /**
  64.  * Implements hook_fied_extra_fields().
  65.  */
  66. function artwork_field_extra_fields() {
  67. $extra = array();
  68.  
  69. foreach (artwork_types() as $type) {
  70. $extra['artwork'][$type->type] = array(
  71. 'form' => array(
  72. 'title' => array(
  73. 'label' => t('Title'),
  74. 'description' => t('The name of the artwork'),
  75. 'weight' => -5,
  76. ),
  77. ),
  78. 'display' => array(
  79. 'title' => array(
  80. 'label' => t('Title'),
  81. 'description' => t('The name of the artwork'),
  82. 'weight' => -5,
  83. ),
  84. ),
  85. );
  86. }
  87.  
  88. return $extra;
  89. }
  90.  
  91. /**
  92.  * Implements hook_permission().
  93.  */
  94. function artwork_permission() {
  95. return array(
  96. 'administer artworks' => array(
  97. 'title' => t('Administer artworks'),
  98. ),
  99. 'create artworks' => array(
  100. 'title' => t('Create artworks'),
  101. ),
  102. 'update artworks' => array(
  103. 'title' => t('Update artworks'),
  104. ),
  105. 'view artworks' => array(
  106. 'title' => t('View artworks'),
  107. ),
  108. 'delete artworks' => array(
  109. 'title' => t('Delete artworks'),
  110. ),
  111. );
  112. }
  113.  
  114. /**
  115.  * Implements hook_menu().
  116.  */
  117. function artwork_menu() {
  118. $items['admin/structure/artworks'] = array(
  119. 'title' => 'Manage artworks',
  120. 'description' => 'Manage artworks.',
  121. 'page callback' => 'artwork_overview_types',
  122. 'access arguments' => array('administer artworks'),
  123. 'file' => 'artwork.admin.inc',
  124. );
  125. $items['admin/structure/artworks/manage/%artwork_type'] = array(
  126. 'title' => 'View artwork type',
  127. 'title callback' => 'artwork_type_page_title',
  128. 'title arguments' => array(4),
  129. 'page callback' => 'artwork_information',
  130. 'page arguments' => array(4),
  131. 'access arguments' => array('administer artworks'),
  132. 'file' => 'artwork.admin.inc',
  133. );
  134. $items['admin/structure/artworks/manage/%artwork_type/view'] = array(
  135. 'title' => 'View',
  136. 'type' => MENU_DEFAULT_LOCAL_TASK,
  137. );
  138.  
  139. $items['artwork/add'] = array(
  140. 'title' => 'Add new artwork',
  141. 'page callback' => 'artwork_add_page',
  142. 'access arguments' => array('create artworks'),
  143. 'weight' => 1,
  144. 'menu_name' => 'management',
  145. 'file' => 'artwork.pages.inc',
  146. );
  147. foreach (artwork_types() as $type) {
  148. $type_url_str = str_replace('_', '-', $type->type);
  149. $items['artwork/add/' . $type_url_str] = array(
  150. 'title' => $type->name,
  151. 'title callback' => 'check_plain',
  152. 'page callback' => 'artwork_add',
  153. 'page arguments' => array(2),
  154. 'access arguments' => array('create artwork'),
  155. 'description' => $type->description,
  156. 'file' => 'artwork.pages.inc',
  157. );
  158. }
  159. $items['artwork/%artwork'] = array(
  160. 'title callback' => 'artwork_page_title',
  161. 'title arguments' => array(1),
  162. 'page callback' => 'artwork_page_view',
  163. 'page arguments' => array(1),
  164. 'access arguments' => array('view artworks'),
  165. 'type' => MENU_CALLBACK,
  166. 'file' => 'artwork.pages.inc',
  167. );
  168. $items['artwork/%artwork/view'] = array(
  169. 'title' => 'View',
  170. 'type' => MENU_DEFAULT_LOCAL_TASK,
  171. 'weight' => -10,
  172. );
  173. $items['artwork/%artwork/edit'] = array(
  174. 'title' => 'Edit',
  175. 'page callback' => 'artwork_page_edit',
  176. 'page arguments' => array(1),
  177. 'access arguments' => array('update artworks'),
  178. 'weight' => 0,
  179. 'type' => MENU_LOCAL_TASK,
  180. 'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
  181. 'file' => 'artwork.pages.inc',
  182. );
  183. $items['artwork/%artwork/delete'] = array(
  184. 'title' => 'Delete',
  185. 'page callback' => 'drupal_get_form',
  186. 'page arguments' => array('artwork_delete_confirm', 1),
  187. 'access arguments' => array('delete artworks'),
  188. 'weight' => 1,
  189. 'type' => MENU_LOCAL_TASK,
  190. 'context' => MENU_CONTEXT_INLINE,
  191. 'file' => 'artwork.pages.inc',
  192. );
  193. $items['artwork/recent'] = array(
  194. 'title' => 'Recently added artworks',
  195. 'page callback' => 'artwork_page_list_recent',
  196. 'access arguments' => array('view artworks'),
  197. 'file' => 'artwork.pages.inc',
  198. );
  199.  
  200. return $items;
  201. }
  202.  
  203. /**
  204.  * Sets the page title based on the specified artwork.
  205.  *
  206.  * @param $artwork
  207.  * The artwork object.
  208.  */
  209. function artwork_page_title($artwork) {
  210. return $artwork->title;
  211. }
  212.  
  213. /**
  214.  * Implements hook_forms().
  215.  *
  216.  * All artwork forms share the same form handler.
  217.  */
  218. function artwork_forms() {
  219. $forms = array();
  220. if ($types = artwork_types()) {
  221. foreach (array_keys($types) as $type) {
  222. $forms[$type . '_artwork_form']['callback'] = 'artwork_form';
  223. }
  224. }
  225. return $forms;
  226. }
  227.  
  228. /**
  229.  * Get a list of all artwork types available.
  230.  *
  231.  * Usually this would be more full-featured.
  232.  *
  233.  * @return array
  234.  * An array of artwork type objects. Note that the "type" key matches what
  235.  * was defined as the main key in hook_entity_info().
  236.  */
  237. function artwork_types() {
  238. $types = &drupal_static(__FUNCTION__);
  239.  
  240. if (empty($types)) {
  241. $types['painting'] = (object)array(
  242. 'type' => 'painting',
  243. 'name' => t('Painting'),
  244. 'description' => t('A picture made with paint.')
  245. );
  246. $types['sculpture'] = (object)array(
  247. 'type' => 'sculpture',
  248. 'name' => t('Sculpture'),
  249. 'description' => t('A carving made out of stone or wood.')
  250. );
  251. $types['ancient_book'] = (object)array(
  252. 'type' => 'ancient_book',
  253. 'name' => t('Ancient book'),
  254. 'description' => t('A very old tome of knowledge.')
  255. );
  256. }
  257. return $types;
  258. }
  259.  
  260. /**
  261.  * Menu title callback.
  262.  *
  263.  * @param $type
  264.  * The artwork type.
  265.  * @return string
  266.  * The human-friendly name of the artwork type.
  267.  */
  268. function artwork_type_page_title($type) {
  269. return t('Manage @type', array('@type' => $type->name));
  270. }
  271.  
  272. /**
  273.  * Get an individual artwork type definition object.
  274.  *
  275.  * @param $type
  276.  * The key of the artwork type we want.
  277.  * @return object
  278.  * The specified artwork type.
  279.  */
  280. function artwork_type_load($type) {
  281. $types = artwork_types();
  282. $type = str_replace('-', '_', $type);
  283. return isset($types[$type]) ? $types[$type] : FALSE;
  284. }
  285.  
  286. /**
  287.  * Load artwork entities from the database.
  288.  *
  289.  * This function should be used whenever you need to load more than one artwork
  290.  * from the database. Artworks are loaded into memory and will not require
  291.  * database access if loaded again during the same page request.
  292.  *
  293.  * @see entity_load()
  294.  *
  295.  * @param $aids
  296.  * An array of artwork IDs.
  297.  * @param $conditions
  298.  * An array of conditions on the {artwork} table in the form 'field' => $value.
  299.  * @param $reset
  300.  * Whether to reset the internal entity_load cache.
  301.  *
  302.  * @return
  303.  * An array of node objects indexed by nid.
  304.  */
  305. function artwork_load_multiple($aids = array(), $conditions = array(), $reset = FALSE) {
  306. return entity_load('artwork', $aids, $conditions, $reset);
  307. }
  308.  
  309. /**
  310.  * Load an artwork object from the database.
  311.  *
  312.  * @param $aid
  313.  * The artwork ID.
  314.  * @param $vid
  315.  * The revision ID.
  316.  * @param $reset
  317.  * Whether to reset the artwork_load_multiple cache.
  318.  *
  319.  * @return
  320.  * A fully-populated node object.
  321.  */
  322. function artwork_load($aid = NULL, $vid = NULL, $reset = FALSE) {
  323. $aids = (isset($aid) ? array($aid) : array());
  324. $conditions = (isset($vid) ? array('vid' => $vid) : array());
  325. $artwork = artwork_load_multiple($aids, $conditions, $reset);
  326. return $artwork ? reset($artwork) : FALSE;
  327. }
  328.  
  329. /**
  330.  * Save an artwork.
  331.  *
  332.  * @param $artwork
  333.  * The artwork to be saved.
  334.  * @return
  335.  * The saved artwork, now with an aid if necessary.
  336.  */
  337. function artwork_save($artwork) {
  338. return entity_get_controller('artwork')->save($artwork);
  339. }
  340.  
  341. /**
  342.  * Returns an initialized artwork object.
  343.  *
  344.  * @param $type
  345.  * The machine-readable type of the artwork.
  346.  *
  347.  * @return
  348.  * An artwork object with all default fields initialized.
  349.  */
  350. function artwork_new($type = '') {
  351. return entity_get_controller('artwork')->create($type);
  352. }
  353.  
  354.  
  355. /**
  356.  * Deletes an artwork by ID.
  357.  *
  358.  * @param $aid
  359.  * The ID of the product to delete.
  360.  *
  361.  * @return
  362.  * TRUE on success, FALSE otherwise.
  363.  */
  364. function artwork_delete($aid) {
  365. return artwork_delete_multiple(array($aid));
  366. }
  367.  
  368. /**
  369.  * Deletes multiple artworks by ID.
  370.  *
  371.  * @param $aids
  372.  * An array of artwork IDs to delete.
  373.  *
  374.  * @return
  375.  * TRUE on success, FALSE otherwise.
  376.  */
  377. function artwork_delete_multiple($aids) {
  378. return entity_get_controller('artwork')->delete($aids);
  379. }
  380.  
  381.  
  382.  
  383. #artwork.pages.inc
  384.  
  385. <?php
  386.  
  387. /**
  388.  * Menu callback; Show list of artwork types we can add.
  389.  */
  390. function artwork_add_page() {
  391. $item = menu_get_item();
  392. $links = system_admin_menu_block($item);
  393.  
  394. foreach ($links as $link) {
  395. $items[] = l($link['title'], $link['href'], $item['localized_options'])
  396. . ': ' . filter_xss_admin($link['description']);
  397. }
  398.  
  399. return theme('item_list', array('items' => $items));
  400. }
  401.  
  402. /**
  403.  * Present an artwork submission form.
  404.  */
  405. function artwork_add($type) {
  406. global $user;
  407.  
  408. $types = artwork_types();
  409. $type = isset($type) ? str_replace('-', '_', $type) : NULL;
  410. if (empty($types[$type])) {
  411. return MENU_NOT_FOUND;
  412. }
  413.  
  414. $artwork = entity_get_controller('artwork')->create($type);
  415.  
  416. drupal_set_title(t('Create @name', array('@name' => $types[$type]->name)), PASS_THROUGH);
  417. return drupal_get_form($type . '_artwork_form', $artwork);
  418. }
  419.  
  420. /**
  421.  * Menu callback; presents the artwork editing form, or redirects to delete confirmation.
  422.  *
  423.  * @param $artwork
  424.  * The artwork object to edit.
  425.  */
  426. function artwork_page_edit($artwork) {
  427. $types = artwork_types();
  428. drupal_set_title(t('<em>Edit @type</em> @title', array('@type' => $types[$artwork->type]->name, '@title' => $artwork->title)), PASS_THROUGH);
  429.  
  430. return drupal_get_form($artwork->type . '_artwork_form', $artwork);
  431. }
  432.  
  433. /**
  434.  * Form builder; Displays the artwork add/edit form.
  435.  *
  436.  * @param $form
  437.  * @param $form_state
  438.  * @param $artwork
  439.  * The artwork object to edit, which may be brand new.
  440.  */
  441. function artwork_form($form, &$form_state, $artwork) {
  442.  
  443. // Set the id and identify this as an artwork edit form.
  444. $form['#id'] = 'artwork-form';
  445.  
  446. // Save the artwork for later, in case we need it.
  447. $form['#artwork'] = $artwork;
  448. $form_state['artwork'] = $artwork;
  449.  
  450. // Common fields. We don't have many.
  451. $form['title'] = array(
  452. '#type' => 'textfield',
  453. '#title' => t('Title'),
  454. '#default_value' => $artwork->title,
  455. '#weight' => -5,
  456. '#required' => TRUE,
  457. );
  458.  
  459. $form['revision'] = array(
  460. '#access' => user_access('administer artworks'),
  461. '#type' => 'checkbox',
  462. '#title' => t('Create new revision'),
  463. '#default_value' => 0,
  464. );
  465.  
  466. // Add the buttons.
  467. $form['buttons'] = array();
  468. $form['buttons']['#weight'] = 100;
  469. $form['buttons']['submit'] = array(
  470. '#type' => 'submit',
  471. '#value' => t('Save'),
  472. '#weight' => 5,
  473. '#submit' => array('artwork_form_submit'),
  474. );
  475. if (!empty($artwork->aid)) {
  476. $form['buttons']['delete'] = array(
  477. '#access' => user_access('delete artworks'),
  478. '#type' => 'submit',
  479. '#value' => t('Delete'),
  480. '#weight' => 15,
  481. '#submit' => array('artwork_form_delete_submit'),
  482. );
  483. }
  484.  
  485. $form['#validate'][] = 'artwork_form_validate';
  486.  
  487. field_attach_form('artwork', $artwork, $form, $form_state);
  488.  
  489. return $form;
  490. }
  491.  
  492. function artwork_form_validate($form, &$form_state) {
  493. $artwork = $form_state['artwork'];
  494.  
  495. // Field validation.
  496. field_attach_form_validate('artwork', $artwork, $form, $form_state);
  497. }
  498.  
  499.  
  500. function artwork_form_submit($form, &$form_state) {
  501. global $user;
  502.  
  503. $artwork = &$form_state['artwork'];
  504.  
  505. // Set the artwork's uid if it's being created at this time.
  506. if (empty($artwork->uid)) {
  507. $artwork->uid = $user->uid;
  508. }
  509.  
  510. $artwork->title = $form_state['values']['title'];
  511. $artwork->revision = $form_state['values']['revision'];
  512.  
  513. // Notify field widgets.
  514. field_attach_submit('artwork', $artwork, $form, $form_state);
  515.  
  516. // Save the artwork.
  517. artwork_save($artwork);
  518.  
  519. // Notify the user.
  520. drupal_set_message(t('Artwork saved.'));
  521.  
  522. $form_state['redirect'] = 'artwork/' . $artwork->aid;
  523. }
  524.  
  525.  
  526. function artwork_form_delete_submit($form, &$form_state) {
  527. $destination = array();
  528. if (isset($_GET['destination'])) {
  529. $destination = drupal_get_destination();
  530. unset($_GET['destination']);
  531. }
  532. $artwork = $form['#artwork'];
  533. $form_state['redirect'] = array('artwork/' . $artwork->aid . '/delete', array('query' => $destination));
  534. }
  535.  
  536. /**
  537.  * Displays an artwork.
  538.  *
  539.  * @param $artwork
  540.  * The artwork object to display.
  541.  * @param $view_mode
  542.  * The view mode we want to display.
  543.  */
  544. function artwork_page_view($artwork, $view_mode = 'full') {
  545. // Remove previously built content, if exists.
  546. $artwork->content = array();
  547.  
  548. if ($view_mode == 'teaser') {
  549. $artwork->content['title'] = array(
  550. '#markup' => filter_xss($artwork->title),
  551. '#weight' => -5,
  552. );
  553. }
  554.  
  555. // Build fields content.
  556. field_attach_prepare_view('artwork', array($artwork->aid => $artwork), $view_mode);
  557. entity_prepare_view('artwork', array($artwork->aid => $artwork));
  558. $artwork->content += field_attach_view('artwork', $artwork, $view_mode);
  559.  
  560. return $artwork->content;
  561. }
  562.  
  563. /**
  564.  * Form bulder; Asks for confirmation of artwork deletion.
  565.  */
  566. function artwork_delete_confirm($form, &$form_state, $artwork) {
  567. $form['#artwork'] = $artwork;
  568. // Always provide entity id in the same form key as in the entity edit form.
  569. $form['aid'] = array('#type' => 'value', '#value' => $artwork->aid);
  570. return confirm_form($form,
  571. t('Are you sure you want to delete %title?', array('%title' => $artwork->title)),
  572. 'artwork/' . $artwork->aid,
  573. t('This action cannot be undone.'),
  574. t('Delete'),
  575. t('Cancel')
  576. );
  577. }
  578.  
  579. /**
  580.  * Executes artwork deletion.
  581.  */
  582. function artwork_delete_confirm_submit($form, &$form_state) {
  583. if ($form_state['values']['confirm']) {
  584. $artwork = artwork_load($form_state['values']['aid']);
  585. artwork_delete($form_state['values']['aid']);
  586. watchdog('artwork', '@type: deleted %title.', array('@type' => $artwork->type, '%title' => $artwork->title));
  587.  
  588. $types = artwork_types();
  589. drupal_set_message(t('@type %title has been deleted.', array('@type' => $types[$artwork->type]->name, '%title' => $artwork->title)));
  590. }
  591.  
  592. $form_state['redirect'] = '<front>';
  593. }
  594.  
  595. /**
  596.  * Menu callback; Displays a listing of recent artworks.
  597.  *
  598.  * This doesn't really work yet because our presentation code doesn't show
  599.  * the title.
  600.  */
  601. function artwork_page_list_recent() {
  602. $content = array();
  603.  
  604. $query = new EntityFieldQuery();
  605. $query
  606. ->entityCondition('entity_type', 'artwork')
  607. ->propertyOrderBy('created', 'DESC')
  608. ->fieldCondition('field_artist', 'value', 'Da Vinci', 'CONTAINS', 0)
  609. ->range(0, 5);
  610. $result = $query->execute();
  611.  
  612. $artworks = artwork_load_multiple(array_keys($result['artwork']));
  613. foreach ($artworks as $artwork) {
  614. $content[$artwork->aid] = artwork_page_view($artwork, 'teaser');
  615. }
  616.  
  617. return $content;
  618. }
  619.  
  620.  
  621. #artwork.admin.inc
  622.  
  623. <?php
  624.  
  625. /**
  626.  * Menu callback; List all artwork types available.
  627.  */
  628. function artwork_overview_types() {
  629. foreach (artwork_types() as $type => $info) {
  630. $type_url_str = str_replace('_', '-', $type);
  631. $label = t('View @type', array('@type' => $info->name));
  632. $items[] = l($label, 'admin/structure/artworks/manage/' . $type_url_str);
  633. }
  634.  
  635. return theme('item_list', array('items' => $items));
  636. }
  637.  
  638. /**
  639.  * Menu callback; Artwork information page.
  640.  *
  641.  * @param object $artwork_type
  642.  */
  643. function artwork_information($artwork_type) {
  644. return $artwork_type->name . ': ' . $artwork_type->description;
  645. }