/** * Executes a job to add activity subscriptions. * @param $data * @return bool */ public function run($data) { try { $data = unserialize($data); $subscriptionsBeanName = BeanFactory::getBeanName('Subscriptions'); $subscriptionsBeanName::addActivitySubscriptions($data); $this->job->succeedJob(); return true; } catch (Exception $e) { $this->job->failJob($e->getMessage()); return false; } }
/** * Find the link entry for a particular relationship and module. * * @param $module * @return array|bool */ public function getLinkedDefForModuleByRelationship($module) { $results = VardefManager::getLinkFieldForRelationship($module, BeanFactory::getBeanName($module), $this->name); //Only a single link was found if (isset($results['name'])) { return $results; } else { if (is_array($results)) { $GLOBALS['log']->error("Warning: Multiple links found for relationship {$this->name} within module {$module}"); return $this->getMostAppropriateLinkedDefinition($results); } else { return FALSE; } } }
public function __construct($def) { global $dictionary; $this->def = $def; $this->name = $def['name']; $this->selfReferencing = $def['lhs_module'] == $def['rhs_module']; $lhsModule = $def['lhs_module']; $rhsModule = $def['rhs_module']; if ($this->selfReferencing) { $links = VardefManager::getLinkFieldForRelationship($lhsModule, BeanFactory::getBeanName($lhsModule), $this->name); if (empty($links)) { $GLOBALS['log']->fatal("No Links found for relationship {$this->name}"); } if (!isset($links[0])) { //Only one link for a self referencing relationship, this is BAAAD $this->lhsLinkDef = $this->rhsLinkDef = $links; } else { if (!empty($links[0]['side']) && $links[0]['side'] == "right" || !empty($links[0]['link_type']) && $links[0]['link_type'] == "one") { //$links[0] is the RHS $this->lhsLinkDef = $links[1]; $this->rhsLinkDef = $links[0]; } else { //$links[0] is the LHS $this->lhsLinkDef = $links[0]; $this->rhsLinkDef = $links[1]; } } } else { $this->lhsLinkDef = VardefManager::getLinkFieldForRelationship($lhsModule, BeanFactory::getBeanName($lhsModule), $this->name); $this->rhsLinkDef = VardefManager::getLinkFieldForRelationship($rhsModule, BeanFactory::getBeanName($rhsModule), $this->name); if (!isset($this->lhsLinkDef['name']) && isset($this->lhsLinkDef[0])) { $this->lhsLinkDef = $this->lhsLinkDef[0]; } if (!isset($this->rhsLinkDef['name']) && isset($this->rhsLinkDef[0])) { $this->rhsLinkDef = $this->rhsLinkDef[0]; } } $this->lhsLink = $this->lhsLinkDef['name']; $this->rhsLink = $this->rhsLinkDef['name']; }
public function __construct($moduleName, $packageName = '', $client = 'base') { $GLOBALS['log']->debug(get_class($this) . ": __construct()"); if (empty($client)) { throw new \InvalidArgumentException("Client cannot be blank in SidecarFilterLayoutMetaDataParser"); } // Set the client $this->client = $client; if (empty($packageName)) { require_once 'modules/ModuleBuilder/parsers/views/DeployedSidecarFilterImplementation.php'; $this->implementation = new DeployedSidecarFilterImplementation($moduleName, $client); } else { require_once 'modules/ModuleBuilder/parsers/views/UndeployedSidecarFilterImplementation.php'; $this->implementation = new UndeployedSidecarFilterImplementation($moduleName, $packageName, $client); } $this->_moduleName = $moduleName; $this->_viewdefs = $this->implementation->getViewdefs(); $this->_paneldefs = $this->_viewdefs; $this->_fielddefs = $this->implementation->getFieldDefs(); $this->columns = array('LBL_DEFAULT' => 'getDefaultFields', 'LBL_HIDDEN' => 'getAvailableFields'); $filterBeanClass = BeanFactory::getBeanName('Filters'); $this->operators = $filterBeanClass::getOperators($client); }
function save($df) { // create the new ID field associated with this relate field - this will hold the id of the related record // this field must have a unique name as the name is used when constructing quicksearches and when saving the field //Check if we have not saved this field so we don't create two ID fields. //Users should not be able to switch the module after having saved it once. if (!$df->fieldExists($this->name)) { $id = new TemplateId(); $id->len = 36; $id->label = strtoupper("LBL_{$this->name}_" . BeanFactory::getBeanName($this->ext2) . "_ID"); $id->vname = $id->label; $this->saveIdLabel($id->label, $df); $count = 0; $basename = strtolower(get_singular_bean_name($this->ext2)) . '_id'; $idName = $basename . '_c'; while ($df->fieldExists($idName, 'id')) { $idName = $basename . ++$count . '_c'; } $id->name = $idName; $id->reportable = false; $id->save($df); // record the id field's name, and save $this->ext3 = $id->name; $this->id_name = $id->name; } parent::save($df); }
/** * This returns an UNFILTERED list of custom relationships by module name. You will have to filter the relationships * by the modules being exported after calling this method * @param string $moduleName * @param bool $lhs Return relationships where $moduleName - left module in join. * @return mixed Array or false when module name is wrong. */ protected function getCustomRelationshipsByModuleName($moduleName, $lhs = false) { if (BeanFactory::getBeanName($moduleName) === false) { return false; } $result = array(); $relation = null; $module = new StudioModule($moduleName); /* @var $rel DeployedRelationships */ $rel = $module->getRelationships(); $relList = $rel->getRelationshipList(); foreach ($relList as $relationshipName) { $relation = $rel->get($relationshipName); if ($relation->getFromStudio()) { if ($lhs && $relation->getLhsModule() != $moduleName) { continue; } $result[$relationshipName] = $relation; } } return $result; }
/** * Doing the same things like setUp but for initialized list of modules * * @static * @return bool are caches refreshed or not */ protected static function tearDown_relation() { SugarRelationshipFactory::deleteCache(); $modules = array_unique(self::$cleanModules); foreach ($modules as $module) { LanguageManager::clearLanguageCache($module); } self::tearDown('dictionary'); VardefManager::$linkFields = array(); VardefManager::clearVardef(); foreach ($modules as $module) { VardefManager::refreshVardefs($module, BeanFactory::getBeanName($module)); } SugarRelationshipFactory::rebuildCache(); self::$cleanModules = array(); return true; }
/** * Merges the fields together and stores them in $this->mergedFields * */ protected function mergeFields() { if ($this->sugarMerge instanceof SugarMerge && is_file($this->sugarMerge->getNewPath() . 'modules/ModuleBuilder/parsers/views/ListLayoutMetaDataParser.php')) { require_once $this->sugarMerge->getNewPath() . 'modules/ModuleBuilder/parsers/views/ListLayoutMetaDataParser.php'; } else { require_once 'modules/ModuleBuilder/parsers/views/ListLayoutMetaDataParser.php'; } $objectName = BeanFactory::getBeanName($this->module); VardefManager::loadVardef($this->module, $objectName); foreach ($this->customFields as $field => $data) { $fieldName = strtolower($data['loc']['row']); if (!empty($GLOBALS['dictionary'][$objectName]['fields'][$fieldName])) { $data['data'] = array_merge(ListLayoutMetaDataParser::createViewDefsByFieldDefs($GLOBALS['dictionary'][$objectName]['fields'][$fieldName]), $data['data']); } //if we have this field in both the new fields and the original fields - it has existed since the last install/upgrade if (isset($this->newFields[$field]) && isset($this->originalFields[$field])) { //if both the custom field and the original match then we take the location of the custom field since it hasn't moved $loc = $this->customFields[$field]['loc']; $loc['source'] = 'custom'; //echo var_export($loc, true); //but we still merge the meta data of the three $this->mergedFields[$field] = array('data' => $this->mergeField($this->originalFields[$field]['data'], $this->newFields[$field]['data'], $this->customFields[$field]['data']), 'loc' => $loc); //if it's not set in the new fields then it was a custom field or an original field so we take the custom fields data and set the location source to custom } else { if (!isset($this->newFields[$field])) { $this->mergedFields[$field] = $data; $this->mergedFields[$field]['loc']['source'] = 'custom'; } else { //otherwise the field is in both new and custom but not in the orignal so we merge the new and custom data together and take the location from the custom $this->mergedFields[$field] = array('data' => $this->mergeField('', $this->newFields[$field]['data'], $this->customFields[$field]['data']), 'loc' => $this->customFields[$field]['loc']); $this->mergedFields[$field]['loc']['source'] = 'custom'; //echo var_export($this->mergedFields[$field], true); } } //then we clear out the field from unset($this->originalFields[$field]); unset($this->customFields[$field]); unset($this->newFields[$field]); } /** * These are fields that were removed by the customer */ foreach ($this->originalFields as $field => $data) { unset($this->originalFields[$field]); unset($this->newFields[$field]); } foreach ($this->newFields as $field => $data) { $data['loc']['source'] = 'new'; $this->mergedFields[$field] = array('data' => $data['data'], 'loc' => $data['loc']); unset($this->newFields[$field]); } }
/** * Renders the QuickCreate form from Smarty and returns HTML * @param array $vars request variable global * @param object $email Fetched email object * @param bool $addToAddressBook * @return array */ function getQuickCreateForm($vars, $email, $addToAddressBookButton = false) { require_once "include/EditView/EditView2.php"; global $app_strings; global $mod_strings; global $current_user; global $current_language; $module = $_REQUEST['qc_module']; $beanName = BeanFactory::getBeanName($module); //Setup the current module languge $mod_strings = return_module_language($current_language, $module); $focus = BeanFactory::getBean($module); $people = array('Contact', 'Lead'); $emailAddress = array(); // people if (in_array($beanName, $people)) { // lead specific $focus->lead_source = 'Email'; $focus->lead_source_description = trim($email->name); $from = isset($email->from_name) && !empty($email->from_name) ? $email->from_name : $email->from_addr; if (isset($_REQUEST['sugarEmail']) && !empty($_REQUEST['sugarEmail'])) { if ($email->status == "sent") { $from = isset($email->to_addrs_names) && !empty($email->to_addrs_names) ? $email->to_addrs_names : $email->to_addrs; } else { $from = isset($email->from_name) && !empty($email->from_name) ? $email->from_name : $email->from_addr_name; } } $name = explode(" ", trim($from)); $address = trim(array_pop($name)); $address = str_replace(array("<", ">", "<", ">"), "", $address); $emailAddress[] = array('email_address' => $address, 'primary_address' => 1, 'invalid_email' => 0, 'opt_out' => 0, 'reply_to_address' => 1); $focus->email1 = $address; if (!empty($name)) { $focus->last_name = trim(array_pop($name)); foreach ($name as $first) { if (!empty($focus->first_name)) { $focus->first_name .= " "; } $focus->first_name .= trim($first); } } } else { // case & bug specific $focus->source = 'InboundEmail'; // bugs, cases, tasks $focus->name = trim($email->name); } $focus->description = trim(strip_tags($email->description)); $focus->assigned_user_id = $current_user->id; $focus->team_id = $current_user->default_team; $EditView = new EditView(); $EditView->ss = new Sugar_Smarty(); //MFH BUG#20283 - checks for custom quickcreate fields $EditView->setup($module, $focus, SugarAutoLoader::loadWithMetafiles($module, 'editviewdefs')); $EditView->process(); $EditView->render(); $EditView->defs['templateMeta']['form']['buttons'] = array('email2save' => array('id' => 'e2AjaxSave', 'customCode' => '<input type="button" class="button" value=" ' . $app_strings['LBL_SAVE_BUTTON_LABEL'] . ' " onclick="SUGAR.email2.detailView.saveQuickCreate(false);" />'), 'email2saveandreply' => array('id' => 'e2SaveAndReply', 'customCode' => '<input type="button" class="button" value=" ' . $app_strings['LBL_EMAIL_SAVE_AND_REPLY'] . ' " onclick="SUGAR.email2.detailView.saveQuickCreate(\'reply\');" />'), 'email2cancel' => array('id' => 'e2cancel', 'customCode' => '<input type="button" class="button" value=" ' . $app_strings['LBL_EMAIL_CANCEL'] . ' " onclick="SUGAR.email2.detailView.quickCreateDialog.hide();" />')); if ($addToAddressBookButton) { $EditView->defs['templateMeta']['form']['buttons']['email2saveAddToAddressBook'] = array('id' => 'e2addToAddressBook', 'customCode' => '<input type="button" class="button" value=" ' . $app_strings['LBL_EMAIL_ADDRESS_BOOK_SAVE_AND_ADD'] . ' " onclick="SUGAR.email2.detailView.saveQuickCreate(true);" />'); } //Get the module language for javascript if (!is_file(sugar_cached('jsLanguage/') . "{$module}/{$GLOBALS['current_language']}.js")) { require_once 'include/language/jsLanguage.php'; jsLanguage::createModuleStringsCache($module, $GLOBALS['current_language']); } $jsLanguage = getVersionedScript("cache/jsLanguage/{$module}/{$GLOBALS['current_language']}.js", $GLOBALS['sugar_config']['js_lang_version']); if ($focus->object_name == 'Contact') { $admin = Administration::getSettings(); if (empty($admin->settings['portal_on']) || !$admin->settings['portal_on']) { unset($EditView->sectionPanels[strtoupper('lbl_portal_information')]); } else { $jsLanguage .= getVersionedScript("modules/Contacts/Contact.js"); $jsLanguage .= getVersionedScript("modules/Contacts/QuickCreateEmailContact.js"); $jsLanguage .= <<<EOQ \t\t\t <script language="javascript"> \t\t\t\t addToValidateComparison('form_EmailQCView_Contacts', 'portal_password', 'varchar', false, SUGAR.language.get('app_strings', 'ERR_SQS_NO_MATCH_FIELD') + SUGAR.language.get('Contacts', 'LBL_PORTAL_PASSWORD'), 'portal_password1'); \t\t addToValidateVerified('form_EmailQCView_Contacts', 'portal_name_verified', 'bool', false, SUGAR.language.get('app_strings', 'ERR_EXISTING_PORTAL_USERNAME')); \t\t YAHOO.util.Event.on('portal_name', 'blur', validatePortalName); \t\t\t\t YAHOO.util.Event.on('portal_name', 'keydown', handleKeyDown); \t\t\t </script> EOQ; } } $EditView->view = 'EmailQCView'; $EditView->defs['templateMeta']['form']['headerTpl'] = 'include/EditView/header.tpl'; $EditView->defs['templateMeta']['form']['footerTpl'] = 'include/EditView/footer.tpl'; $meta = array(); $meta['html'] = $jsLanguage . $EditView->display(false, true); $meta['html'] = str_replace("src='" . getVersionedPath('include/SugarEmailAddress/SugarEmailAddress.js') . "'", '', $meta['html']); $meta['emailAddress'] = $emailAddress; $mod_strings = return_module_language($current_language, 'Emails'); return $meta; }
/** * Subscribe supplied User to supplied Bean * * @param User $user * @param SugarBean $bean * @return void */ protected function subscribeUserToRecord(User $user, SugarBean $bean) { $subs = BeanFactory::getBeanName('Subscriptions'); $subs::subscribeUserToRecord($user, $bean, array('disable_row_level_security' => true)); }
/** * Given an array of documents, this constructs an array of records that can be saved to FTS queue. * @param SugarBean $bean * @return array */ protected function getRecordsFromDocs($docs) { $records = array(); $i = 0; foreach ($docs as $doc) { $records[$i]['bean_id'] = $doc->getId(); $records[$i]['bean_module'] = BeanFactory::getBeanName($doc->getType()); $i++; } return $records; }
/** * Helper for processing subscriptions on a post activity. */ protected function processPostSubscription() { if (isset($this->parent_type) && isset($this->parent_id)) { $bean = BeanFactory::getBean($this->parent_type, $this->parent_id); $subscriptionsBeanName = BeanFactory::getBeanName('Subscriptions'); $this->processRecord($bean); $subscriptionsBeanName::processSubscriptions($bean, $this, array()); } else { $globalTeam = BeanFactory::getBean('Teams', '1'); if ($this->load_relationship('activities_teams')) { $this->activities_teams->add($globalTeam, array('fields' => '[]')); } } }
/** * Index records into search engine * * @param string $module * @param array $fieldDefinitions * @return integer number of indexed records, -1 if fails */ public function indexRecords($module, array $fieldDefinitions) { $beanName = BeanFactory::getBeanName($module); $bean = BeanFactory::newBean($module); $queuTableName = self::QUEUE_TABLE; $processedFtsIds = array(); $count = 0; $docs = array(); if ($this->shouldIndexViaBean($module)) { $GLOBALS['log']->debug("SugarFullIndexer will use bean to index records"); $selectAllQuery = "SELECT id, bean_id FROM {$queuTableName} WHERE bean_module='{$beanName}' AND processed = 0"; $result = $this->db->limitQuery($selectAllQuery, 0, $this->max_bulk_threshold, true, "Unable to retrieve records from FTS queue"); } else { $GLOBALS['log']->debug("SugarFullIndexer will use db to index records"); $sql = $this->generateFTSQuery($module, $fieldDefinitions); $result = $this->db->limitQuery($sql, 0, $this->max_bulk_query_threshold, true, "Unable to retrieve records from FTS queue"); } while ($row = $this->db->fetchByAssoc($result, false)) { $beanID = $row['id']; $ftsId = $row['fts_id']; $processed = $row['fts_processed']; if ($this->shouldIndexViaBean($module)) { $bean = BeanFactory::getBean($module, $beanID); } else { $row['module_dir'] = $module; $row = $bean->convertRow($row); $bean->fetched_row = $row; $bean->populateFromRow($row); } if ($bean !== false) { $GLOBALS['log']->debug("About to index bean: {$beanID} {$module}"); $docs[] = $this->SSEngine->createIndexDocument($bean, $fieldDefinitions); // add related beans to queue (processed == 0) if ($processed == 0) { $this->postProcessing($bean); } $processedFtsIds[] = $ftsId; $count++; } if ($count != 0 && $count % $this->max_bulk_threshold == 0) { $ok = $this->SSEngine->bulkInsert($docs); if ($ok) { $this->delFtsProcessed($processedFtsIds); } else { return -1; } $docs = $processedBeans = array(); sugar_cache_reset(); if (function_exists('gc_collect_cycles')) { gc_collect_cycles(); } $lastMemoryUsage = isset($lastMemoryUsage) ? $lastMemoryUsage : 0; $currentMemUsage = memory_get_usage(); $totalMemUsage = $currentMemUsage - $lastMemoryUsage; $GLOBALS['log']->info("Flushing records, count: {$count} mem. usage:" . memory_get_usage() . " , mem. delta: " . $totalMemUsage); $lastMemoryUsage = $currentMemUsage; } } if (count($docs) > 0) { $ok = $this->SSEngine->bulkInsert($docs); if (!$ok) { return -1; } } $this->delFtsProcessed($processedFtsIds); return $count; }
/** * This function adds records to FTS queue. * * @param $records array of records */ protected function addRecordsToQueue($records) { $this->logger->info('addRecordsToQueue'); $db = DBManagerFactory::getInstance('fts'); $db->resetQueryCount(); foreach ($records as $rec) { if (!is_array($rec) || empty($rec['bean_id']) || empty($rec['bean_module'])) { $this->logger->error('Error populating fts_queue. Empty bean_id or bean_module.'); continue; } // support multiple values for 'processed' $rec['processed'] = empty($rec['processed']) ? 0 : $rec['processed']; $query = sprintf("SELECT id, processed FROM fts_queue WHERE bean_id = %s AND bean_module = %s", $db->quoted($rec['bean_id']), $db->quoted(BeanFactory::getBeanName($rec['bean_module']))); $res = $db->query($query, true, "Error get records from queue for fts"); if ($item = $db->fetchRow($res)) { if ($item['processed'] != $rec['processed'] && $item['processed'] != 0) { $query = sprintf("UPDATE fts_queue SET processed = %s, date_modified = current_timestamp WHERE id = %s", $db->quoted($rec['processed']), $db->quoted($item['id'])); $db->query($query, true, "Error update record in queue for fts"); } } else { $beanName = BeanFactory::getBeanName($rec['bean_module']); if (empty($beanName)) { $GLOBALS['log']->error("Full indexer: Failed to get bean name for module: {$rec['bean_module']}"); continue; } $query = sprintf("INSERT INTO fts_queue (id, bean_id, bean_module, processed, date_created)\n values (%s, %s, %s, %s, %s)", $db->quoted(create_guid()), $db->quoted($rec['bean_id']), $db->quoted($beanName), $db->quoted($rec['processed']), $db->now()); $db->query($query, true, "Error populating index queue for fts"); } } /* * The full indexer jobs should already be present when a full reindex * has been scheduled earler on. Those are presistent jobs and will * remain in the job queue to process new reocrds from the fts_queue. * * If a full indexer job is manually removed, scheduling again a full * reindex will trigger restoration of the full indexer jobs where needed. */ }