public function executeStep3(sfWebRequest $request) { if (PcUserPeer::getLoggedInUser()->hasGoogleCalendarIntegrationActive()) { $this->redirect('default', array('module' => 'main', 'action' => 'index')); } $googleCalendarInterface = new GoogleCalendarInterface(PcUserPeer::getLoggedInUser()); $googleCalendarInterface->init(); $calendars = $googleCalendarInterface->getAllCalendars(); $oldCalendarUrl = $googleCalendarInterface->getCalendarUrl(); $plancakeCalendarName = GoogleCalendarInterface::PLANCAKE_SPECIFIC_CALENDAR_NAME; $this->calendarAlreadyExist = false; foreach ($calendars as $calendar) { if ($calendar->title == $plancakeCalendarName || $calendar->content->src == $oldCalendarUrl) { $this->calendarAlreadyExist = true; break; } } }
public function executeScheduledTasksForTodo(sfWebRequest $request) { $loggedInUser = PcUserPeer::getLoggedInUser(); if ($loggedInUser->hasGoogleCalendarIntegrationActive()) { $gcal = new GoogleCalendarInterface($loggedInUser); $gcal->init(); $gcal->syncPlancake(); } include_once sfConfig::get('sf_root_dir') . '/apps/api/lib/PlancakeApiServer.class.php'; $apiVersion = sfConfig::get('app_api_version'); $doneParam = $request->getParameter('done'); $typeParam = $request->getParameter('type'); $extraParam = $request->getParameter('extraParam'); $filters = array(); $filters['list_id'] = $loggedInUser->getTodo()->getId(); $filters['only_with_due_date'] = 1; $tasks = PlancakeApiServer::getTasks(array_merge($filters, array('api_ver' => $apiVersion, 'camel_case_keys' => 1))); $tasks['tasks'] = array_reverse($tasks['tasks']); // to make them easier to show on the UI if ($request->isXmlHttpRequest()) { return $this->renderJson($tasks); } }
$authSubUrl = Zend_Gdata_AuthSub::getAuthSubTokenUri($next, $scope, $secure, $session); header("HTTP/1.0 307 Temporary redirect"); header("Location: " . $authSubUrl); exit; } else { try { $client = new Zend_Gdata_HttpClient(); $pathToKey = sfConfig::get('sf_root_dir') . '/' . sfConfig::get('app_googleCalendarIntegration_privateKeyPath'); $client->setAuthSubPrivateKeyFile($pathToKey, null, true); $sessionToken = Zend_Gdata_AuthSub::getAuthSubSessionToken($_GET['token'], $client); } catch (Exception $e) { sfErrorNotifier::alert("Google Calendar Init: " . $e->getMessage()); $this->redirect('default', array('module' => 'googleCalendarIntegration', 'action' => 'step3Error')); } $redirectUrl = ''; if ($sessionToken) { $loggedInUser = PcUserPeer::getLoggedInUser(); if ($loggedInUser) { $googleCalendarInterface = new GoogleCalendarInterface($loggedInUser); $googleCalendarInterface->resetDbEntry(); $googleCalendarInterface->setSessionToken($sessionToken); } $configuration->loadHelpers('Url'); $redirectUrl = 'http://' . sfConfig::get('app_site_url') . '/' . sfConfig::get('app_accountApp_frontController') . '/googleCalendarIntegration/step3'; } else { // something wrong $configuration->loadHelpers('Url'); $redirectUrl = 'http://' . sfConfig::get('app_site_url') . ($redirectUrl = 'http://' . sfConfig::get('app_site_url') . '/' . sfConfig::get('app_accountApp_frontController') . '/googleCalendarIntegration/step3Error'); } header("Location: {$redirectUrl}"); }
/** * Executes index action * * @param sfRequest $request A request object */ public function executeIndex(sfWebRequest $request) { // for performance reasons, we insert this configuration inside the method itself $methods = array('getToken', 'getServerTime', 'getUserSettings', 'getLists', 'getDeletedLists', 'getTags', 'getDeletedTags', 'getRepetitions', 'getRepetitionOptions', 'getTasks', 'getDeletedTasks', 'completeTask', 'uncompleteTask', 'deleteTask', 'addTask', 'editTask', 'setTaskNote', 'sync', 'whatHasChanged'); // token, sig, api_ver are required for each method $extraRequiredParamsMap = array('getToken' => array('api_key'), 'getServerTime' => array(), 'getUserSettings' => array(), 'getLists' => array(), 'getDeletedLists' => array('from_ts', 'to_ts'), 'getTags' => array(), 'getDeletedTags' => array('from_ts', 'to_ts'), 'getRepetitions' => array(), 'getRepetitionOptions' => array(), 'getTasks' => array(), 'getDeletedTasks' => array('from_ts', 'to_ts'), 'completeTask' => array('task_id'), 'uncompleteTask' => array('task_id'), 'addTask' => array('descr'), 'editTask' => array('task_id'), 'setTaskNote' => array('task_id', 'note'), 'deleteTask' => array('task_id'), 'sync' => array('local_changes'), 'whatHasChanged' => array('from_ts', 'to_ts')); $optionalParamsMap = array('getToken' => array('user_key', 'user_email', 'user_pwd', 'extra_info'), 'getServerTime' => array(), 'getUserSettings' => array(), 'getLists' => array('from_ts', 'to_ts'), 'getDeletedLists' => array(), 'getTags' => array('from_ts', 'to_ts'), 'getDeletedTags' => array(), 'getRepetitions' => array('from_ts', 'to_ts'), 'getRepetitionOptions' => array('from_ts', 'to_ts'), 'getTasks' => array('from_ts', 'to_ts', 'task_id', 'list_id', 'tag_id', 'completed', 'only_with_due_date', 'only_without_due_date', 'only_due_today_or_tomorrow', 'only_starred', 'by_date', 'search_query'), 'getDeletedTasks' => array(), 'completeTask' => array('baseline_due_date'), 'uncompleteTask' => array(), 'addTask' => array('list_id', 'is_header', 'due_date', 'due_time', 'is_starred', 'repetition_id', 'repetition_param', 'repetition_ical_rrule', 'note', 'tag_ids'), 'editTask' => array('list_id', 'descr', 'is_header', 'due_date', 'due_time', 'is_starred', 'repetition_id', 'repetition_param', 'repetition_ical_rrule', 'note', 'tag_ids'), 'setTaskNote' => array(), 'deleteTask' => array(), 'sync' => array(), 'whatHasChanged' => array()); $methodName = $request->getParameter('method_name'); $token = $request->getParameter('token'); $sig = $request->getParameter('sig'); $apiVersion = $request->getParameter('api_ver'); if (!in_array($methodName, $methods)) { return $this->returnError(PlancakeApiServer::INVALID_METHOD_ERROR); } $this->methodName = $methodName; if ($token === null) { return $this->returnError(PlancakeApiServer::MISSING_TOKEN_ERROR); } if (!$sig) { return $this->returnError(PlancakeApiServer::MISSING_SIGNATURE_ERROR); } if (!$apiVersion) { return $this->returnError(PlancakeApiServer::MISSING_API_VERSION); } $params = array(); $params['token'] = $token; $params['sig'] = $sig; $params['api_ver'] = $apiVersion; $extraRequiredParams = $extraRequiredParamsMap[$methodName]; foreach ($extraRequiredParams as $extraRequiredParam) { $paramValue = $request->getParameter($extraRequiredParam); if ($paramValue !== null) { $params[$extraRequiredParam] = $paramValue; } else { return $this->returnError(PlancakeApiServer::MISSING_PARAMETER_ERROR); } } if (!$this->isTokenValid($token)) { return $this->returnError(PlancakeApiServer::INVALID_TOKEN_ERROR); } $apiKey = isset($params['api_key']) ? $params['api_key'] : null; $apiApp = $this->getApiApp($params['token'], $apiKey); if ($apiApp === null) { return $this->returnError(PlancakeApiServer::INVALID_API_KEY_OR_TOKEN_ERROR); } if ($apiApp->isLimited()) { if ($apiApp->hasReachedLimits()) { return $this->returnError(PlancakeApiServer::RATE_LIMIT_REACHED); } } $apiSecret = $apiApp->getApiSecret(); // loading optional params $optionalParams = $optionalParamsMap[$methodName]; foreach ($optionalParams as $optionalParam) { $paramValue = $request->getParameter($optionalParam); if ($paramValue !== null) { $params[$optionalParam] = $paramValue; } } // if from_ts is specified, also to_ts if (isset($params['from_ts']) && !isset($params['to_ts']) || isset($params['to_ts']) && !isset($params['from_ts']) || isset($params['from_ts']) && isset($params['from_ts']) && !((int) $params['from_ts'] > 0) || isset($params['from_ts']) && isset($params['from_ts']) && !((int) $params['to_ts'] > 0)) { return $this->returnError(PlancakeApiServer::MISSING_FROMTS_OR_TOTS_PARAMETER_ERROR); } if (!(strlen($apiSecret) > 0)) { return $this->returnError(PlancakeApiServer::INVALID_API_KEY_ERROR); } if (!$this->isSignatureValid($params, $apiSecret)) { return $this->returnError(PlancakeApiServer::INVALID_SIGNATURE_ERROR); } $user = null; if (strlen($token) > 0) { $userId = PcApiTokenPeer::retrieveByPK($token)->getUserId(); $user = PcUserPeer::retrieveByPK($userId); PcUserPeer::setLoggedInUser($user); $user->refreshLastLogin()->save(); } unset($params['token']); unset($params['sig']); $response = call_user_func(array('PlancakeApiServer', $methodName), $params); $jsonResponse = json_encode($response); $apiApp->recordStats(strlen($jsonResponse)); if ($user && $user->hasGoogleCalendarIntegrationActive()) { $gcalRecord = PcGoogleCalendarPeer::retrieveByUser($user); if ($gcalRecord && time() - $gcalRecord->getLatestSyncEndTimestamp() > sfConfig::get('app_api_googleCalendarSyncMinInterval')) { $gcal = new GoogleCalendarInterface($user); $gcal->init(); $gcal->syncPlancake(); } } if ($callback = $request->getParameter('callback')) { $this->getResponse()->setContentType('text/javascript'); $response = $callback . '(' . $jsonResponse . ')'; } else { $this->getResponse()->setContentType('application/json'); $response = $jsonResponse; } return $this->renderText($response); }
/** * Creates (or edits) a task * By default, it sets isFromSystem false. That is because a user may * edit a task from the system and make it meaningful to them. The problem * is the automatic cleaning up of system tasks would delete it. And this * method is used also when editing a task. * Repetition expression has got priority on dueDate * * @param string $description * @param integer $listId (if listId not >0, we will use the user's Inbox) * @param integer $taskId (if we are editing an existing task) * @param string $contexts (comma separated list of ids) * @param boolean $isHeader * @param string $note * @param string $dueDate (no GMT but user's local date) * @param string $dueTime - formatted as an integer, ie: 0753 (no GMT but user's local time) * @param integer $repetitionId * @param integer $repetitionParam * @param integer $taskAboveId - if ($taskAboveId = -100000), that means to put at the end of the list * @param string $callerContext - can be either 'ajax' or 'email' or 'gcal' * @param string $dueDateFormat - to specify a particular format for parsing the dueDate param * (otherwise the user's date format is used). * Uses the PHP date() format * @param boolean $setNextOccurrence (=true) * @return PcTask - the object that has been created */ public static function createOrEdit($description, $listId = 0, $taskId = 0, $contexts = '', $isHeader = false, $note = '', $dueDate = '', $dueTime = '', $isStarred = 0, $repetitionId = 0, $repetitionParam = 0, $taskAboveId = 0, $callerContext = '', $dueDateFormat = '', $setNextOccurrence = true) { $dueDate = strtolower($dueDate); $loggedInUser = PcUserPeer::getLoggedInUser(); if ($repetitionId < 0) { $repetitionId = 0; } if (!((int) $listId > 0)) { // Inserting into the default list: Inbox $listId = $loggedInUser->getInbox()->getId(); } $listCreator = PcListPeer::retrieveByPk($listId)->getCreator(); PcUtils::checkLoggedInUserPermission($listCreator); $mode = $taskId ? 'edit' : 'add'; $task = $mode == 'add' ? new PcTask() : PcTaskPeer::retrieveByPk($taskId); if ($mode == 'edit' && !$task->validateOwner($loggedInUser)) { throw new sfException('User ' . $loggedInUser->getId() . ' trying to access the task ' . $task->getId() . ' illegitimately'); } list($listIdFromShortcut, $contextIdsFromShortcut, $potentialDueDateExpressionsFromShortcut, $potentialDueTimeExpressionsFromShortcut) = $task->extractInfoFromTaskDescription($description); $listId = $listIdFromShortcut > 0 ? $listIdFromShortcut : $listId; // if we are here all the contexts (if any) are valid if (count($contextIdsFromShortcut)) { $task->setContexts(implode(',', $contextIdsFromShortcut)); } else { $userContexts = $loggedInUser->getContextsArray(true); $contextIdsFromInput = PcUtils::explodeWithEmptyInputDetection(',', $contexts); $validatedContexts = array(); foreach ($contextIdsFromInput as $cid) { $userContext = PcUsersContextsPeer::retrieveByPK($cid); if ($userContext) { $validatedContexts[] = array_search(strtolower($userContext->getContext()), $userContexts); } } $task->setContexts(implode(',', $validatedContexts)); } // {{{ START: looking for a contact $contactPrefix = 'cid'; if (strpos($description, $contactPrefix) !== FALSE) { if (preg_match('/' . $contactPrefix . '([0-9]+)/', $description, $contactArray)) { $description = str_replace($contactArray[0], '', $description); // removing the contact bit from the description if (is_numeric($contactArray[1])) { $task->setContactId($contactArray[1]); } } } // END: looking for a contact }}} $task->setDescription($description); // it is the actual content of the task if ($repetitionId == 34 && !($repetitionParam > 0)) { // $repetitionParam should have been > 0! $repetitionId = 0; } $oldRepetitionId = $task->getRepetitionId(); if ($repetitionId > 0) { $task->setRepetitionId($repetitionId); $task->setRepetitionParam($repetitionParam); } else { $task->setRepetitionId(NULL); $task->setRepetitionParam(0); } $changeInRepetitionId = false; if ($oldRepetitionId != $task->getRepetitionId()) { $changeInRepetitionId = true; } try { $task->setListId($listId); } catch (sfException $e) { if ($callerContext == 'ajax') { die('ERROR: You can\'t insert a task in a header.'); } } $task->setIsHeader($isHeader); if (!$isHeader) { $task->setNote($note); } else { $task->setDueDate(null); } $validDueDateExpression = false; $unrecognizedShortcuts = array(); if (count($potentialDueDateExpressionsFromShortcut) && !$isHeader) { foreach ($potentialDueDateExpressionsFromShortcut as $potentialDueDateExpressionFromShortcut) { $validDueDateExpression = $task->setDueDate($potentialDueDateExpressionFromShortcut); if (!$validDueDateExpression) { $unrecognizedShortcuts[] = $potentialDueDateExpressionFromShortcut; } else { $validDueDateExpression = true; break; } } } if (!$validDueDateExpression && $dueDate && !$isHeader) { $validDueDateExpression = $task->setDueDate($dueDate, $dueDateFormat); } if (!$task->getDueDate()) { $task->setDueDate(NULL); } if ($mode == 'add') { $list = $task->getPcList(); if (!$list) { // this should not happen, but just in case... $list = $loggedInUser->getInbox(); } if (!$taskAboveId) { $maxTasksSortOrder = self::getMaxTasksSortOrder($list); $task->setSortOrder($maxTasksSortOrder + 1); } else { if ($taskAboveId == -100000) { $minTasksSortOrder = self::getMinTasksSortOrder($list); $task->setSortOrder($minTasksSortOrder - 1); } else { $maxTasksSortOrder = self::getMaxTasksSortOrder($list); // they are inserting the new task below an old one // I need to insert the new task after the task whose id is beforeListId $allTasks = $list->getIncompletedTasks(); // the tasks are returned with sortOrder descending order // and the tasks are displayed with the greatest sortOrder on top $newSortOrder = $maxTasksSortOrder; foreach ($allTasks as $oneOfTheOtherTasks) { $delta = 1; if ($oneOfTheOtherTasks->getId() == $taskAboveId) { $task->setSortOrder($newSortOrder - 1); $delta++; } $oneOfTheOtherTasks->setSortOrder($newSortOrder); $oneOfTheOtherTasks->save(); $newSortOrder -= $delta; } } } } if (count($unrecognizedShortcuts)) { if ($callerContext == 'ajax') { die("ERROR: {$unrecognizedShortcuts[0]} is not a tag neither a valid due date/time expression."); } } if ($potentialDueTimeExpressionsFromShortcut && $callerContext == 'ajax') { if (!$potentialDueTimeExpressionsFromShortcut->isValid()) { die("ERROR: the due time shortcut is not valid."); } } if ($dueTime || $potentialDueTimeExpressionsFromShortcut) { // it doesn't make sense to set a time if a date is not specified if ($task->getDueDate() || $task->getRepetitionId()) { if ($dueTime) { $task->setDueTime($dueTime); } else { $task->setDueTime($potentialDueTimeExpressionsFromShortcut->getIntegerValue()); } } else { if ($callerContext == 'ajax') { die('ERROR: You can\'t set a due time without a due date.'); } else { // if the user tried to insert a due time shortcuts but we couldn't take // that value because there is no due date, we put the due time back in // the description if ($potentialDueTimeExpressionsFromShortcut) { $descriptionWithDueTimeEmbedded = $task->getDescription() . ' @' . $potentialDueTimeExpressionsFromShortcut->getHumanFriendlyTime($loggedInUser); $task->setDescription($descriptionWithDueTimeEmbedded); } } } } else { $task->setDueTime(null); } if (!$task->isHeader()) { $task->setStarred((bool) $isStarred); } $task->save(); if ($task->getRepetitionId() && $setNextOccurrence) { $task->setNextOccurrence(true); // N.B.: this saves the object!!!!!!! } // we need to do this operation here because we need the object // saved in the db to be able to refer to it via its ID $task->alignTasksContextsTable(); // {{{ // this is to fix a bug: // long task descriptions were cut (because of database schema contraint) // without a clear feedback on the user interface (Javascript was // inserting the whole string sent via AJAX) $task = PcTaskPeer::retrieveByPK($task->getId()); // }}} // This is VERY IMPRTANT because a user may // edit a task from the system and make it meaningful to them. The problem // is the automatic cleaning up of system tasks would delete it. And this // method is used also when editing a task. $task->setIsFromSystem(false); if ($loggedInUser->hasGoogleCalendarIntegrationActive()) { if ($callerContext != 'gcal') { $gcal = new GoogleCalendarInterface($loggedInUser); $gcal->init(); $gcal->createOrUpdateEvent($task); } } return $task; }
* Plancake is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Affero General Public License for more details. * * * * You should have received a copy of the GNU Affero General Public License * * along with this program. If not, see <http://www.gnu.org/licenses/>. * * * **************************************************************************************/ require_once dirname(__FILE__) . '/../../config/ProjectConfiguration.class.php'; $configuration = ProjectConfiguration::getApplicationConfiguration('account', 'prod', false); $context = sfContext::createInstance($configuration); require_once 'Zend/Loader.php'; Zend_Loader::loadClass('Zend_Gdata'); Zend_Loader::loadClass('Zend_Gdata_AuthSub'); Zend_Loader::loadClass('Zend_Gdata_ClientLogin'); Zend_Loader::loadClass('Zend_Gdata_Calendar'); $redirectUrl = ''; try { $googleCalender = new GoogleCalendarInterface(PcUserPeer::getLoggedInUser()); $googleCalender->init(); $googleCalender->import(PcTaskPeer::getIncompletedTasksWithDate()); $configuration->loadHelpers('Url'); $redirectUrl = 'http://' . sfConfig::get('app_site_url') . '/' . sfConfig::get('app_accountApp_frontController') . '/googleCalendarIntegration/step4'; } catch (Exception $e) { sfErrorNotifier::alert("Google Calendar Import: " . $e->getMessage()); error_log("Google Calendar Import: " . $e->getMessage()); $configuration->loadHelpers('Url'); $redirectUrl = 'http://' . sfConfig::get('app_site_url') . '/' . sfConfig::get('app_accountApp_frontController') . '/googleCalendarIntegration/step4Error'; } header("Location: {$redirectUrl}");
/** * Marks the tasks as incomplete */ public function markIncomplete() { $this->setIsCompleted(0); $this->setCompletedAt(NULL); $this->setCreatedAt(time()); // so it will be displayed at the end of the list after reloading $this->save(); $loggedInUser = PcUserPeer::getLoggedInUser(); if ($loggedInUser->hasGoogleCalendarIntegrationActive()) { $this->removeGoogleCalendarEventId(); // if we don't do this the integration // will try to edit a non-existing event on GCal, rather than creating a new one $gcal = new GoogleCalendarInterface($loggedInUser); $gcal->init(); $gcal->createOrUpdateEvent($this); } }