/** * This is the Ajax function that is called with the results of the * form supplied by news_<user/admin>_new() to create a new draft item * The following parameters are received in an array 'story'! * * @param string 'title' the title of the news item * * @author Erik Spaan * @return array(output, etc) with output being a rendered template or a simple text and action the performed action */ public function savedraft() { $this->checkAjaxToken(); $story = $this->request->getPost()->get('story', null); // cannot process file inputs (pictures) via ajax // File inputs are skipped as they cannot be serialized and sent using only JavaScript. // @see http://api.prototypejs.org/dom/Form/serialize/ // @see http://www.openjs.com/articles/ajax/ajax_file_upload/ $output = ''; $slug = ''; $fullpermalink = ''; $showslugedit = false; // Validate the input $validationerror = News_Util::validateArticle($story); // check hooked modules for validation $sid = isset($story['sid']) ? $story['sid'] : null; $hookvalidators = $this->notifyHooks('news.ui_hooks.articles.validate_edit', $story, $sid, array(), new Zikula_Hook_ValidationProviders())->getData(); if ($hookvalidators->hasErrors()) { $validationerror .= $this->__('Error! Hooked content does not validate.') . "\n"; } if ($validationerror) { return new Zikula_Response_Ajax_BadData($validationerror); } $newitem = array( 'sid' => isset($story['sid']) ? $story['sid'] : null, 'title' => $story['title'], 'urltitle' => isset($story['urltitle']) ? $story['urltitle'] : '', '__CATEGORIES__' => isset($story['__CATEGORIES__']) ? $story['__CATEGORIES__'] : null, '__ATTRIBUTES__' => isset($story['attributes']) ? News_Util::reformatAttributes($story['attributes']) : null, 'language' => isset($story['language']) ? $story['language'] : '', 'hometext' => isset($story['hometext']) ? $story['hometext'] : '', 'hometextcontenttype' => $story['hometextcontenttype'], 'bodytext' => isset($story['bodytext']) ? $story['bodytext'] : '', 'bodytextcontenttype' => $story['bodytextcontenttype'], 'notes' => isset($story['notes']) ? $story['notes'] : '', 'displayonindex' => isset($story['displayonindex']) ? $story['displayonindex'] : 0, 'allowcomments' => isset($story['allowcomments']) ? $story['allowcomments'] : 0, 'from' => isset($story['from']) ? $story['from'] : null, 'tonolimit' => isset($story['tonolimit']) ? $story['tonolimit'] : null, 'to' => isset($story['to']) ? $story['to'] : null, 'unlimited' => isset($story['unlimited']) && $story['unlimited'] ? true : false, 'weight' => isset($story['weight']) ? $story['weight'] : 0, 'tempfiles' => isset($story['tempfiles']) ? $story['tempfiles'] : null, 'pictures' => isset($story['pictures']) ? $story['pictures'] : 0, 'del_pictures' => isset($story['del_pictures']) ? $story['del_pictures'] : null, 'published_status' => isset($story['published_status']) ? $story['published_status'] : News_Api_User::STATUS_DRAFT, ); // get all module vars $modvars = $this->getVars(); // Check if the article is already saved as draft if (isset($story['sid']) && $story['sid'] > 0) { // Get the current news article $item = ModUtil::apiFunc('News', 'User', 'get', array('sid' => $story['sid'])); if ($item == false) { throw new Zikula_Exception_NotFound($this->__('Error! No such article found.')); } // Security check $this->throwForbiddenUnless(SecurityUtil::checkPermission('News::', "{$item['cr_uid']}::{$story['sid']}", ACCESS_EDIT)); if (!ModUtil::apiFunc('News', 'admin', 'update', $newitem)) { $output = DataUtil::formatForDisplayHTML($this->__('Error! Could not save your changes.')); } else { $output = $this->__f('Draft updated at %s', DateUtil::getDatetime_Time('', '%H:%M')); // Return the permalink (domain shortened) and the slug of the permalink $slug = $item['urltitle']; $fullpermalink = DataUtil::formatForDisplayHTML(ModUtil::url('News', 'user', 'display', array('sid' => $story['sid']))); // Only show "edit the slug" if the shorturls are active $showslugedit = (System::getVar('shorturls', false)); } $sid = $story['sid']; } else { // Create a first draft version of the story $sid = ModUtil::apiFunc('News', 'User', 'create', $newitem); if (!empty($sid)) { // Success and now reload the news story $item = ModUtil::apiFunc('News', 'User', 'get', array('sid' => $sid)); if ($item == false) { throw new Zikula_Exception_NotFound($this->__('Error! No such article found.')); } else { // Return the Draft creation date $output = $this->__f('Draft saved at %s', DateUtil::getDatetime_Time($item['cr_date'], '%H:%M')); // Return the permalink (domain shortened) and the slug of the permalink $slug = $item['urltitle']; $fullpermalink = DataUtil::formatForDisplayHTML(ModUtil::url('News', 'user', 'display', array('sid' => $sid))); // Only show "edit the slug" if the shorturls are active $showslugedit = (System::getVar('shorturls', false)); } } else { $output = DataUtil::formatForDisplayHTML($this->__('Error! Could not save your changes.')); } } //lock the page so others cannot edit it if (ModUtil::available('PageLock')) { $returnUrl = ModUtil::url('News', 'admin', 'view'); ModUtil::apiFunc('PageLock', 'user', 'pageLock', array( 'lockName' => "Newsnews{$sid}", 'returnUrl' => $returnUrl)); } return new Zikula_Response_Ajax(array( 'result' => $output, 'sid' => $sid, 'slug' => $slug, 'fullpermalink' => $fullpermalink, 'showslugedit' => $showslugedit)); }
/** * This is a standard function that is called with the results of the * form supplied by News_admin_newitem() or News_user_newitem to create * a new item. * * @author Mark West * @param string 'title' the title of the news item * @param string 'language' the language of the news item * @param string 'hometext' the summary text of the news item * @param int 'hometextcontenttype' the content type of the summary text * @param string 'bodytext' the body text of the news item * @param int 'bodytextcontenttype' the content type of the body text * @param string 'notes' any administrator notes * @param int 'published_status' the published status of the item * @param int 'displayonindex' display the article on the index page * @return bool true */ public function create($args) { // Get parameters from whatever input we need $story = FormUtil::getPassedValue('story', isset($args['story']) ? $args['story'] : null, 'POST'); $files = News_ImageUtil::reArrayFiles(FormUtil::getPassedValue('news_files', null, 'FILES')); // Create the item array for processing $item = array( 'title' => $story['title'], 'urltitle' => isset($story['urltitle']) ? $story['urltitle'] : '', '__CATEGORIES__' => isset($story['__CATEGORIES__']) ? $story['__CATEGORIES__'] : null, '__ATTRIBUTES__' => isset($story['attributes']) ? News_Util::reformatAttributes($story['attributes']) : null, 'language' => isset($story['language']) ? $story['language'] : '', 'hometext' => isset($story['hometext']) ? $story['hometext'] : '', 'hometextcontenttype' => $story['hometextcontenttype'], 'bodytext' => isset($story['bodytext']) ? $story['bodytext'] : '', 'bodytextcontenttype' => $story['bodytextcontenttype'], 'notes' => $story['notes'], 'displayonindex' => isset($story['displayonindex']) ? $story['displayonindex'] : 0, 'allowcomments' => isset($story['allowcomments']) ? $story['allowcomments'] : 0, 'from' => isset($story['from']) ? $story['from'] : null, 'tonolimit' => isset($story['tonolimit']) ? $story['tonolimit'] : null, 'to' => isset($story['to']) ? $story['to'] : null, 'unlimited' => isset($story['unlimited']) && $story['unlimited'] ? true : false, 'weight' => isset($story['weight']) ? $story['weight'] : 0, 'action' => isset($story['action']) ? $story['action'] : self::ACTION_PREVIEW, 'sid' => isset($story['sid']) ? $story['sid'] : null, 'tempfiles' => isset($story['tempfiles']) ? $story['tempfiles'] : null, 'del_pictures' => isset($story['del_pictures']) ? $story['del_pictures'] : null, ); // convert user times to server times (TZ compensation) refs #181 // can't do the below because values are YYYY-MM-DD HH:MM:SS and DateUtil value is in seconds. // $item['from'] = $item['from'] + DateUtil::getTimezoneUserDiff(); // $item['to'] = $item['to'] + DateUtil::getTimezoneUserDiff(); // Disable the non accessible fields for non editors if (!SecurityUtil::checkPermission('News::', '::', ACCESS_ADD)) { $item['notes'] = ''; $item['displayonindex'] = 1; $item['allowcomments'] = 1; $item['from'] = null; $item['tonolimit'] = true; $item['to'] = null; $item['unlimited'] = true; $item['weight'] = 0; if ($item['action'] > self::ACTION_SUBMIT) { $item['action'] = self::ACTION_PREVIEW; } } // Validate the input $validationerror = News_Util::validateArticle($item); // check hooked modules for validation $sid = isset($item['sid']) ? $item['sid'] : null; $hookvalidators = $this->notifyHooks(new Zikula_ValidationHook('news.ui_hooks.articles.validate_edit', new Zikula_Hook_ValidationProviders()))->getValidators(); if ($hookvalidators->hasErrors()) { $validationerror .= $this->__('Error! Hooked content does not validate.') . "\n"; } // get all module vars $modvars = $this->getVars(); if (isset($files) && $modvars['picupload_enabled']) { list($files, $item) = News_ImageUtil::validateImages($files, $item); } else { $item['pictures'] = 0; } // story was previewed with uploaded pics if (isset($item['tempfiles'])) { $tempfiles = unserialize($item['tempfiles']); // delete files if requested if (isset($item['del_pictures'])) { foreach ($tempfiles as $key => $file) { if (in_array($file['name'], $item['del_pictures'])) { unset($tempfiles[$key]); News_ImageUtil::removePreviewImages(array($file)); } } } $files = array_merge($files, $tempfiles); $item['pictures'] += count($tempfiles); } // if the user has selected to preview the article we then route them back // to the new function with the arguments passed here if ($item['action'] == self::ACTION_PREVIEW || $validationerror !== false) { // log the error found if any if ($validationerror !== false) { LogUtil::registerError(nl2br($validationerror)); } if ($item['pictures'] > 0) { $tempfiles = News_ImageUtil::tempStore($files); $item['tempfiles'] = serialize($tempfiles); } // back to the referer form SessionUtil::setVar('newsitem', $item); $this->redirect(ModUtil::url('News', 'user', 'newitem')); } else { // As we're not previewing the item let's remove it from the session SessionUtil::delVar('newsitem'); } // Confirm authorization code. $this->checkCsrfToken(); if (!isset($item['sid']) || empty($item['sid'])) { // Create the news story $sid = ModUtil::apiFunc('News', 'user', 'create', $item); if ($sid != false) { // Success LogUtil::registerStatus($this->__('Done! Created new article.')); // Let any hooks know that we have created a new item $this->notifyHooks(new Zikula_ProcessHook('news.ui_hooks.articles.process_edit', $sid, new Zikula_ModUrl('News', 'User', 'display', ZLanguage::getLanguageCode(), array('sid' => $sid)))); $this->notify($item); // send notification email } else { // fail! story not created throw new Zikula_Exception_Fatal($this->__('Story not created for unknown reason (Api failure).')); return false; } } else { // update the draft $result = ModUtil::apiFunc('News', 'admin', 'update', $item); if ($result) { LogUtil::registerStatus($this->__('Story Updated.')); } else { // fail! story not updated throw new Zikula_Exception_Fatal($this->__('Story not updated for unknown reason (Api failure).')); return false; } } // clear respective cache ModUtil::apiFunc('News', 'user', 'clearItemCache', $item); if (isset($files) && $modvars['picupload_enabled']) { $resized = News_ImageUtil::resizeImages($sid, $files); // resize and move the uploaded pics if (isset($item['tempfiles'])) { News_ImageUtil::removePreviewImages($tempfiles); // remove any preview images } LogUtil::registerStatus($this->_fn('%1$s out of %2$s picture was uploaded and resized.', '%1$s out of %2$s pictures were uploaded and resized.', $item['pictures'], array($resized, $item['pictures']))); if (($item['action'] >= self::ACTION_SAVEDRAFT) && ($resized <> $item['pictures'])) { LogUtil::registerStatus($this->_fn('Article now has draft status, since the picture was not uploaded.', 'Article now has draft status, since not all pictures were uploaded.', $item['pictures'], array($resized, $item['pictures']))); } } // release pagelock if (ModUtil::available('PageLock')) { ModUtil::apiFunc('PageLock', 'user', 'releaseLock', array('lockName' => "Newsnews{$item['sid']}")); } if ($item['action'] == self::ACTION_SAVEDRAFT_RETURN) { SessionUtil::setVar('newsitem', $item); $this->redirect(ModUtil::url('News', 'user', 'newitem')); } $this->redirect(ModUtil::url('News', 'user', 'view')); }
/** * view items * @param int 'startnum' starting number for paged output * @author Mark West * @return string HTML string */ public function view($args) { $this->throwForbiddenUnless(SecurityUtil::checkPermission('News::', '::', ACCESS_EDIT), LogUtil::getErrorMsgPermission()); // initialize sort array - used to display sort classes and urls $sort = array(); $fields = array('sid', 'weight', 'from'); // possible sort fields foreach ($fields as $field) { $sort['class'][$field] = 'z-order-unsorted'; // default values } $startnum = FormUtil::getPassedValue('startnum', isset($args['startnum']) ? $args['startnum'] : null, 'GETPOST'); $news_status = FormUtil::getPassedValue('news_status', isset($args['news_status']) ? $args['news_status'] : null, 'GETPOST'); $language = FormUtil::getPassedValue('news_language', isset($args['news_language']) ? $args['news_language'] : null, 'GETPOST'); $purge = FormUtil::getPassedValue('purge', false, 'GET'); $order = FormUtil::getPassedValue('order', isset($args['order']) ? $args['order'] : 'from', 'GETPOST'); $original_sdir = FormUtil::getPassedValue('sdir', isset($args['sdir']) ? $args['sdir'] : 1, 'GETPOST'); $this->view->assign('startnum', $startnum); $this->view->assign('order', $order); $this->view->assign('sdir', $original_sdir); $this->view->assign('selected_language', (isset($language)) ? $language : ''); $sdir = $original_sdir ? 0 : 1; //if true change to false, if false change to true // change class for selected 'orderby' field to asc/desc if ($sdir == 0) { $sort['class'][$order] = 'z-order-desc'; $orderdir = 'DESC'; } if ($sdir == 1) { $sort['class'][$order] = 'z-order-asc'; $orderdir = 'ASC'; } $filtercats = FormUtil::getPassedValue('news', null, 'GETPOST'); $filtercats_serialized = FormUtil::getPassedValue('filtercats_serialized', false, 'GET'); $filtercats = $filtercats_serialized ? unserialize($filtercats_serialized) : $filtercats; $catsarray = News_Util::formatCategoryFilter($filtercats); // complete initialization of sort array, adding urls foreach ($fields as $field) { $sort['url'][$field] = ModUtil::url('News', 'admin', 'view', array( 'news_status' => $news_status, 'news_language' => $language, 'filtercats_serialized' => serialize($filtercats), 'order' => $field, 'sdir' => $sdir)); } $this->view->assign('sort', $sort); $this->view->assign('filter_active', (!isset($language) && !isset($news_status) && empty($filtercats)) ? false : true); if ($purge) { if (ModUtil::apiFunc('News', 'admin', 'purgepermalinks')) { LogUtil::registerStatus($this->__('Done! Purged permalinks.')); } else { LogUtil::registerError($this->__('Error! Could not purge permalinks.')); } return $this->redirect(strpos(System::serverGetVar('HTTP_REFERER'), 'purge') ? ModUtil::url('News', 'admin', 'view') : System::serverGetVar('HTTP_REFERER')); } // clean the session preview data SessionUtil::delVar('newsitem'); // get module vars for later use $modvars = $this->getVars(); if ($modvars['enablecategorization']) { $catregistry = CategoryRegistryUtil::getRegisteredModuleCategories('News', 'news'); $this->view->assign('catregistry', $catregistry); } $multilingual = System::getVar('multilingual', false); $now = DateUtil::getDatetime(); $status = null; if (isset($news_status) && $news_status != '') { if ($news_status == 0) { $status = 0; $to = $now; } elseif ($news_status == 5) { // scheduled is actually the published status, but in the future $status = 0; $from = $now; } else { $status = $news_status; } } // Get all news stories $getallargs = array('startnum' => $startnum, 'status' => $status, 'numitems' => $modvars['itemsperadminpage'], 'ignoreml' => true, 'language' => $language, 'order' => isset($order) ? $order : 'from', 'orderdir' => isset($orderdir) ? $orderdir : 'DESC', 'from' => isset($from) ? $from : null, 'to' => isset($to) ? $to : null, 'filterbydate' => false, 'category' => null, 'catfilter' => isset($catsarray) ? $catsarray : null, 'catregistry' => isset($catregistry) ? $catregistry : null); $items = ModUtil::apiFunc('News', 'user', 'getall', $getallargs); $total_articles = ModUtil::apiFunc('News', 'user', 'countitems', $getallargs); // Set the possible status for later use $itemstatus = array( '' => $this->__('All'), News_Api_User::STATUS_PUBLISHED => $this->__('Published'), News_Api_User::STATUS_REJECTED => $this->__('Rejected'), News_Api_User::STATUS_PENDING => $this->__('Pending Review'), News_Api_User::STATUS_ARCHIVED => $this->__('Archived'), News_Api_User::STATUS_DRAFT => $this->__('Draft'), News_Api_User::STATUS_SCHEDULED => $this->__('Scheduled') ); $newsitems = array(); foreach ($items as $item) { $options = array(); if (System::getVar('shorturls', false)) { $options[] = array('url' => ModUtil::url('News', 'user', 'display', array('sid' => $item['sid'], 'from' => $item['from'], 'urltitle' => $item['urltitle'])), 'image' => '14_layer_visible.png', 'title' => $this->__('View')); } else { $options[] = array('url' => ModUtil::url('News', 'user', 'display', array('sid' => $item['sid'])), 'image' => '14_layer_visible.png', 'title' => $this->__('View')); } if (SecurityUtil::checkPermission('News::', "{$item['cr_uid']}::{$item['sid']}", ACCESS_EDIT)) { if ($item['published_status'] == News_Api_User::STATUS_PENDING) { $options[] = array('url' => ModUtil::url('News', 'admin', 'modify', array('sid' => $item['sid'])), 'image' => 'editcut.png', 'title' => $this->__('Review')); } else { $options[] = array('url' => ModUtil::url('News', 'admin', 'modify', array('sid' => $item['sid'])), 'image' => 'xedit.png', 'title' => $this->__('Edit')); } if (($item['published_status'] != News_Api_User::STATUS_PENDING && (SecurityUtil::checkPermission('News::', "{$item['cr_uid']}::{$item['sid']}", ACCESS_DELETE))) || SecurityUtil::checkPermission('News::', "{$item['cr_uid']}::{$item['sid']}", ACCESS_ADMIN)) { $options[] = array('url' => ModUtil::url('News', 'admin', 'delete', array('sid' => $item['sid'])), 'image' => '14_layer_deletelayer.png', 'title' => $this->__('Delete')); } } $item['options'] = $options; if (in_array($item['published_status'], array_keys($itemstatus))) { $item['status'] = $itemstatus[$item['published_status']]; } else { $item['status'] = $this->__('Unknown'); } $item['infuture'] = DateUtil::getDatetimeDiff_AsField($item['from'], DateUtil::getDatetime(), 6) < 0; $newsitems[] = $item; } // Assign the items to the template $this->view->assign('newsitems', $newsitems); $this->view->assign('total_articles', $total_articles); // Assign the current status filter and the possible ones $this->view->assign('news_status', $news_status); $this->view->assign('itemstatus', $itemstatus); $this->view->assign('order', $order); $selectedcategories = array(); if (is_array($filtercats)) { $catsarray = $filtercats['__CATEGORIES__']; foreach ($catsarray as $propname => $propid) { if ($propid > 0) { $selectedcategories[$propname] = $propid; // removes categories set to 'all' } } } $this->view->assign('selectedcategories', $selectedcategories); // Return the output that has been generated by this function return $this->view->fetch('admin/view.tpl'); }