/** * Retrieves all saved reports that meet args-driven criteria * * @param $api ServiceBase The API class of the request * @param $args array The arguments array passed in from the API * @return array */ public function getSavedReports($api, $args) { // Make sure the user isn't seeing reports they don't have access to require_once 'modules/Reports/SavedReport.php'; $modules = array_keys(getACLDisAllowedModules()); $fieldList = array('id', 'name', 'module', 'report_type', 'content', 'chart_type', 'assigned_user_id'); $sq = new SugarQuery(); $sq->from(BeanFactory::getBean('Reports')); $sq->select($fieldList); $sq->orderBy('name', 'asc'); // if there were restricted modules, add those to the query if (count($modules)) { $sq->where()->notIn('module', $modules); } if (isset($args['has_charts']) && $args['has_charts'] == 'true') { $sq->where()->notEquals('chart_type', 'none'); } if (isset($args['module']) && $args['module'] !== '') { $sq->where()->in('module', array($args['module'])); } $result = $sq->execute(); // check acls foreach ($result as $key => &$row) { $savedReport = $this->getSavedReportFromData($row); if ($savedReport->ACLAccess('list')) { // for front-end to check acls $row['_acl'] = ApiHelper::getHelper($api, $savedReport)->getBeanAcl($savedReport, $fieldList); } else { unset($result[$key]); } } return $result; }
protected function populateFromApi($api, $bean, $args, $options = array()) { $errors = ApiHelper::getHelper($api, $bean)->populateFromApi($bean, $args, $options); // remove email_addr_bean_rel records created by SugarFieldEmail::apiSave() for new bean (empty id) if (empty($args['id']) && !empty($bean->emailAddress)) { $bean->emailAddress->deleteLinks($bean->id, $bean->module_dir); } return $errors; }
/** * Fetches data from the $args array and updates the bean with that data * @param $bean SugarBean The bean to be updated * @param $api ServiceBase The API class of the request, used in cases where the API changes how the fields are pulled from the args array. * @param $args array The arguments array passed in from the API * @return id Bean id */ protected function updateBean(SugarBean $bean, ServiceBase $api, $args) { $helper = ApiHelper::getHelper($api, $bean); $options = array(); if (!empty($args['_headers']['X_TIMESTAMP'])) { $options['optimistic_lock'] = $args['_headers']['X_TIMESTAMP']; } try { $errors = $helper->populateFromApi($bean, $args, $options); } catch (SugarApiExceptionEditConflict $conflict) { $api->action = 'view'; $data = $this->formatBean($api, $args, $bean); // put current state of the record on the exception $conflict->setExtraData("record", $data); throw $conflict; } if ($errors !== true) { // There were validation errors. throw new SugarApiExceptionInvalidParameter('There were validation errors on the submitted data. Record was not saved.'); } $check_notify = $helper->checkNotify($bean); $bean->save($check_notify); /* * Refresh the bean with the latest data. * This is necessary due to BeanFactory caching. * Calling retrieve causes a cache refresh to occur. */ $id = $bean->id; if (isset($args['my_favorite'])) { $this->toggleFavorites($bean, $args['my_favorite']); } $bean->retrieve($id); /* * Even though the bean is refreshed above, return only the id * This allows loadBean to be run to handle formatting and ACL */ return $id; }
/** * Update records. * * @param $data array of job data */ public function runUpdate($data) { // Get the data down to just the list of fields $module = $data['module']; unset($data['module']); $action = $data['action']; unset($data['action']); $ids = is_array($data['uid']) ? $data['uid'] : array(); unset($data['uid']); unset($data['filter']); unset($data['entire']); $prospectLists = isset($data['prospect_lists']) ? $data['prospect_lists'] : array(); unset($data['prospect_lists']); $seed = BeanFactory::newBean($module); $fakeApi = new RestService(); $fakeApi->user = $GLOBALS['current_user']; $helper = ApiHelper::getHelper($fakeApi, $seed); $failed = 0; foreach ($ids as $id) { // Doing a full retrieve because we are writing we may need dependent fields for workflow that we don't know about $bean = BeanFactory::retrieveBean($module, $id); if ($bean == null) { // Team permissions may have changed, or a deletion, we won't hold it against them continue; } if (!$bean->aclAccess($action)) { // ACL's might not let them modify this bean, but we should still do the rest continue; } if ($action == 'delete') { $bean->mark_deleted($id); continue; } try { $errors = $helper->populateFromApi($bean, $data, array('massUpdate' => true)); $check_notify = $helper->checkNotify($bean); $bean->save($check_notify); } catch (SugarApiExceptionNotAuthorized $e) { // ACL's might not let them modify this bean, but we should still do the rest $failed++; continue; } } if (count($prospectLists) > 0) { $massupdate = new MassUpdate(); foreach ($prospectLists as $listId) { if ($action == 'save') { $success = $massupdate->add_prospects_to_prospect_list($module, $listId, $ids); } else { $success = $massupdate->remove_prospects_from_prospect_list($module, $listId, $ids); } } if (!$success) { $GLOBALS['log']->error("Could not add prospects to prospect list, could not find a relationship to the ProspectLists module."); } } return array('failed' => $failed); }
function updateRelatedLink($api, $args) { $api->action = 'save'; $primaryBean = $this->loadBean($api, $args); list($linkName, $relatedBean) = $this->checkRelatedSecurity($api, $args, $primaryBean, 'view', 'edit'); // Make sure the link isn't a readonly link if (isset($primaryBean->field_defs[$linkName])) { $def = $primaryBean->field_defs[$linkName]; if (isset($def['type']) && $def['type'] == 'link' && !empty($def['readonly'])) { throw new SugarApiExceptionNotAuthorized("Cannot update related records on readonly relationships"); } } $relatedBean->retrieve($args['remote_id']); if (empty($relatedBean->id)) { // Retrieve failed, probably doesn't have permissions throw new SugarApiExceptionNotFound('Could not find the related bean'); } BeanFactory::registerBean($relatedBean); // updateBean may remove the relationship. see PAT-337 for details $id = $this->updateBean($relatedBean, $api, $args); $relatedArray = array(); // Make sure there is a related object if (!empty($primaryBean->{$linkName})) { $relObj = $primaryBean->{$linkName}->getRelationshipObject(); } if (!empty($relObj)) { if ($primaryBean->module_name === $relObj->getLHSModule()) { $lhsBean = $primaryBean; $rhsBean = $relatedBean; } else { $lhsBean = $relatedBean; $rhsBean = $primaryBean; } // If the relationship still exists, we need to save changes to relationship fields if ($relObj->relationship_exists($lhsBean, $rhsBean)) { $relatedData = $this->getRelatedFields($api, $args, $primaryBean, $linkName, $relatedBean); // This function add() is actually 'addOrUpdate'. Here we use it for update only. $primaryBean->{$linkName}->add(array($relatedBean), $relatedData); // BR-2964, related objects are not populated ApiHelper::getHelper($api, $relatedBean)->populateFromApi($relatedBean, $args); // BR-2937 The edit view cache issue for relate documents of a module // nomad still needs this related array $relatedArray = $this->formatBean($api, $args, $relatedBean); } else { // Prepare the ralated bean data for formatNearAndFarRecords() below $relatedArray = $this->formatBean($api, $args, $relatedBean); // This record is unlinked to primary bean $relatedArray['_unlinked'] = true; } } //Clean up any hanging related records. SugarRelationship::resaveRelatedBeans(); // This forces a re-retrieval of the bean from the database BeanFactory::unregisterBean($relatedBean); return $this->formatNearAndFarRecords($api, $args, $primaryBean, $relatedArray); }