- <?php 
- /* 
-  * Copyright (C) 2017 Karmabunny Pty Ltd. 
-  * 
-  * This file is a part of SproutCMS. 
-  * 
-  * SproutCMS is free software: you can redistribute it and/or modify it under the terms 
-  * of the GNU General Public License as published by the Free Software Foundation, either 
-  * version 2 of the License, or (at your option) any later version. 
-  * 
-  * For more information, visit <http://getsproutcms.com>. 
-  */ 
-   
- namespace Sprout\Controllers; 
-   
- use Exception; 
- use InvalidArgumentException; 
-   
- use karmabunny\pdb\Exceptions\RowMissingException; 
- use Sprout\Helpers\AdminAuth; 
- use Sprout\Helpers\Cron; 
- use Sprout\Helpers\Email; 
- use Sprout\Helpers\Enc; 
- use Sprout\Helpers\Notification; 
- use Sprout\Helpers\Pdb; 
- use Sprout\Helpers\Sprout; 
- use Sprout\Helpers\SubsiteSelector; 
- use Sprout\Helpers\Subsites; 
- use Sprout\Helpers\Url; 
- use Sprout\Helpers\View; 
-   
-   
- /** 
-  * Handles subscriptions to various types of content in a centralised manner 
-  * 
-  * Subscribers are emailed regarding new/updated content as various subscription handlers see fit 
-  */ 
- class ContentSubscribeController extends Controller 
- { 
-   
-     public function __construct() 
-     { 
-         parent::__construct(); 
-     } 
-   
-   
-     /** 
-     * Unsubscribe a user from a subscription (form) 
-     **/ 
-     public function unsub($id, $code) 
-     { 
-         $id = (int) $id; 
-   
-         // Check the id and code match 
-         $q = "SELECT email 
-             FROM ~content_subscriptions 
-             WHERE id = ? AND code = ? 
-             LIMIT 1"; 
-         try { 
-             $email = Pdb::q($q, [$id, $code], 'val'); 
-         } catch (RowMissingException $ex) { 
-             Notification::error('Invalid id or unsubscription code'); 
-             Url::redirect('result/error'); 
-         } 
-   
-         // Fetch all of the subscriptions for this email address. 
-         // Codes are derived from the email address so they'll all be the same. 
-         $q = "SELECT id, handler_class, handler_settings 
-             FROM ~content_subscriptions 
-             WHERE code = ? AND email = ? 
-             ORDER BY id"; 
-         $res = Pdb::q($q, [$code, $email], 'arr'); 
-   
-         foreach ($res as $row) { 
-             // Create instance 
-             $inst = Sprout::instance($row['handler_class'], 'Sprout\\Helpers\\Subscribe'); 
-   
-             // Load settings 
-             $settings = json_decode($row['handler_settings'], true); 
-             if (!is_array($settings)) $settings = []; 
-   
-             // Get the name 
-             $result = $inst->getName($settings); 
-             if (! $result) continue; 
-   
-             $subs[$row['id']] = $result; 
-         } 
-   
-         $view = new View('sprout/content_unsubscribe_form'); 
-         $view->subscriptions = $subs; 
-         $view->id = $id; 
-         $view->code = $code; 
-   
-         $page_view = new View('skin/inner'); 
-         $page_view->page_title = 'Unsubscribe'; 
-         $page_view->main_content = $view; 
-         $page_view->controller_name = $this->getCssClassName(); 
-         echo $page_view->render(); 
-     } 
-   
-   
-     /** 
-     * Unsubscribe a user from a subscription (action) 
-     **/ 
-     public function unsubAction($id, $code) 
-     { 
-         $id = (int) $id; 
-   
-         // Check the id and code match 
-         $q = "SELECT email 
-             FROM ~content_subscriptions 
-             WHERE id = ? AND code = ? 
-             LIMIT 1"; 
-         try { 
-             $email = Pdb::q($q, [$id, $code], 'row'); 
-         } catch (RowMissingException $ex) { 
-             Notification::error('Invalid id or unsubscription code'); 
-             Url::redirect('result/error'); 
-         } 
-   
-         // Did they actually choose anything? 
-         if (empty($_POST['unsubscribe'])) { 
-             Notification::error('You didn\'t select anything'); 
-             Url::redirect("content_subscribe/unsub/{$id}/{$code}"); 
-         } 
-   
-         // Fetch the IDs of all of the subscriptions for this email address. 
-         // Codes are derived from the email address so they'll all be the same. 
-         $q = "SELECT id 
-             FROM ~content_subscriptions 
-             WHERE code = ? AND email = ?"; 
-         $ids = Pdb::q($q, [$code, $email], 'col'); 
-   
-         // Now we can iterate over the unsubscriptions, and remove them 
-         foreach ($_POST['unsubscribe'] as $id) { 
-   
-             Pdb::delete('content_subscriptions', ['id' => $id]); 
-         } 
-   
-         Notification::confirm('You have been unsubscribed'); 
-         Url::redirect('result/error'); 
-     } 
-   
-   
-     /** 
-     * Send the content subscription emails to the users who have registered 
-     **/ 
-     public function cronSendSubscriptions() 
-     { 
-         Cron::start("Content subscribe"); 
-   
-         Cron::message('Fetching subscriptions'); 
-   
-         $q = 'SELECT id, content_id, name, code, mobile FROM ~subsites'; 
-         $subsites = Pdb::query($q, [], 'arr'); 
-   
-         foreach ($subsites as $subsite) { 
-             Cron::message(''); 
-             Cron::message(''); 
-             Cron::message('Subscriptions for subsite: ' . $subsite['name']); 
-   
-             // Fake the subsite selection so that the subscription handlers and email sending all behaves correctly 
-             SubsiteSelector::$subsite_id = $subsite['id']; 
-             SubsiteSelector::$content_id = $subsite['content_id'] ?: $subsite['id']; 
-             SubsiteSelector::$subsite_code = $subsite['code']; 
-             SubsiteSelector::$mobile = $subsite['mobile']; 
-   
-             // Get the records 
-             $q = "SELECT id, code, handler_class, handler_settings, name, email, subsite_id 
-                 FROM ~content_subscriptions 
-                 WHERE subsite_id = ? 
-                 ORDER BY id"; 
-             $res = Pdb::q($q, [$subsite['id']], 'pdo'); 
-   
-             // TODO: should this be per subscription or should be store when it last ran? 
-   
-             Cron::message('Loading lists'); 
-   
-             // Get a unique list of class/settings 
-             foreach ($res as $row) { 
-   
-                 if (!isset($users[$row['email']])) { 
-                     $users[$row['email']] = array( 
-                         'id' => $row['id'], 
-                         'code' => $row['code'], 
-                         'name' => $row['name'], 
-                     ); 
-                 } 
-   
-                 $users[$row['email']]['subs'][] = md5($row['handler_class'] . '.' . $row['handler_settings']); 
-   
-                 $key = md5($row['handler_class'] . '.' . $row['handler_settings']); 
-                 if (isset($lists[$key])) continue; 
-   
-                 $class = $row['handler_class']; 
-   
-                 // Create class instance 
-                 try { 
-                     $inst = Sprout::instance($class, 'Sprout\\Helpers\\Subscribe'); 
-                 } catch (InvalidArgumentException $ex) { 
-                     Cron::message("    Loading '{$class}' failed: {$ex->getMessage()}"); 
-                     continue; 
-                 } 
-   
-                 // Load settings 
-                 $settings = json_decode($row['handler_settings'], true); 
-                 if (!is_array($settings)) $settings = []; 
-   
-                 // Run method to fetch items 
-                 try { 
-                     $result = $inst->getList($settings, $since); 
-                     if (! is_array($result)) throw new-  Exception ("Returned result is not an array");
 
-   
-                 } catch (Exception $ex) { 
-                     Cron::message("    Loading '{$class}' failed: {$ex->getMessage()}"); 
-                     continue; 
-                 } 
-   
-                 Cron ::message("    Loaded '{$class}'; Key '{$key}'; Num rows: " . count($result));
-   
-                 // Set the URL as the key for each item 
-                 // This prevents duplicates when the items are sent out 
-                 foreach ($result as $row) { 
-                     $uniq_result[$row['url']] = $row; 
-                 } 
-   
-                 // Save result 
-                 $lists[$key] = $uniq_result; 
-             } 
-   
-             Cron::message(''); 
-             Cron::message('Building user lists'); 
-   
-             $res->closeCursor(); 
-   
-             Cron ::message('Num users: ' . count($users));
-             Cron::message(''); 
-   
-             // For each user, build, sort and send out the lists 
-             $none = 0; 
-             $success = 0; 
-             $failure = 0; 
-             foreach ($users as $email => $deets) { 
-                 foreach ($deets['subs'] as $listkey) { 
-                     if ($lists[$listkey]) { 
-                     } 
-                 } 
-   
-                 if (count($items) == 0) { 
-                     $none++; 
-                     continue; 
-                 } 
-   
-                 usort($items, 'Sprout\\Helpers\\ContentSubscribe::tsSort'); 
-   
-                 foreach ($items as &$row) { 
-                     if ($row['url'][0] == '/') { 
-                         $row['url'] =-  Subsites ::getAbsRoot($subsite['id']) . ltrim($row['url'], '/');
 
-                     } 
-                 } 
-   
-                 $subsite_title = Subsites::getConfig('site_title', $subsite['id']); 
-   
-                 $view = new View('sprout/email/content_subscribe'); 
-                 $view->unsubscribe_url = Subsites::getAbsRoot($subsite['id']) . "content_subscribe/unsub/{$deets['id']}/{$deets['code']}"; 
-                 $view->name = $deets['name']; 
-                 $view->email = $email; 
-                 $view->items = $items; 
-                 $view->subsite_title = $subsite_title; 
-   
-                 $mail = new Email(); 
-                 $mail->AddAddress($email); 
-                 $mail->Subject = 'Updates on the ' . $subsite_title . ' website'; 
-                 $mail->SkinnedHTML($view->render()); 
-                 $result = $mail->Send(); 
-   
-                 Cron::message($email . ($result ? '; success' : '; failure')); 
-   
-                 if ($result) { $success++; } else { $failure++; } 
-             } 
-         } 
-   
-         if (!$success and $failure) { 
-             Cron::failure('All emails we tried to send failed; is there a server config error?'); 
-         } 
-   
-         if ($success or $failure) { 
-             Cron::message(''); 
-         } 
-   
-         Cron::message(''); 
-         Cron::message('No items:  ' . $none); 
-         Cron::message('Success:   ' . $success); 
-         Cron::message('Failed:    ' . $failure); 
-   
-         Cron::success(); 
-     } 
-   
-   
-     /** 
-     * Tool to clean up subscriptions which refer to classes that don't exist. 
-     **/ 
-     public function cleanupInvalidClasses() 
-     { 
-         AdminAuth::checkLogin(); 
-   
-         // Get the records 
-         $q = "SELECT handler_class 
-             FROM ~content_subscriptions 
-             GROUP BY handler_class 
-             ORDER BY handler_class"; 
-         $res = Pdb::q($q, [], 'arr'); 
-   
-         echo '<pre>'; 
-   
-         if (! $_GET['delete']) { 
-             echo 'Not deleting, use GET param delete=1 to delete categories.', PHP_EOL, PHP_EOL; 
-         } else { 
-             echo 'Deleting invalid subscriptions, if found.', PHP_EOL, PHP_EOL; 
-         } 
-   
-         foreach ($res as $row) { 
-             $delete = false; 
-   
-                 echo '<span style="color: #090;">[Found  ] ', Enc::html($row['handler_class']), '</span>', PHP_EOL; 
-             } else { 
-                 echo '<span style="color: #900;">[MISSING] ', Enc::html($row['handler_class']), '</span>', PHP_EOL; 
-                 $delete = true; 
-             } 
-   
-             if ($_GET['delete'] and $delete) { 
-                 Pdb::delete('content_subscriptions', ['handler_class' => $row['handler_class']]); 
-                 echo '<span style="color: #090;">[Deleted] ', Enc::html($row['handler_class']), '</span>', PHP_EOL; 
-             } 
-         } 
-   
-         echo '</pre>'; 
-     } 
-   
- } 
-