uc_roles.module 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296
  1. <?php
  2. /**
  3. * @file
  4. * Grants roles upon accepted payment of products.
  5. *
  6. * The uc_roles module will grant specified roles upon purchase of specified
  7. * products. Granted roles can be set to have a expiration date. Users can also
  8. * be notified of the roles they are granted and when the roles will
  9. * expire/need to be renewed/etc.
  10. */
  11. /**
  12. * Implements hook_help().
  13. */
  14. function uc_roles_help($path, $arg) {
  15. if ($path == 'node/%/edit/features/%/%' && $arg[4] == 'role') {
  16. return '<p>' . t('Add roles through this page and then use the <a href="!url">Rules interface</a> to limit which orders they are applied to. Most important is the order status on which role granting will be triggered.', array('!url' => url('admin/config/workflow/rules/reaction'))) . '</p>';
  17. }
  18. switch ($path) {
  19. case 'admin/people/expiration':
  20. return '<p>' . t('Ubercart grants certain roles to customers when they purchase products with a role assignment feature. These can be permanent or temporary roles. Here you can view and edit when temporary roles are set to expire.') . '</p>';
  21. }
  22. }
  23. /**
  24. * Implements hook_cron().
  25. */
  26. function uc_roles_cron() {
  27. $reminder_granularity = variable_get('uc_roles_reminder_granularity', 'never');
  28. $reminder_qty = variable_get('uc_roles_reminder_length', NULL);
  29. $query = db_select('uc_roles_expirations', 'e')
  30. ->fields('e');
  31. $condition = db_or()
  32. ->condition('e.expiration', REQUEST_TIME, '<=');
  33. if ($reminder_granularity != 'never') {
  34. $condition->condition(db_and()
  35. ->isNull('e.notified')
  36. ->condition('e.expiration', _uc_roles_get_expiration($reminder_qty, $reminder_granularity, REQUEST_TIME), '<=')
  37. );
  38. }
  39. $query->condition($condition);
  40. $result = $query->execute();
  41. foreach ($result as $expiration) {
  42. $account = user_load($expiration->uid);
  43. // Cleanup if user or role was deleted already.
  44. if (!$account || !in_array($expiration->rid, array_keys($account->roles))) {
  45. uc_roles_delete($expiration, $expiration->rid, TRUE);
  46. }
  47. // Role expired.
  48. elseif ($expiration->expiration <= REQUEST_TIME) {
  49. rules_invoke_event('uc_roles_notify_revoke', $account, $expiration);
  50. uc_roles_revoke($account, $expiration->rid);
  51. }
  52. // Remind the user about an upcoming expiration.
  53. elseif ($reminder_granularity != 'never') {
  54. rules_invoke_event('uc_roles_notify_reminder', $account, $expiration);
  55. db_update('uc_roles_expirations')
  56. ->fields(array('notified' => 1))
  57. ->condition('uid', $account->uid)
  58. ->condition('rid', $expiration->rid)
  59. ->execute();
  60. }
  61. }
  62. }
  63. /**
  64. * Implements hook_menu().
  65. */
  66. function uc_roles_menu() {
  67. $items = array();
  68. $items['admin/people/expiration'] = array(
  69. 'title' => 'Role expiration',
  70. 'description' => 'Edit and view role expirations set by Ubercart',
  71. 'page callback' => 'drupal_get_form',
  72. 'page arguments' => array('uc_roles_expiration'),
  73. 'access arguments' => array('administer users'),
  74. 'type' => MENU_LOCAL_TASK,
  75. 'file' => 'uc_roles.admin.inc',
  76. );
  77. $items['admin/people/expiration/delete/%user/%'] = array(
  78. 'title' => 'Delete role expiration',
  79. 'description' => 'Delete a specified role expiration',
  80. 'page callback' => 'drupal_get_form',
  81. 'page arguments' => array('uc_roles_deletion_form', 4, 5),
  82. 'access arguments' => array('administer users'),
  83. 'type' => MENU_CALLBACK,
  84. 'file' => 'uc_roles.admin.inc',
  85. );
  86. return $items;
  87. }
  88. /**
  89. * Implements hook_permission().
  90. */
  91. function uc_roles_permission() {
  92. return array(
  93. 'view all role expirations' => array(
  94. 'title' => t('View all role expirations'),
  95. )
  96. );
  97. }
  98. /**
  99. * Implements hook_theme().
  100. */
  101. function uc_roles_theme() {
  102. return array(
  103. 'uc_roles_expiration' => array(
  104. 'render element' => 'form',
  105. 'file' => 'uc_roles.admin.inc',
  106. ),
  107. 'uc_roles_user_expiration' => array(
  108. 'render element' => 'form',
  109. 'file' => 'uc_roles.theme.inc',
  110. ),
  111. 'uc_roles_user_new' => array(
  112. 'render element' => 'form',
  113. 'file' => 'uc_roles.theme.inc',
  114. ),
  115. );
  116. }
  117. /**
  118. * Implements hook_form_user_profile_form_alter().
  119. */
  120. function uc_roles_form_user_profile_form_alter(&$form, &$form_state) {
  121. $account = $form_state['build_info']['args'][0];
  122. if (isset($form_state['build_info']['args'][1])) {
  123. $category = $form_state['build_info']['args'][1];
  124. }
  125. else {
  126. // user_profile_form() has a default value for $category.
  127. $category = 'account';
  128. }
  129. if (!user_access('administer users') || $category != 'account') {
  130. return;
  131. }
  132. $role_choices = _uc_roles_get_choices(array_keys($account->roles));
  133. $polarity_widget = array(
  134. '#type' => 'select',
  135. '#options' => array(
  136. 'add' => '+',
  137. 'remove' => '-',
  138. ),
  139. );
  140. $quantity_widget = array(
  141. '#type' => 'textfield',
  142. '#size' => 4,
  143. '#maxlength' => 4
  144. );
  145. $granularity_widget = array(
  146. '#type' => 'select',
  147. '#options' => array(
  148. 'day' => t('day(s)'),
  149. 'week' => t('week(s)'),
  150. 'month' => t('month(s)'),
  151. 'year' => t('year(s)'),
  152. ),
  153. );
  154. $form['uc_roles'] = array(
  155. '#type' => 'fieldset',
  156. '#title' => t('Ubercart roles'),
  157. '#collapsible' => TRUE,
  158. '#collapsed' => TRUE,
  159. '#weight' => 10,
  160. '#theme' => 'uc_roles_user_new',
  161. );
  162. $form['uc_roles']['expirations'] = array(
  163. '#type' => 'fieldset',
  164. '#title' => t('Pending expirations'),
  165. '#collapsible' => FALSE,
  166. '#weight' => 0,
  167. '#theme' => 'uc_roles_user_expiration',
  168. );
  169. $form['uc_roles']['expirations']['table']['#tree'] = TRUE;
  170. // Create the expirations table.
  171. $expirations = db_query("SELECT * FROM {uc_roles_expirations} WHERE uid = :uid", array(':uid' => $account->uid));
  172. foreach ($expirations as $expiration) {
  173. $form['uc_roles']['expirations']['table'][$expiration->rid] = array(
  174. 'name' => array(
  175. '#type' => 'value',
  176. '#value' => _uc_roles_get_name($expiration->rid),
  177. ),
  178. 'remove' => array(
  179. '#type' => 'checkbox',
  180. ),
  181. 'expiration' => array(
  182. '#type' => 'value',
  183. '#value' => $expiration->expiration,
  184. ),
  185. 'polarity' => $polarity_widget,
  186. 'qty' => $quantity_widget,
  187. 'granularity' => $granularity_widget,
  188. );
  189. }
  190. // Option to allow temporary roles.
  191. if (!empty($role_choices)) {
  192. $form['uc_roles']['new_role'] = array(
  193. '#type' => 'checkbox',
  194. '#title' => t('Add role'),
  195. );
  196. $form['uc_roles']['new_role_add'] = array(
  197. '#type' => 'select',
  198. '#default_value' => variable_get('uc_roles_default_role', NULL),
  199. '#options' => $role_choices,
  200. );
  201. $form['uc_roles']['new_role_add_for'] = array(
  202. '#markup' => ' ' . t('for') . ' ',
  203. );
  204. $form['uc_roles']['new_role_add_qty'] = $quantity_widget;
  205. $form['uc_roles']['new_role_add_granularity'] = $granularity_widget;
  206. if (($default_granularity = variable_get('uc_roles_default_granularity', 'never')) != 'never') {
  207. $form['uc_roles']['new_role_add_qty'] = $form['uc_roles']['new_role_add_qty'] + array('#default_value' => variable_get('uc_roles_default_length', NULL));
  208. $form['uc_roles']['new_role_add_granularity'] = $form['uc_roles']['new_role_add_granularity'] + array('#default_value' => $default_granularity);
  209. }
  210. }
  211. $form['#validate'][] = 'uc_roles_user_validate';
  212. return $form;
  213. }
  214. /**
  215. * User profile form validate handler.
  216. *
  217. * @see uc_roles_form_user_profile_form_alter()
  218. */
  219. function uc_roles_user_validate($form, &$form_state) {
  220. $edit = $form_state['values'];
  221. $account = $form_state['build_info']['args'][0];
  222. if (isset($form_state['build_info']['args'][1])) {
  223. $category = $form_state['build_info']['args'][1];
  224. }
  225. else {
  226. // user_profile_form() has a default value for $category.
  227. $category = 'account';
  228. }
  229. // Validate the amount of time for the expiration.
  230. if (!empty($edit['new_role']) && $category == 'account') {
  231. if (intval($edit['new_role_add_qty']) < 1) {
  232. form_set_error('new_role_add_qty', t('The expiration length must be a positive integer'));
  233. }
  234. }
  235. // Validate adjusted expirations.
  236. if (isset($edit['table'])) {
  237. foreach ((array) $edit['table'] as $rid => $value) {
  238. // We don't validate if nothing was actually selected, the role, or the
  239. // expiration is removed.
  240. if ($value['qty'] == 0 || $value['remove'] == 1 || !$edit['roles'][$rid]) {
  241. continue;
  242. }
  243. $qty = $value['qty'];
  244. $qty *= $value['polarity'] == 'add' ? 1 : -1;
  245. $new_expiration = _uc_roles_get_expiration($qty, $value['granularity'], $value['expiration']);
  246. if (REQUEST_TIME > $new_expiration) {
  247. form_set_error('qty', t("The new expiration date, %date, has already occurred.", array('%date' => format_date($new_expiration, 'short'))));
  248. }
  249. }
  250. }
  251. }
  252. /**
  253. * Implements hook_user_cancel().
  254. */
  255. function uc_roles_user_cancel($edit, $account, $method) {
  256. uc_roles_delete($account);
  257. }
  258. /**
  259. * Implements hook_user_presave().
  260. */
  261. function uc_roles_user_presave(&$edit, $account, $category) {
  262. if (!user_access('administer users') || $category != 'account') {
  263. return;
  264. }
  265. // Grant a new role if a new temporary role is added.
  266. if (isset($edit['new_role']) && $edit['new_role'] && $category == 'account') {
  267. // Save our role info, but don't save the user; user.module will do that.
  268. uc_roles_grant($account, $edit['new_role_add'], _uc_roles_get_expiration($edit['new_role_add_qty'], $edit['new_role_add_granularity']), FALSE);
  269. // Push in values so user.module will save in the roles.
  270. $edit['roles'][$edit['new_role_add']] = _uc_roles_get_name($edit['new_role_add']);
  271. // Reset the new role form.
  272. $edit['new_role'] = $edit['new_role_add'] = $edit['new_role_add_qty'] = $edit['new_role_add_granularity'] = NULL;
  273. }
  274. // Check if any temporary role actions were taken.
  275. if (isset($edit['table'])) {
  276. foreach ((array) $edit['table'] as $rid => $value) {
  277. // Remove this expiration.
  278. if ($value['remove']) {
  279. uc_roles_delete($account, $rid);
  280. }
  281. // Adjust it.
  282. else {
  283. if ($value['qty'] && $edit['roles'][$rid]) {
  284. $qty = $value['qty'];
  285. $qty *= $value['polarity'] == 'add' ? 1 : -1;
  286. uc_roles_renew($account, $rid, _uc_roles_get_expiration($qty, $value['granularity'], $value['expiration']));
  287. }
  288. }
  289. }
  290. }
  291. // If a user's role is removed using Drupal, then so is any expiration data.
  292. if (isset($edit['roles']) && is_array($edit['roles']) && isset($account->roles)) {
  293. $allowed_uc_roles = _uc_roles_get_choices();
  294. foreach ($account->roles as $rid => $role) {
  295. if (isset($allowed_uc_roles[$rid]) && !$edit['roles'][$rid]) {
  296. uc_roles_delete($account, $rid);
  297. }
  298. }
  299. }
  300. }
  301. /**
  302. * Implements hook_user_view().
  303. *
  304. * Displays role expirations on the user account screen.
  305. */
  306. function uc_roles_user_view($account, $view_mode) {
  307. global $user;
  308. // Kick out anonymous.
  309. if (!$user->uid) {
  310. return;
  311. }
  312. // Only show if this user can access all role expirations, or if it's the same
  313. // user and the expirations are showing on the user pages.
  314. $show_expiration = variable_get('uc_roles_default_show_expiration', TRUE);
  315. if (!user_access('view all role expirations') && ($user->uid != $account->uid || !$show_expiration)) {
  316. return;
  317. }
  318. $items = array();
  319. $form = array();
  320. $expirations = db_query("SELECT * FROM {uc_roles_expirations} WHERE uid = :uid", array(':uid' => $account->uid));
  321. foreach ($expirations as $expiration) {
  322. $form[$expiration->rid] = array(
  323. '#type' => 'user_profile_item',
  324. '#title' => check_plain(_uc_roles_get_name($expiration->rid)),
  325. '#markup' => t('This role will expire on !date', array('!date' => format_date($expiration->expiration, 'short'))),
  326. );
  327. }
  328. // Don't display anything if there aren't any expirations.
  329. if (!count($form)) {
  330. return;
  331. }
  332. $item = array(
  333. '#type' => 'user_profile_category',
  334. '#weight' => '-1',
  335. '#title' => t('Expiring roles'),
  336. );
  337. $account->content['uc_roles'] = $item + $form;
  338. }
  339. /**
  340. * Implements hook_uc_order_product_can_ship().
  341. */
  342. function uc_roles_uc_order_product_can_ship($item) {
  343. $roles = db_query("SELECT * FROM {uc_roles_products} WHERE nid = :nid", array(':nid' => $item->nid));
  344. foreach ($roles as $role) {
  345. // If the model is empty, keep looking. (Everyone needs a role model...).
  346. if (empty($role->model)) {
  347. continue;
  348. }
  349. // If there's an adjusted SKU, use it... otherwise use the node SKU.
  350. $sku = (empty($item->data['model'])) ? $item->model : $item->data['model'];
  351. // Keep looking if it doesn't match.
  352. if ($sku != $role->model) {
  353. continue;
  354. }
  355. return $role->shippable;
  356. }
  357. }
  358. /**
  359. * Implements hook_uc_product_feature().
  360. */
  361. function uc_roles_uc_product_feature() {
  362. $features[] = array(
  363. 'id' => 'role',
  364. 'title' => t('Role assignment'),
  365. 'callback' => 'uc_roles_feature_form',
  366. 'delete' => 'uc_roles_feature_delete',
  367. 'settings' => 'uc_roles_feature_settings',
  368. );
  369. return $features;
  370. }
  371. /**
  372. * Implements hook_uc_store_status().
  373. */
  374. function uc_roles_uc_store_status() {
  375. $message = array();
  376. $role_choices = _uc_roles_get_choices();
  377. if (empty($role_choices)) {
  378. $message[] = array(
  379. 'status' => 'warning',
  380. 'title' => t('Roles'),
  381. 'desc' => t('There are no product role(s) that can be assigned upon product purchase. Set product roles in the <a href="!url">product settings</a> under the role assignment settings tab.', array('!url' => url('admin/store/settings/products'))),
  382. );
  383. }
  384. else {
  385. $message[] = array(
  386. 'status' => 'ok',
  387. 'title' => t('Roles'),
  388. 'desc' => t('The role(s) %roles are set to be used with the Role Assignment product feature.', array('%roles' => implode(', ', $role_choices))),
  389. );
  390. }
  391. return $message;
  392. }
  393. /**
  394. * Implements hook_uc_message().
  395. */
  396. function uc_roles_uc_message() {
  397. $messages['uc_roles_grant_subject'] = t('[store:name]: [expiration:name] role granted');
  398. $messages['uc_roles_grant_message'] = t("[order:first-name] [order:last-name], \n\nThanks to your order, [order:link], at [store:name] you now have a new role, [expiration:name].\n\nThanks again, \n\n[store:name]\n[site:slogan]");
  399. $messages['uc_roles_revoke_subject'] = t('[store:name]: [expiration:name] role expired');
  400. $messages['uc_roles_revoke_message'] = t("The role, [expiration:name], you acquired by purchasing a product at our store has expired. Any special access or privileges that came with it are now gone. You can purchase it again by going to [store:link]\n\nThanks again, \n\n[store:name]\n[site:slogan]");
  401. $messages['uc_roles_renew_subject'] = t('[store:name]: [expiration:name] role renewed');
  402. $messages['uc_roles_renew_message'] = t("[order:first-name] [order:last-name], \n\nThanks to your order, [order:link], at [store:name] you have renewed the role, [expiration:name]. It is now set to expire on [expiration:expiration:short].\n\nThanks again, \n\n[store:name]\n[site:slogan]");
  403. $messages['uc_roles_reminder_subject'] = t('[store:name]: [expiration:name] role expiration notice');
  404. $messages['uc_roles_reminder_message'] = t("This message is to remind you that the role, [expiration:name], you acquired by making a purchase at our store will expire at [expiration:expiration:short]. You may visit [store:link] to renew this role before it expires.\n\nThanks again, \n\n[store:name]\n[site:slogan]");
  405. return $messages;
  406. }
  407. /**
  408. * Form builder for hook_uc_product_feature().
  409. *
  410. * @see uc_roles_feature_form_validate()
  411. * @see uc_roles_feature_form_submit()
  412. *
  413. * @ingroup forms
  414. */
  415. function uc_roles_feature_form($form, &$form_state, $node, $feature) {
  416. $models = uc_product_get_models($node->nid);
  417. // Check if editing or adding to set default values.
  418. if (!empty($feature)) {
  419. $product_role = db_query("SELECT * FROM {uc_roles_products} WHERE pfid = :pfid", array(':pfid' => $feature['pfid']))->fetchObject();
  420. $default_model = $product_role->model;
  421. $default_role = $product_role->rid;
  422. $default_qty = $product_role->duration;
  423. $default_granularity = $product_role->granularity;
  424. $default_shippable = $product_role->shippable;
  425. $default_by_quantity = $product_role->by_quantity;
  426. if ($product_role->end_time) {
  427. $end_time = array(
  428. 'day' => date('j', $product_role->end_time),
  429. 'month' => date('n', $product_role->end_time),
  430. 'year' => date('Y', $product_role->end_time),
  431. );
  432. $default_end_type = 'abs';
  433. }
  434. else {
  435. $temp = _uc_roles_get_expiration($default_qty, $default_granularity);
  436. $end_time = array(
  437. 'day' => date('j', $temp),
  438. 'month' => date('n', $temp),
  439. 'year' => date('Y', $temp),
  440. );
  441. $default_end_type = 'rel';
  442. }
  443. $form['pfid'] = array(
  444. '#type' => 'value',
  445. '#value' => $feature['pfid'],
  446. );
  447. $form['rpid'] = array(
  448. '#type' => 'value',
  449. '#value' => $product_role->rpid,
  450. );
  451. $default_end_override = $product_role->end_override;
  452. }
  453. else {
  454. $default_model = 0;
  455. $default_role = variable_get('uc_roles_default_role', NULL);
  456. $default_qty = (variable_get('uc_roles_default_granularity', 'never') == 'never') ? NULL : variable_get('uc_roles_default_length', NULL);
  457. $default_granularity = variable_get('uc_roles_default_granularity', 'never');
  458. $default_shippable = $node->shippable;
  459. $default_by_quantity = variable_get('uc_roles_default_by_quantity', FALSE);
  460. $end_time = variable_get('uc_roles_default_end_time', array(
  461. 'day' => date('j'),
  462. 'month' => date('n'),
  463. 'year' => date('Y'),
  464. ));
  465. $default_end_type = variable_get('uc_roles_default_end_expiration', 'rel');
  466. $default_end_override = FALSE;
  467. }
  468. $roles = _uc_roles_get_choices();
  469. if (!count($roles)) {
  470. // No actions can be done. Remove submit buttons.
  471. unset($form['buttons']);
  472. $form['no_roles'] = array(
  473. '#markup' => t('You need to <a href="!url">create new roles</a> before any can be added as product features.', array('!url' => url('admin/people/permissions/roles', array('query' => array('destination' => 'admin/store/settings/products'))))),
  474. '#prefix' => '<p>',
  475. '#suffix' => '</p>',
  476. );
  477. return $form;
  478. }
  479. $form['nid'] = array(
  480. '#type' => 'value',
  481. '#value' => $node->nid,
  482. );
  483. $form['uc_roles_model'] = array(
  484. '#type' => 'select',
  485. '#title' => t('SKU'),
  486. '#default_value' => $default_model,
  487. '#description' => t('This is the SKU of the product that will grant the role.'),
  488. '#options' => $models,
  489. );
  490. $form['uc_roles_role'] = array(
  491. '#type' => 'select',
  492. '#title' => t('Role'),
  493. '#default_value' => $default_role,
  494. '#description' => t('This is the role the customer will receive after purchasing the product.'),
  495. '#options' => $roles,
  496. );
  497. $form['uc_roles_shippable'] = array(
  498. '#type' => 'checkbox',
  499. '#title' => t('Shippable product'),
  500. '#default_value' => $default_shippable,
  501. '#description' => t('Check if this product SKU that uses role assignment is associated with a shippable product.'),
  502. );
  503. $form['end_override'] = array(
  504. '#type' => 'checkbox',
  505. '#title' => t('Override the <a href="!url">default role expiration</a>.', array('!url' => url('admin/store/settings/products'))),
  506. '#default_value' => $default_end_override,
  507. );
  508. $form['role_lifetime'] = array(
  509. '#type' => 'fieldset',
  510. '#title' => t('Role expiration'),
  511. '#states' => array(
  512. 'visible' => array('input[name="end_override"]' => array('checked' => TRUE)),
  513. ),
  514. );
  515. $form['role_lifetime']['expiration'] = array(
  516. '#type' => 'select',
  517. '#title' => t('Expiration type'),
  518. '#options' => array(
  519. 'rel' => t('Relative to purchase date'),
  520. 'abs' => t('Fixed date'),
  521. ),
  522. '#default_value' => $default_end_type,
  523. );
  524. $form['role_lifetime']['uc_roles_expire_relative_duration'] = array(
  525. '#type' => 'textfield',
  526. '#default_value' => $default_qty,
  527. '#size' => 4,
  528. '#maxlength' => 4,
  529. '#prefix' => '<div class="expiration">',
  530. '#suffix' => '</div>',
  531. '#states' => array(
  532. 'visible' => array('select[name="expiration"]' => array('value' => 'rel')),
  533. 'invisible' => array('select[name="uc_roles_expire_relative_granularity"]' => array('value' => 'never')),
  534. ),
  535. );
  536. $form['role_lifetime']['uc_roles_expire_relative_granularity'] = array(
  537. '#type' => 'select',
  538. '#options' => array(
  539. 'never' => t('never'),
  540. 'day' => t('day(s)'),
  541. 'week' => t('week(s)'),
  542. 'month' => t('month(s)'),
  543. 'year' => t('year(s)'),
  544. ),
  545. '#default_value' => $default_granularity,
  546. '#description' => t('From the time the role was purchased.'),
  547. '#prefix' => '<div class="expiration">',
  548. '#suffix' => '</div>',
  549. '#states' => array(
  550. 'visible' => array('select[name="expiration"]' => array('value' => 'rel')),
  551. ),
  552. );
  553. $form['role_lifetime']['absolute'] = array(
  554. '#type' => 'container',
  555. '#states' => array(
  556. 'visible' => array('select[name="expiration"]' => array('value' => 'abs')),
  557. ),
  558. );
  559. $form['role_lifetime']['absolute']['uc_roles_expire_absolute'] = array(
  560. '#type' => 'date',
  561. '#description' => t('Expire the role at the beginning of this day.'),
  562. );
  563. if ($end_time) {
  564. $form['role_lifetime']['absolute']['uc_roles_expire_absolute']['#default_value'] = $end_time;
  565. }
  566. $form['role_lifetime']['uc_roles_by_quantity'] = array(
  567. '#type' => 'checkbox',
  568. '#title' => t('Multiply by quantity'),
  569. '#default_value' => $default_by_quantity,
  570. '#description' => t('Check if the role duration should be multiplied by the quantity purchased.'),
  571. );
  572. return $form;
  573. }
  574. /**
  575. * Validation function for the roles feature form.
  576. *
  577. * @see uc_roles_feature_form()
  578. * @see uc_roles_feature_form_submit()
  579. */
  580. function uc_roles_feature_form_validate($form, &$form_state) {
  581. // Invalid quantity?
  582. if ($form_state['values']['expiration'] === 'abs') {
  583. $form_state['values']['uc_roles_expire_absolute'] = mktime(0, 0, 0,
  584. $form_state['values']['uc_roles_expire_absolute']['month'],
  585. $form_state['values']['uc_roles_expire_absolute']['day'],
  586. $form_state['values']['uc_roles_expire_absolute']['year']
  587. );
  588. if ($form_state['values']['uc_roles_expire_absolute'] <= REQUEST_TIME) {
  589. form_set_error('uc_roles_expire_absolute', t('The specified date !date has already occurred. Please choose another.', array('!date' => format_date($form_state['values']['uc_roles_expire_absolute']))));
  590. }
  591. }
  592. else {
  593. if ($form_state['values']['uc_roles_expire_relative_granularity'] != 'never' && intval($form_state['values']['uc_roles_expire_relative_duration']) < 1) {
  594. form_set_error('uc_roles_expire_relative_duration', t('The amount of time must be a positive integer.'));
  595. }
  596. }
  597. // No roles?
  598. if (empty($form_state['values']['uc_roles_role'])) {
  599. form_set_error('uc_roles_role', t('You must have a role to assign. You may need to <a href="!role_url">create a new role</a> or perhaps <a href="!feature_url">set role assignment defaults</a>.', array('!role_url' => url('admin/people/permissions/roles'), '!feature_url' => url('admin/store/settings/products'))));
  600. }
  601. // This role already set on this SKU?
  602. if (!isset($form_state['values']['pfid']) && ($product_roles = db_query("SELECT * FROM {uc_roles_products} WHERE nid = :nid AND model = :model AND rid = :rid", array(':nid' => $form_state['values']['nid'], ':model' => $form_state['values']['uc_roles_model'], ':rid' => $form_state['values']['uc_roles_role']))->fetchObject())) {
  603. form_set_error('uc_roles_role', t('The combination of SKU and role already exists for this product.'));
  604. form_set_error('uc_roles_model', ' ');
  605. }
  606. }
  607. /**
  608. * Little helper for cleaning up input to drupal_write_record().
  609. */
  610. function uc_roles_product_write_record($product_role) {
  611. foreach (array('duration', 'granularity', 'end_time') as $property) {
  612. $product_role[$property] = $product_role[$property] === NULL ? 0 : $product_role[$property];
  613. }
  614. $key = array();
  615. if ($product_role['rpid']) {
  616. $key = 'rpid';
  617. }
  618. drupal_write_record('uc_roles_products', $product_role, $key);
  619. }
  620. /**
  621. * Submission handler for uc_roles_feature_form().
  622. *
  623. * @see uc_roles_feature_form()
  624. * @see uc_roles_feature_form_validate()
  625. */
  626. function uc_roles_feature_form_submit($form, &$form_state) {
  627. $product_role = array(
  628. 'pfid' => isset($form_state['values']['pfid']) ? $form_state['values']['pfid'] : NULL,
  629. 'rpid' => isset($form_state['values']['rpid']) ? $form_state['values']['rpid'] : NULL,
  630. 'nid' => $form_state['values']['nid'],
  631. 'model' => $form_state['values']['uc_roles_model'],
  632. 'rid' => $form_state['values']['uc_roles_role'],
  633. 'duration' => $form_state['values']['uc_roles_expire_relative_granularity'] != 'never' ? $form_state['values']['uc_roles_expire_relative_duration'] : NULL,
  634. 'granularity' => $form_state['values']['uc_roles_expire_relative_granularity'],
  635. 'by_quantity' => $form_state['values']['uc_roles_by_quantity'],
  636. 'shippable' => $form_state['values']['uc_roles_shippable'],
  637. // We should be setting NULL, but drupal_write_record() ...
  638. 'end_override' => $form_state['values']['end_override'],
  639. 'end_time' => $form_state['values']['expiration'] === 'abs' ? $form_state['values']['uc_roles_expire_absolute'] : NULL,
  640. );
  641. $description = empty($product_role['model']) ? t('<strong>SKU:</strong> Any<br />') : t('<strong>SKU:</strong> !sku<br />', array('!sku' => $product_role['model']));
  642. $description .= t('<strong>Role:</strong> @role_name<br />', array('@role_name' => _uc_roles_get_name($product_role['rid'])));
  643. if ($product_role['end_override']) {
  644. if ($product_role['end_time']) {
  645. $description .= t('<strong>Expiration:</strong> !date<br />', array('!date' => format_date($product_role['end_time'])));
  646. }
  647. else {
  648. switch ($product_role['granularity']) {
  649. case 'never':
  650. $description .= t('<strong>Expiration:</strong> never<br />');
  651. break;
  652. case 'day':
  653. $description .= t('<strong>Expiration:</strong> !qty day(s)<br />', array('!qty' => $product_role['duration']));
  654. break;
  655. case 'week':
  656. $description .= t('<strong>Expiration:</strong> !qty week(s)<br />', array('!qty' => $product_role['duration']));
  657. break;
  658. case 'month':
  659. $description .= t('<strong>Expiration:</strong> !qty month(s)<br />', array('!qty' => $product_role['duration']));
  660. break;
  661. case 'year':
  662. $description .= t('<strong>Expiration:</strong> !qty year(s)<br />', array('!qty' => $product_role['duration']));
  663. break;
  664. default:
  665. break;
  666. }
  667. }
  668. }
  669. else {
  670. $description .= t('<strong>Expiration:</strong> !link (not overridden)<br />', array('!link' => l(t('Global expiration'), 'admin/store/settings/products')));
  671. }
  672. $description .= $product_role['shippable'] ? t('<strong>Shippable:</strong> Yes<br />') : t('<strong>Shippable:</strong> No<br />');
  673. $description .= $product_role['by_quantity'] ? t('<strong>Multiply by quantity:</strong> Yes') : t('<strong>Multiply by quantity:</strong> No');
  674. $data = array(
  675. 'pfid' => $product_role['pfid'],
  676. 'nid' => $product_role['nid'],
  677. 'fid' => 'role',
  678. 'description' => $description,
  679. );
  680. $form_state['redirect'] = uc_product_feature_save($data);
  681. // Updating the 'pfid' on $product_role and on $form_state for future use.
  682. $form_state['values']['pfid'] = $product_role['pfid'] = $data['pfid'];
  683. // Insert or update uc_file_product table.
  684. uc_roles_product_write_record($product_role);
  685. }
  686. /**
  687. * Form builder for role settings.
  688. *
  689. * @ingroup forms
  690. */
  691. function uc_roles_feature_settings($form, &$form_state) {
  692. $default_role_choices = user_roles(TRUE);
  693. unset($default_role_choices[DRUPAL_AUTHENTICATED_RID]);
  694. if (!count($default_role_choices)) {
  695. $form['no_roles'] = array(
  696. '#markup' => t('You need to <a href="!url">create new roles</a> before any can be added as product features.', array('!url' => url('admin/people/permissions/roles', array('query' => array('destination' => 'admin/store/settings/products'))))),
  697. '#prefix' => '<p>',
  698. '#suffix' => '</p>',
  699. );
  700. return $form;
  701. }
  702. foreach (uc_order_status_list('general') as $status) {
  703. $statuses[$status['id']] = $status['title'];
  704. }
  705. $form['uc_roles_default_role'] = array(
  706. '#type' => 'select',
  707. '#title' => t('Default role'),
  708. '#default_value' => variable_get('uc_roles_default_role', NULL),
  709. '#description' => t('The default role Ubercart grants on specified products.'),
  710. '#options' => _uc_roles_get_choices(),
  711. );
  712. $form['uc_roles_default_role_choices'] = array(
  713. '#type' => 'checkboxes',
  714. '#title' => t('Product roles'),
  715. '#default_value' => variable_get('uc_roles_default_role_choices', array()),
  716. '#multiple' => TRUE,
  717. '#description' => t('These are roles that Ubercart can grant to customers who purchase specified products. If you leave all roles unchecked, they will all be eligible for adding to a product.'),
  718. '#options' => $default_role_choices,
  719. );
  720. $form['role_lifetime'] = array(
  721. '#type' => 'fieldset',
  722. '#title' => t('Default role expiration'),
  723. );
  724. $form['role_lifetime']['uc_roles_default_end_expiration'] = array(
  725. '#type' => 'select',
  726. '#title' => t('Expiration type'),
  727. '#options' => array(
  728. 'rel' => t('Relative to purchase date'),
  729. 'abs' => t('Fixed date'),
  730. ),
  731. '#default_value' => variable_get('uc_roles_default_end_expiration', 'rel'),
  732. );
  733. $form['role_lifetime']['uc_roles_default_length'] = array(
  734. '#type' => 'textfield',
  735. '#default_value' => (variable_get('uc_roles_default_granularity', 'never') == 'never') ? NULL : variable_get('uc_roles_default_length', NULL),
  736. '#size' => 4,
  737. '#maxlength' => 4,
  738. '#prefix' => '<div class="expiration">',
  739. '#suffix' => '</div>',
  740. '#states' => array(
  741. 'visible' => array('select[name="uc_roles_default_end_expiration"]' => array('value' => 'rel')),
  742. 'invisible' => array('select[name="uc_roles_default_granularity"]' => array('value' => 'never')),
  743. ),
  744. );
  745. $form['role_lifetime']['uc_roles_default_granularity'] = array(
  746. '#type' => 'select',
  747. '#default_value' => variable_get('uc_roles_default_granularity', 'never'),
  748. '#options' => array(
  749. 'never' => t('never'),
  750. 'day' => t('day(s)'),
  751. 'week' => t('week(s)'),
  752. 'month' => t('month(s)'),
  753. 'year' => t('year(s)'),
  754. ),
  755. '#description' => t('From the time the role was purchased.'),
  756. '#prefix' => '<div class="expiration">',
  757. '#suffix' => '</div>',
  758. '#states' => array(
  759. 'visible' => array('select[name="uc_roles_default_end_expiration"]' => array('value' => 'rel')),
  760. ),
  761. );
  762. $form['role_lifetime']['absolute'] = array(
  763. '#type' => 'container',
  764. '#states' => array(
  765. 'visible' => array('select[name="uc_roles_default_end_expiration"]' => array('value' => 'abs')),
  766. ),
  767. );
  768. $form['role_lifetime']['absolute']['uc_roles_default_end_time'] = array(
  769. '#type' => 'date',
  770. '#description' => t('Expire the role at the beginning of this day.'),
  771. '#default_value' => variable_get('uc_roles_default_end_time', array(
  772. 'day' => date('j'),
  773. 'month' => date('n'),
  774. 'year' => date('Y'),
  775. )),
  776. );
  777. $form['role_lifetime']['uc_roles_default_by_quantity'] = array(
  778. '#type' => 'checkbox',
  779. '#title' => t('Multiply by quantity'),
  780. '#description' => t('Check if the role duration should be multiplied by the quantity purchased.'),
  781. '#default_value' => variable_get('uc_roles_default_by_quantity', FALSE),
  782. );
  783. $form['reminder']['uc_roles_reminder_length'] = array(
  784. '#type' => 'textfield',
  785. '#title' => t('Time before reminder'),
  786. '#default_value' => (variable_get('uc_roles_reminder_granularity', 'never') == 'never') ? NULL : variable_get('uc_roles_reminder_length', NULL),
  787. '#size' => 4,
  788. '#maxlength' => 4,
  789. '#prefix' => '<div class="expiration">',
  790. '#suffix' => '</div>',
  791. '#states' => array(
  792. 'disabled' => array('select[name="uc_roles_reminder_granularity"]' => array('value' => 'never')),
  793. ),
  794. );
  795. $form['reminder']['uc_roles_reminder_granularity'] = array(
  796. '#type' => 'select',
  797. '#default_value' => variable_get('uc_roles_reminder_granularity', 'never'),
  798. '#options' => array(
  799. 'never' => t('never'),
  800. 'day' => t('day(s)'),
  801. 'week' => t('week(s)'),
  802. 'month' => t('month(s)'),
  803. 'year' => t('year(s)'),
  804. ),
  805. '#description' => t('The amount of time before a role expiration takes place that a customer is notified of its expiration.'),
  806. '#prefix' => '<div class="expiration">',
  807. '#suffix' => '</div>',
  808. );
  809. $form['uc_roles_default_show_expiration'] = array(
  810. '#type' => 'checkbox',
  811. '#title' => t('Show expirations on user page'),
  812. '#default_value' => variable_get('uc_roles_default_show_expiration', TRUE),
  813. '#description' => t('If users have any role expirations they will be displayed on their account page.'),
  814. );
  815. return $form;
  816. }
  817. /**
  818. * Gets role name.
  819. *
  820. * @param int $rid
  821. * The Drupal role id number.
  822. *
  823. * @return string|false
  824. * A string containing the name of the role, returns FALSE if rid is invalid.
  825. */
  826. function _uc_roles_get_name($rid) {
  827. $roles = user_roles(TRUE);
  828. return (!is_null($roles[$rid])) ? $roles[$rid] : FALSE;
  829. }
  830. /**
  831. * Gets available roles for granting on product purchase.
  832. *
  833. * @param array $exclude
  834. * A list of role ids to exclude from the list.
  835. *
  836. * @return array
  837. * An assoc array with key = rid and value = role name.
  838. */
  839. function _uc_roles_get_choices($exclude = array()) {
  840. $output = array();
  841. // Get roles from Drupal, excluding Anonymous and Authenticated.
  842. $roles = user_roles(TRUE);
  843. unset($roles[DRUPAL_AUTHENTICATED_RID]);
  844. // User set specific roles that we must use?
  845. $selected = variable_get('uc_roles_default_role_choices', array());
  846. // If there's none, or if none are checked, use all of em.
  847. $default = empty($selected) || array_sum($selected) == 0;
  848. foreach ($roles as $rid => $name) {
  849. if ($default || (!empty($selected[$rid]) && !in_array($rid, $exclude))) {
  850. $output[$rid] = $roles[$rid];
  851. }
  852. }
  853. return $output;
  854. }
  855. /**
  856. * Deletes all role data associated with a given product feature.
  857. *
  858. * @param int $pfid
  859. * An Ubercart product feature ID.
  860. */
  861. function uc_roles_feature_delete($pfid) {
  862. db_delete('uc_roles_products')
  863. ->condition('pfid', $pfid)
  864. ->execute();
  865. }
  866. /**
  867. * Deletes an expiration using user id or user id and rid.
  868. *
  869. * This function deletes expirations associated with users and roles. If
  870. * no role ID is passed, the function deletes all role expirations associated
  871. * with the given user. Otherwise, the function only deletes expirations whose
  872. * user and role IDs match. If any roles were actually deleted, the function
  873. * notifies the user. The menu cache is then flushed, as privileges to view
  874. * menu items may have been lost in the process.
  875. *
  876. * @param $account
  877. * A Drupal user object.
  878. * @param int $rid
  879. * A Drupal role ID.
  880. * @param bool $silent
  881. * When set to TRUE will suppress any Drupal messages from this function.
  882. */
  883. function uc_roles_delete($account, $rid = NULL, $silent = FALSE) {
  884. global $user;
  885. $query = db_delete('uc_roles_expirations')
  886. ->condition('uid', $account->uid);
  887. if ($rid) {
  888. $query->condition('rid', $rid);
  889. }
  890. // Echo the deletion only if something was actually deleted.
  891. if ($query->execute() && !$silent) {
  892. if ($user->uid == $account->uid) {
  893. drupal_set_message(t('The expiration of your %role_name role has been deleted.', array('%role_name' => _uc_roles_get_name($rid))));
  894. }
  895. else {
  896. drupal_set_message(t('The expiration of %role_name role for the user !user has been deleted.', array(
  897. '!user' => theme('username', array(
  898. 'account' => $account,
  899. 'name' => check_plain(format_username($account)),
  900. 'link_path' => 'user/' . $account->uid,
  901. )),
  902. '%role_name' => _uc_roles_get_name($rid),
  903. )));
  904. }
  905. }
  906. // Flush visible menu items, since our permissions could've changed.
  907. _uc_roles_flush_menu_cache($account);
  908. }
  909. /**
  910. * Revokes a role on a given user.
  911. *
  912. * This function deletes a given role from a user's list of roles, as
  913. * well as removing any expiration data associated with the user/role.
  914. * The function notifies the user of revocation.
  915. *
  916. * @param $account
  917. * A Drupal user object.
  918. * @param int $rid
  919. * A Drupal role ID.
  920. * @param bool $silent
  921. * When set to TRUE will suppress any Drupal messages from this function.
  922. */
  923. function uc_roles_revoke(&$account, $rid, $silent = FALSE) {
  924. global $user;
  925. // Remove this role from the user's list.
  926. $roles_list = $account->roles;
  927. unset($roles_list[$rid]);
  928. $account = user_save($account, array('roles' => $roles_list));
  929. // Remove our record of the expiration.
  930. uc_roles_delete($account, $rid, $silent);
  931. $role_name = db_query("SELECT name FROM {role} WHERE rid = :rid", array(':rid' => $rid))->fetchField();
  932. if (!$silent) {
  933. if ($user->uid == $account->uid) {
  934. drupal_set_message(t('Your %role role has been revoked.', array('%role' => $role_name)));
  935. }
  936. else {
  937. drupal_set_message(t('!user has had the %role role revoked.', array(
  938. '!user' => theme('username', array(
  939. 'account' => $account,
  940. 'name' => check_plain(format_username($account)),
  941. 'link_path' => 'user/' . $account->uid,
  942. )),
  943. '%role' => $role_name,
  944. )));
  945. }
  946. }
  947. }
  948. /**
  949. * Grants a role to a given user.
  950. *
  951. * This function grants a given role to a user's list of roles. If there
  952. * is a previous record of this user/role combination, it is first removed.
  953. * The function then saves the user (if $user_save is TRUE). Next, a check
  954. * to verify the role actually exists, if not, no expiration data is stored.
  955. * The menu cache is flushed, as new menu items may be visible after the
  956. * new role is granted. The function notifies the user of the role grant.
  957. *
  958. * @param $account
  959. * A Drupal user object.
  960. * @param int $rid
  961. * A Drupal role ID.
  962. * @param int $timestamp
  963. * When this role will expire.
  964. * @param $save_user
  965. * Optimization to prevent unnecessary user saving when calling from
  966. * uc_roles_user_presave().
  967. * @param bool $silent
  968. * When set to TRUE will suppress any Drupal messages from this function.
  969. */
  970. function uc_roles_grant(&$account, $rid, $timestamp, $save_user = TRUE, $silent = FALSE) {
  971. global $user;
  972. // First, delete any previous record of this user/role association.
  973. uc_roles_delete($account, $rid, $silent);
  974. if ($save_user) {
  975. // Punch the role into the user object.
  976. $roles_list = $account->roles + array($rid => _uc_roles_get_name($rid));
  977. $account = user_save($account, array('roles' => $roles_list));
  978. }
  979. // If the role expires, keep a record.
  980. if (!is_null($timestamp)) {
  981. db_insert('uc_roles_expirations')
  982. ->fields(array(
  983. 'uid' => $account->uid,
  984. 'rid' => $rid,
  985. 'expiration' => $timestamp,
  986. ))
  987. ->execute();
  988. }
  989. // Flush visible menu items, since our permissions could've changed.
  990. _uc_roles_flush_menu_cache($account);
  991. // Display the message if appropriate.
  992. if (!$silent) {
  993. $role_name = db_query("SELECT name FROM {role} WHERE rid = :rid", array(':rid' => $rid))->fetchField();
  994. if ($user->uid == $account->uid) {
  995. $message = t('You have been granted the %role role.', array('%role' => $role_name));
  996. }
  997. else {
  998. $message = t('!user has been granted the %role role.', array(
  999. '!user' => theme('username', array(
  1000. 'account' => $account,
  1001. 'name' => check_plain(format_username($account)),
  1002. 'link_path' => 'user/' . $account->uid,
  1003. )),
  1004. '%role' => $role_name,
  1005. ));
  1006. }
  1007. if ($timestamp) {
  1008. $message .= ' ' . t('It will expire on %date', array('%date' => format_date($timestamp, 'short')));
  1009. }
  1010. drupal_set_message($message);
  1011. }
  1012. }
  1013. /**
  1014. * Renews a given role on a user.
  1015. *
  1016. * This function updates expiration time on a role already granted to a
  1017. * user. First the function checks the new expiration. If it never expires,
  1018. * the function deletes the past expiration record and returns, leaving
  1019. * management up to Drupal. Otherwise, the record is updated with the new
  1020. * expiration time, and the user is notified of the change.
  1021. *
  1022. * @param $account
  1023. * A Drupal user object.
  1024. * @param int $rid
  1025. * A Drupal role ID.
  1026. * @param int $timestamp
  1027. * When this role will expire.
  1028. * @param bool $silent
  1029. * When set to TRUE will suppress any Drupal messages from this function.
  1030. */
  1031. function uc_roles_renew($account, $rid, $timestamp, $silent = FALSE) {
  1032. global $user;
  1033. // If it doesn't expire, we'll remove our data associated with it.
  1034. // After that, Drupal will take care of it.
  1035. if (is_null($timestamp)) {
  1036. uc_roles_delete($account, $rid);
  1037. return;
  1038. }
  1039. // Update the expiration date and reset the notified flag.
  1040. db_update('uc_roles_expirations')
  1041. ->fields(array(
  1042. 'expiration' => $timestamp,
  1043. 'notified' => NULL,
  1044. ))
  1045. ->condition('uid', $account->uid)
  1046. ->condition('rid', $rid)
  1047. ->execute();
  1048. if (!$silent) {
  1049. $role_name = db_query("SELECT name FROM {role} WHERE rid = :rid", array(':rid' => $rid))->fetchField();
  1050. if ($user->uid == $account->uid) {
  1051. $message = t('Your %role role has been renewed. It will expire on %date.', array('%role' => $role_name, '%date' => format_date($timestamp, 'short')));
  1052. }
  1053. else {
  1054. $message = t("!user's %role role has been renewed. It will expire on %date.", array(
  1055. '!user' => theme('username', array(
  1056. 'account' => $account,
  1057. 'name' => check_plain(format_username($account)),
  1058. 'link_path' => 'user/' . $account->uid,
  1059. )),
  1060. '%role' => $role_name,
  1061. '%date' => format_date($timestamp, 'short'),
  1062. ));
  1063. }
  1064. drupal_set_message($message);
  1065. }
  1066. }
  1067. /**
  1068. * Flushes the menu cache.
  1069. *
  1070. * When roles are gained/lost, menu items might appear/disappear respectively,
  1071. * so we have to ensure the cache is rebuilt with any new values.
  1072. *
  1073. * @param $account
  1074. * A Drupal user object.
  1075. *
  1076. * @see uc_roles_delete()
  1077. * @see uc_roles_grant()
  1078. */
  1079. function _uc_roles_flush_menu_cache($account) {
  1080. cache_clear_all($account->uid . ':', 'cache_menu', TRUE);
  1081. }
  1082. /**
  1083. * Calculates the expiration time using a role_product object.
  1084. *
  1085. * @param $role_product
  1086. * The role product object whose expiration times to calculate.
  1087. * @param $quantity
  1088. * Used to multiply any relative expiration time, if the $role_product
  1089. * says to.
  1090. * @param $time
  1091. * The current time to use as a starting point for relative expiration
  1092. * calculation.
  1093. */
  1094. function _uc_roles_product_get_expiration($role_product, $quantity, $time) {
  1095. // Override the end expiration?
  1096. if ($role_product->end_override) {
  1097. // Absolute times are easy...
  1098. if ($role_product->end_time) {
  1099. return $role_product->end_time;
  1100. }
  1101. // We're gonna have to calculate the relative time from $time.
  1102. $length = $role_product->duration * ($role_product->by_quantity ? $quantity : 1);
  1103. return _uc_roles_get_expiration($length, $role_product->granularity, $time);
  1104. }
  1105. // No override, use the default expiration values.
  1106. else {
  1107. // Relative...
  1108. if (variable_get('uc_roles_default_end_expiration', 'rel') === 'rel') {
  1109. $length = variable_get('uc_roles_default_length', NULL) * ($role_product->by_quantity ? $quantity : 1);
  1110. return _uc_roles_get_expiration($length, variable_get('uc_roles_default_granularity', 'never'), $time);
  1111. }
  1112. // Absolute...
  1113. $end_time = variable_get('uc_roles_default_end_time', NULL);
  1114. if ($end_time) {
  1115. $end_time = mktime(0, 0, 0, $end_time['month'], $end_time['day'], $end_time['year']);
  1116. }
  1117. return $end_time;
  1118. }
  1119. }
  1120. /**
  1121. * Returns an expiration time stamp given a period of time.
  1122. *
  1123. * @param $duration
  1124. * The amount of time until expiration.
  1125. * @param $granularity
  1126. * A string representing the granularity's name (e.g. "day", "month", etc.).
  1127. * @param $start_time
  1128. * (optional) The starting date for when the role will last. Defaults to
  1129. * the current time.
  1130. *
  1131. * @return int|null
  1132. * A UNIX timestamp representing the second that expiration takes place,
  1133. * or NULL if the expiration should never occur.
  1134. */
  1135. function _uc_roles_get_expiration($duration, $granularity, $start_time = NULL) {
  1136. // Never expires?
  1137. if ($granularity == 'never') {
  1138. return NULL;
  1139. }
  1140. $start_time = (!is_null($start_time)) ? $start_time : REQUEST_TIME;
  1141. $operator = ($duration < 0) ? '' : '+';
  1142. return strtotime($operator . $duration . ' ' . $granularity, $start_time);
  1143. }
  1144. /**
  1145. * Implements hook_views_api().
  1146. */
  1147. function uc_roles_views_api() {
  1148. return array(
  1149. 'api' => '2.0',
  1150. 'path' => drupal_get_path('module', 'uc_roles') . '/views',
  1151. );
  1152. }