Fixed #1831784: Use Payment 7.x-1.1 prefixed line item callback.
[project/payment_webform.git] / payment_webform.module
1 <?php
2
3 /**
4 * @file
5 * Hook implementations and shared functions.
6 */
7
8 /**
9 * Implements hook_menu().
10 */
11 function payment_webform_menu() {
12 $item['payment_webform/finish'] = array(
13 'title' => 'Payment for Webform finished',
14 'page callback' => 'payment_webform_page_finish',
15 'access callback' => 'payment_webform_page_finish_access',
16 'type' => MENU_CALLBACK,
17 );
18 $item['payment_webform/pay/%node/%'] = array(
19 'title' => 'Add a payment reference',
20 'title callback' => 'node_page_title',
21 'title arguments' => array(2),
22 'page callback' => 'payment_webform_page_payment',
23 'page arguments' => array(2, 3),
24 'access callback' => 'payment_webform_page_payment_access',
25 'access arguments' => array(2, 3),
26 );
27
28 return $item;
29 }
30
31 /**
32 * Implements hook_page_alter().
33 */
34 function payment_webform_page_alter(&$page) {
35 if (arg(0) == 'payment_webform') {
36 $skip_regions = array_diff(element_children($page), array('content'));
37 foreach ($skip_regions as $skip_region) {
38 $page[$skip_region]['#access'] = FALSE;
39 }
40 }
41 }
42
43 /**
44 * Implements hook_payment_line_item_info().
45 */
46 function payment_webform_payment_line_item_info() {
47 return array(
48 new PaymentLineItemInfo(array(
49 'callback' => 'payment_line_item_get_prefixed',
50 'name' => 'payment_webform',
51 'title' => t('All Payment for Webform items'),
52 )),
53 );
54 }
55
56 /**
57 * Implements hook_webform_select_options_info().
58 */
59 function payment_webform_webform_select_options_info() {
60 $options['payment_method'] = array(
61 'title' => t('Payment methods'),
62 'options callback' => 'payment_method_options',
63 );
64 $options['payment_status'] = array(
65 'title' => t('Payment statuses'),
66 'options callback' => 'payment_status_options',
67 );
68
69 return $options;
70 }
71
72 /**
73 * Implements hook_webform_component_info().
74 */
75 function payment_webform_webform_component_info() {
76 $components['payment_webform'] = array(
77 'label' => t('Payment reference'),
78 'description' => t('Basic textfield type.'),
79 'features' => array(
80 'default_value' => FALSE,
81 'required' => TRUE,
82 ),
83 'file' => 'payment_webform.webform.inc',
84 );
85
86 return $components;
87 }
88
89 /**
90 * Implements hook_webform_component_delete().
91 */
92 function payment_webform_webform_component_delete($component) {
93 payment_webform_delete_by_cid($component['cid']);
94 }
95
96 /**
97 * Implements hook_ENTITY_TYPE_ACTION().
98 */
99 function payment_webform_payment_delete($entity) {
100 payment_webform_delete_by_pid($entity->pid);
101 }
102
103 /**
104 * Load the Webform NID for a Payment.
105 *
106 * @param integer $pid
107 *
108 * @return integer|false
109 */
110 function payment_webform_load_nid($pid) {
111 return db_query("SELECT nid FROM {webform_component} wc LEFT JOIN {payment_webform} pw ON wc.cid = pw.cid WHERE pw.pid = :pid", array(
112 ':pid' => $pid,
113 ))->fetchField();
114 }
115
116 /**
117 * Loads a PID of a Payment available for referencing.
118 */
119 function payment_webform_load($cid, $uid) {
120 $query = db_select('payment_webform', 'pw');
121 $query->addJoin('INNER', 'payment', 'p', 'p.pid = pw.pid');
122 $query->addJoin('INNER', 'payment_status_item', 'psi', 'p.psiid_last = psi.psiid');
123 $query->fields('pw', array('pid'))
124 ->condition('cid', $cid)
125 ->condition('status', array_merge(payment_status_info(PAYMENT_STATUS_SUCCESS)->descendants(), array(PAYMENT_STATUS_SUCCESS)))
126 ->condition('uid', $uid)
127 // Order by pid ASC, so we use the oldest payment first.
128 ->orderBy('pid')
129 ->range(0, 1);
130
131 return $query->execute()->fetchField();
132 }
133
134 /**
135 * Insert a Payment available for referencing through a Webform component.
136 *
137 * @param integer $cid
138 * The CID of the component the reference is available for.
139 * @param integer $pid
140 * The PID of the available payment.
141 *
142 * @return integer
143 * SAVED_NEW
144 */
145 function payment_webform_insert($cid, $pid) {
146 $data = array(
147 'cid' => $cid,
148 'pid' => $pid,
149 );
150
151 return drupal_write_record('payment_webform', $data);
152 }
153
154 /**
155 * Delete a Payment from the queue by PID.
156 *
157 * @param integer $pid
158 */
159 function payment_webform_delete_by_pid($pid) {
160 db_delete('payment_webform')
161 ->condition('pid', $pid)
162 ->execute();
163 }
164
165 /**
166 * Delete a Payment from the queue by CID.
167 *
168 * @param integer $cid
169 */
170 function payment_webform_delete_by_cid($cid) {
171 db_delete('payment_webform')
172 ->condition('cid', $cid)
173 ->execute();
174 }
175
176 /**
177 * Check if a user has access to the redirect page.
178 *
179 * @param stdClass $node
180 * The node to which the webform component belongs.
181 * @param integer $cid
182 * The ID of the webform component to check access to.
183 * @param stdClass|null $account
184 * The account whose access to check. Use NULL to default to the currently
185 * logged in user.
186 *
187 * @return boolean
188 */
189 function payment_webform_page_payment_access($node, $cid, $account = NULL) {
190 global $user;
191
192 if (!$account) {
193 $account = $user;
194 }
195
196 return node_access('view', $node, $account)
197 && isset($node->webform['components'][$cid])
198 && !payment_webform_load($cid, $account->uid);
199 }
200
201 /**
202 * Return a payment page for a field instance.
203 *
204 * @param stdClass $node
205 * @param integer $cid
206 *
207 * @return array
208 * A Drupal build array.
209 */
210 function payment_webform_page_payment($node, $cid) {
211 $component = $node->webform['components'][$cid];
212 $payment = new Payment(array(
213 'context' => 'payment_webform_' . $node->nid . '_' . $cid,
214 'currency_code' => $component['extra']['payment_currency_code'],
215 'description' => $component['extra']['payment_description'],
216 'finish_callback' => 'payment_webform_payment_finish',
217 ));
218 foreach ($component['extra']['payment_line_items'] as $line_item) {
219 $line_item->name = 'payment_webform_' . $line_item->name;
220 $payment->setLineItem($line_item);
221 }
222
223 return drupal_get_form('payment_form_standalone', $payment);
224 }
225
226 /**
227 * Implements Payment::finish_callback.
228 */
229 function payment_webform_payment_finish(Payment $payment) {
230 payment_webform_insert($payment->context_data['cid'], $payment->pid);
231 $_SESSION['payment_webform_pid'] = $payment->pid;
232 drupal_goto('payment_webform/finish');
233 }
234
235 /**
236 * Menu page callback to call after a payment reference payment has finished.
237 *
238 * @return integer|array
239 */
240 function payment_webform_page_finish() {
241 $pid = $_SESSION['payment_webform_pid'];
242 unset($_SESSION['payment_webform_pid']);
243
244 $payment = entity_load_single('payment', $pid);
245 $node = node_load(payment_webform_load_nid($pid));
246 drupal_set_title(node_page_title($node));
247 return array(
248 '#type' => 'markup',
249 '#markup' => t('Your payment is %status. You can now <span class="paymentreference-window-close">close this window</span>.', array(
250 '%status' => payment_status_info($payment->getStatus()->status, TRUE)->title,
251 )),
252 '#attached' => array(
253 'js' => array(drupal_get_path('module', 'paymentreference') . '/js/paymentreference.js'),
254 ),
255 );
256 }
257
258 /**
259 * Check if a user has access to the finish page.
260 *
261 * @return boolean
262 */
263 function payment_webform_page_finish_access() {
264 return isset($_SESSION['payment_webform_pid']) && payment_webform_load_nid($_SESSION['payment_webform_pid']);
265 }