uc_file.rules.inc 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. <?php
  2. /**
  3. * @file
  4. * Rules hooks and functions for uc_file.module.
  5. */
  6. /**
  7. * Implements hook_rules_data_info().
  8. *
  9. * An entity is defined in order to get file expiration(s) down to token in the
  10. * email.
  11. */
  12. function uc_file_rules_data_info() {
  13. $data['uc_file_expiration'] = array(
  14. 'label' => t('Ubercart file expiration(s)'),
  15. 'wrap' => TRUE,
  16. 'property info' => array(
  17. 'fuid' => array(
  18. 'type' => 'integer',
  19. 'label' => t('File-user ID'),
  20. 'description' => t('Primary key for user permission to download a file.'),
  21. ),
  22. 'fid' => array(
  23. 'type' => 'integer',
  24. 'label' => t('File ID'),
  25. 'description' => t('The file that may be downloaded.'),
  26. ),
  27. 'file' => array(
  28. 'type' => 'file',
  29. 'label' => t('File'),
  30. 'description' => t('The file that may be downloaded.'),
  31. 'getter callback' => 'uc_file_get_expiration_properties',
  32. 'setter callback' => 'uc_file_set_expiration_properties',
  33. ),
  34. 'uid' => array(
  35. 'type' => 'integer',
  36. 'label' => t('User ID'),
  37. 'description' => t('The user account ID.'),
  38. ),
  39. 'user' => array(
  40. 'type' => 'user',
  41. 'label' => t('User'),
  42. 'description' => t('The user account that may download the file.'),
  43. 'getter callback' => 'uc_file_get_expiration_properties',
  44. 'setter callback' => 'uc_file_set_expiration_properties',
  45. ),
  46. 'pfid' => array(
  47. 'type' => 'integer',
  48. 'label' => t('Product feature ID'),
  49. 'description' => t('The product feature that granted permission to download the file.'),
  50. ),
  51. 'file-key' => array(
  52. 'type' => 'text',
  53. 'label' => t('File key'),
  54. 'description' => t('A hash of the permission and expiraiton data.'),
  55. ),
  56. 'granted' => array(
  57. 'type' => 'date',
  58. 'label' => t('Granted time'),
  59. 'description' => t('The time the permission to download the file was granted.'),
  60. ),
  61. 'expiration' => array(
  62. 'type' => 'date',
  63. 'label' => t('Expiration time'),
  64. 'description' => t('The time when the permission to download the file will expire.'),
  65. ),
  66. 'accessed' => array(
  67. 'type' => 'integer',
  68. 'label' => t('Accesses'),
  69. 'description' => t('The number of times the file has been accessed.'),
  70. ),
  71. 'addresses' => array(
  72. 'type' => 'list<text>',
  73. 'label' => t('IP addresses'),
  74. 'description' => t('List of IP addresses to which the file has been downloaded.'),
  75. ),
  76. 'download-limit' => array(
  77. 'type' => 'integer',
  78. 'label' => t('Download limit'),
  79. 'description' => t('The numer of times the user may download the file.'),
  80. ),
  81. 'address-limit' => array(
  82. 'type' => 'integer',
  83. 'label' => t('Address limit'),
  84. 'description' => t('The number of different IP addresses that may download the file.'),
  85. ),
  86. ),
  87. 'group' => t('File download'),
  88. 'token type' => 'uc_file',
  89. );
  90. return $data;
  91. }
  92. /**
  93. * Callback for getting download expiration properties.
  94. *
  95. * @see entity_metadata_node_entity_info_alter()
  96. */
  97. function uc_file_get_expiration_properties($expiration, array $options, $name, $entity_type) {
  98. switch ($name) {
  99. case 'user':
  100. return $expiration->uid;
  101. case 'file':
  102. return $expiration->fid;
  103. }
  104. }
  105. /**
  106. * Callback for setting download expiration properties.
  107. *
  108. * @see entity_metadata_node_entity_info_alter()
  109. */
  110. function uc_file_set_expiration_properties($expiration, $name, $value) {
  111. if ($name == 'user') {
  112. $expiration->uid = $value;
  113. }
  114. elseif ($name == 'file') {
  115. $expiration->fid = $value;
  116. }
  117. }
  118. /**
  119. * Implements hook_rules_action_info().
  120. */
  121. function uc_file_rules_action_info() {
  122. // Renew file expirations.
  123. $actions['uc_file_order_renew'] = array(
  124. 'label' => t('Renew the files on an order.'),
  125. 'group' => t('renewal'),
  126. 'base' => 'uc_file_action_order_renew',
  127. 'parameter' => array(
  128. 'order' => array(
  129. 'type' => 'uc_order',
  130. 'label' => t('Order'),
  131. ),
  132. ),
  133. );
  134. // Send an email to an order with a file expiration.
  135. $actions['uc_file_order_email'] = array(
  136. 'label' => t('Send an order email regarding files.'),
  137. 'group' => t('Notification'),
  138. 'base' => 'uc_file_action_order_email',
  139. 'parameter' => array(
  140. 'order' => array(
  141. 'type' => 'uc_order',
  142. 'label' => t('Order'),
  143. ),
  144. 'expiration' => array(
  145. 'type' => 'uc_file_expiration',
  146. 'label' => t('File expiration'),
  147. ),
  148. 'from' => array(
  149. 'type' => 'text',
  150. 'label' => t('Sender'),
  151. ),
  152. 'addresses' => array(
  153. 'type' => 'text',
  154. 'label' => t('Recipients'),
  155. ),
  156. 'subject' => array(
  157. 'type' => 'text',
  158. 'label' => t('Subject'),
  159. ),
  160. 'message' => array(
  161. 'type' => 'text',
  162. 'label' => t('Message'),
  163. ),
  164. 'format' => array(
  165. 'type' => 'text',
  166. 'label' => t('Message format'),
  167. 'options list' => 'uc_file_message_formats',
  168. ),
  169. ),
  170. );
  171. return $actions;
  172. }
  173. /**
  174. * Options list callback for message formats.
  175. */
  176. function uc_file_message_formats() {
  177. global $user;
  178. $options = array();
  179. $formats = filter_formats($user);
  180. foreach ($formats as $format) {
  181. $options[$format->format] = $format->name;
  182. }
  183. return $options;
  184. }
  185. /**
  186. * Implements hook_rules_event_info().
  187. */
  188. function uc_file_rules_event_info() {
  189. $events['uc_file_notify_grant'] = array(
  190. 'label' => t('E-mail for granted files'),
  191. 'group' => t('Notification'),
  192. 'variables' => array(
  193. 'order' => array(
  194. 'type' => 'uc_order',
  195. 'label' => t('Order'),
  196. ),
  197. 'expiration' => array(
  198. 'type' => 'uc_file_expiration',
  199. 'label' => t('File expiration'),
  200. ),
  201. ),
  202. );
  203. return $events;
  204. }
  205. /**
  206. * Send an email with order and file replacement tokens.
  207. *
  208. * The recipients, subject, and message fields take order token replacements.
  209. */
  210. function uc_file_action_order_email($order, $file_expiration, $from, $addresses, $subject, $message, $format) {
  211. $settings = array(
  212. 'from' => $from,
  213. 'addresses' => $addresses,
  214. 'subject' => $subject,
  215. 'message' => $message,
  216. 'format' => $format,
  217. );
  218. // Token replacements for the subject and body.
  219. $settings['replacements'] = array(
  220. 'uc_order' => $order,
  221. 'uc_file' => $file_expiration,
  222. );
  223. // Replace tokens and parse recipients.
  224. $recipients = array();
  225. $addresses = token_replace($settings['addresses'], $settings['replacements']);
  226. foreach (explode("\n", $addresses) as $address) {
  227. $recipients[] = trim($address);
  228. }
  229. // Send to each recipient.
  230. foreach ($recipients as $email) {
  231. $sent = drupal_mail('uc_order', 'action-mail', $email, uc_store_mail_recipient_language($email), $settings, $settings['from']);
  232. if (!$sent['result']) {
  233. watchdog('uc_file', 'Attempt to e-mail @email concerning order @order_id failed.', array('@email' => $email, '@order_id' => $order->order_id), WATCHDOG_ERROR);
  234. }
  235. }
  236. }
  237. /**
  238. * Renews an orders product files.
  239. *
  240. * This function updates access limits on all files found on all products
  241. * on a given order. First, the order user is loaded, then the order's products
  242. * are scanned for file product features. An order comment is saved, and the
  243. * user is notified in Drupal, as well as through the email address associated
  244. * with the order.
  245. *
  246. * @param object $order
  247. * An Ubercart order object.
  248. */
  249. function uc_file_action_order_renew($order) {
  250. $user_downloads = array();
  251. // Load user.
  252. if (!$order->uid || !($order_user = user_load($order->uid))) {
  253. return;
  254. }
  255. // Scan products for models matching downloads.
  256. foreach ($order->products as $product) {
  257. $files = db_query("SELECT * FROM {uc_file_products} fp " .
  258. "INNER JOIN {uc_product_features} pf ON pf.pfid = fp.pfid " .
  259. "INNER JOIN {uc_files} f ON f.fid = fp.fid " .
  260. "WHERE nid = :nid", array(':nid' => $product->nid));
  261. foreach ($files as $file) {
  262. // Either they match, or the file was set to any SKU.
  263. if (!empty($file->model) && $file->model != $product->model) {
  264. continue;
  265. }
  266. // Grab any existing privilege so we can calculate the new expiration time
  267. // as an offset of the previous.
  268. $file_user = _uc_file_user_get($order_user, $file->fid);
  269. // Get the limit info from the product feature.
  270. $file_modification = array(
  271. 'download_limit' => uc_file_get_download_limit($file),
  272. 'address_limit' => uc_file_get_address_limit($file),
  273. 'expiration' => _uc_file_expiration_date(uc_file_get_time_limit($file), ($file_user ? max($file_user->expiration, REQUEST_TIME) : NULL)),
  274. );
  275. // Add file_user(s) for this file/directory. (No overwrite).
  276. $new_files = uc_file_user_renew($file->fid, $order_user, $file->pfid, $file_modification, FALSE);
  277. // Save for notification.
  278. $user_downloads = array_merge($user_downloads, $new_files);
  279. // Note on the order where the user has gained download permission.
  280. if (is_dir(uc_file_qualify_file($file->filename))) {
  281. $comment = t('User can now download files in the directory %dir.', array('%dir' => $file->filename));
  282. }
  283. else {
  284. $comment = t('User can now download the file %file.', array('%file' => basename($file->filename)));
  285. }
  286. uc_order_comment_save($order->order_id, $order_user->uid, $comment);
  287. }
  288. }
  289. // Notify the user of their download(s).
  290. if ($user_downloads) {
  291. rules_invoke_event('uc_file_notify_grant', $order, $user_downloads);
  292. }
  293. }