/** * type : 'profile' == profile status, * content : shared content. */ public function add() { $type = JRequest::getString('type'); $content = JRequest::getVar('text'); $my = FD::get('People'); $streamId = ''; switch ($type) { case 'profile': $data = array(); $data['actor_node_id'] = $my->get('node_id'); $data['node_id'] = '1'; $data['content'] = $content; $storyTbl = FD::table('Story'); $storyTbl->bind($data); $storyTbl->store(); $streamId = $storyTbl->streamId; if (!empty($streamId)) { $story = FD::get('Stream')->get('people', '', '', false, $streamId); FD::get('AJAX')->success($story[0]); return; } break; default: break; } FD::get('AJAX')->success(); }
/** * Retrieve the title of the stream * * @since 1.2 * @access public * @param string * @return */ public function getTitle() { // Get the actors $actors = $this->item->actors; // Get the source id $sourceId = $this->share->uid; // Load the stream $stream = FD::table('Stream'); $stream->load($sourceId); // If stream cannot be loaded, skip this altogether if (!$stream->id) { return; } // Build the permalink to the stream item $link = FRoute::stream(array('layout' => 'item', 'id' => $sourceId)); // Get the target user. $target = FD::user($stream->actor_id); $actor = $actors[0]; $theme = FD::get('Themes'); $theme->set('actor', $actor); $theme->set('link', $link); $theme->set('target', $target); $title = $theme->output('apps/group/shares/streams/stream/title'); return $title; }
public function load($path) { // Locate for the manifest file in the folder. $files = FD::get('Folders')->files($path, '.xml', self::RECURSIVE_SEARCH, self::RETRIEVE_FULL_PATH); $this->source = $path; if (!count($files)) { // Throw errors FD::get('Errors')->set('installer.xml', self::XML_NOT_FOUND); return false; } // Load through the list of manifest files to perform the installation. foreach ($files as $file) { $xml = JFactory::getXML($file); if (!$xml) { FD::get('Errors')->set('installer', self::XML_NOT_VALID); unset($xml); continue; } $this->type = (string) $xml->attributes()->type; if ($xml->getName() != 'social' || !in_array($this->type, $this->allowed)) { FD::get('Errors')->set('installer', self::XML_NOT_VALID); unset($parser); continue; } $this->parser = JFactory::getXMLParser('Simple'); $this->parser->loadFile($file); // Set the path of the current xml file. $this->path = $file; // Retrieves the element $this->element = $this->parser->document->getElementByPath('element')->data(); unset($xml); return true; } return false; }
/** * Does a remote call to the server to fetch contents of a given url. * * @since 1.0 * @access public */ public function fetch() { // Check for request forgeries! $urls = $this->input->get('urls', array(), 'array'); // Result placeholder $result = array(); if (!$urls) { $this->view->setMessage('COM_EASYSOCIAL_CRAWLER_INVALID_URL_PROVIDED', SOCIAL_MSG_ERROR); return $this->view->call(__FUNCTION__); } // Get the crawler $crawler = FD::get('crawler'); foreach ($urls as $url) { // Generate a hash for the url $hash = md5($url); $link = FD::table('Link'); $exists = $link->load(array('hash' => $hash)); // If it doesn't exist, store it. if (!$exists) { $crawler->crawl($url); // Get the data from our crawler library $data = $crawler->getData(); // Now we need to cache the link so that the next time, we don't crawl it again. $link->hash = $hash; $link->data = json_encode($data); $link->store(); } $result[$url] = json_decode($link->data); } return $this->view->call(__FUNCTION__, $result); }
public function display($theme = null) { if (is_null($theme)) { $theme = FD::get('Themes'); } return $this->theme->output($theme); }
/** * Loads the installation file based on a given path. * * @since 1.0 * @access public * @param string The installation path to lookup for. * @return bool True if loaded successfully, false otherwise. * * @author Mark Lee <*****@*****.**> */ public function load($path) { // Locate for the manifest file in the folder. $files = JFolder::files($path, '.xml', self::RECURSIVE_SEARCH, self::RETRIEVE_FULL_PATH); // Set the source so the parent can manipulate it ? $this->source = $path; // If there's no .xml files, throw errors here. if (!$files || count($files) <= 0) { $this->setError(JText::_('Manifest file does not exist.')); return false; } // Load through the list of manifest files to perform the installation. foreach ($files as $file) { $parser = FD::get('Parser'); // Render the xml file. $parser->load($file); // Set the app type. $this->type = (string) $parser->attributes()->type; // Set the app group. $this->group = (string) $parser->attributes()->group; if ($parser->getName() != self::XML_NAMESPACE || !in_array($this->type, $this->allowed)) { $this->setError(JText::_('Manifest file is not a valid EasySocial application')); continue; } // Set the path of the current xml file. $this->path = $file; // Retrieves the element $childs = $parser->children(); $this->element = (string) $childs->element; // Assign the parser into the property. $this->parser = $parser; return true; } return false; }
public function create_report() { $app = JFactory::getApplication(); $msg = $app->input->get('message', '', 'STRING'); $title = $app->input->get('user_title', '', 'STRING'); $item_id = $app->input->get('itemId', 0, 'INT'); $log_user = $this->plugin->get('user')->id; $data = array(); $data['message'] = $msg; $data['uid'] = $item_id; $data['type'] = 'stream'; $data['title'] = $title; $data['extension'] = 'com_easysocial'; //build share url use for share post through app $sharing = FD::get('Sharing', array('url' => FRoute::stream(array('layout' => 'item', 'id' => $item_id, 'external' => true, 'xhtml' => true)), 'display' => 'dialog', 'text' => JText::_('COM_EASYSOCIAL_STREAM_SOCIAL'), 'css' => 'fd-small')); $url = $sharing->url; $data['url'] = $url; // Get the reports model $model = FD::model('Reports'); // Determine if this user has the permissions to submit reports. $access = FD::access(); // Determine if this user has exceeded the number of reports that they can submit $total = $model->getCount(array('created_by' => $log_user)); if ($access->exceeded('reports.limit', $total)) { $final_result['message'] = "Limit exceeds"; $final_result['status'] = true; return $final_result; } // Create the report $report = FD::table('Report'); $report->bind($data); // Set the creator id. $report->created_by = $log_user; // Set the default state of the report to new $report->state = 0; // Try to store the report. $state = $report->store(); // If there's an error, throw it if (!$state) { $final_result['message'] = "Can't save report"; $final_result['status'] = true; return $final_result; } // @badge: reports.create // Add badge for the author when a report is created. $badge = FD::badges(); $badge->log('com_easysocial', 'reports.create', $log_user, JText::_('COM_EASYSOCIAL_REPORTS_BADGE_CREATED_REPORT')); // @points: reports.create // Add points for the author when a report is created. $points = FD::points(); $points->assign('reports.create', 'com_easysocial', $log_user); // Determine if we should send an email $config = FD::config(); if ($config->get('reports.notifications.moderators')) { $report->notify(); } $final_result['message'] = "Report logged successfully!"; $final_result['status'] = true; return $final_result; }
public function onPrepareStoryPanel($story) { if ($story->clusterType != SOCIAL_TYPE_GROUP) { return; } $params = $this->getParams(); // Determine if we should attach ourselves here. if (!$params->get('story_event', true)) { return; } if (!FD::config()->get('events.enabled')) { return; } // Create plugin object $plugin = $story->createPlugin('event', 'panel'); // Get the theme class $theme = FD::themes(); // Get the available event category $categories = FD::model('EventCategories')->getCreatableCategories(FD::user()->getProfile()->id); $theme->set('categories', $categories); $plugin->button->html = $theme->output('apps/user/events/story/panel.button'); $plugin->content->html = $theme->output('apps/user/events/story/panel.content'); $script = FD::get('Script'); $plugin->script = $script->output('apps:/user/events/story'); return $plugin; }
/** * Does a remote call to the server to fetch contents of a given url. * * @since 1.0 * @access public */ public function fetch() { // Check for request forgeries! $urls = JRequest::getVar('urls'); // Ensure that the urls are in an array FD::makeArray($urls); // Get the current view. $view = $this->getCurrentView(); // Result placeholder $result = array(); if (!$urls || empty($urls)) { $view->setMessage(JText::_('COM_EASYSOCIAL_CRAWLER_INVALID_URL_PROVIDED'), SOCIAL_MSG_ERROR); return $view->call(__FUNCTION__); } $crawler = FD::get('Crawler'); foreach ($urls as $url) { $hash = md5($url); $link = FD::table('Link'); $exists = $link->load(array('hash' => $hash)); // If it doesn't exist, store it. if (!$exists) { $crawler->crawl($url); $data = $crawler->getData(); $link->hash = $hash; $link->data = FD::json()->encode($data); // Store the new link $link->store(); } $result[$url] = FD::json()->decode($link->data); } return $view->call(__FUNCTION__, $result); }
public function getAjaxTemplate() { $templateFiles = JRequest::getVar('names'); // Ensure the integrity of each items submitted to be an array. if (!is_array($templateFiles)) { $templateFiles = array($templateFiles); } $result = array(); $theme = FD::get('Themes'); foreach ($templateFiles as $file) { // Remove any trailing .ejs in file name if exist. $file = str_replace('.ejs', '', $file); $template = $theme->getTemplate($file); ob_start(); include $template->ejs; $output = ob_get_contents(); ob_end_clean(); $obj = new stdClass(); $obj->name = $file; $obj->content = $output; $result[] = $obj; } if (!$result) { header('HTTP/1.1 404 Not Found'); exit; } header('Content-type: text/x-json; UTF-8'); $json = FD::json(); echo $json->encode($result); exit; }
/** * Does a remote call to the server to fetch contents of a given url. * * @since 1.0 * @access public */ public function proxy() { $type = JRequest::getWord('type'); $url = JRequest::getVar('url'); // Currently we only support serving of images if ($type != 'image') { $this->blank(); } // dump($url); $connector = FD::get('Connector'); $connector->addUrl($url); $connector->connect(); $contents = $connector->getResult($url, true); list($headers, $output) = explode("\r\n\r\n", $contents); // Get the content type $pattern = '/Content-Type: (.*)/i'; preg_match($pattern, $headers, $matches); if (!$matches || empty($matches) || !isset($matches[1])) { $this->blank(); } $contentType = strtolower(trim($matches[1])); $allowedTypes = array('image/png', 'image/jpeg', 'image/gif', 'image/bmp'); // Only allow image types if (!in_array($contentType, $allowedTypes)) { $this->blank(); } header('Content-Type: ' . $contentType); header('Content-Length: ' . strlen($output)); echo $output; exit; }
/** * Some desc * * @since 1.0 * @access public * @param string * @return */ public function createCover($file, $inputName) { // Load our own image library $image = FD::image(); // Generates a unique name for this image. $name = $file['name']; // Load up the file. $image->load($file['tmp_name'], $name); // Ensure that the image is valid. if (!$image->isValid()) { // @TODO: Add some logging here. echo JText::_('PLG_FIELDS_AVATAR_VALIDATION_INVALID_IMAGE'); exit; } // Get the storage path $storage = SocialFieldsUserCoverHelper::getStoragePath($inputName); // Create a new avatar object. $photos = FD::get('Photos', $image); // Create avatars $sizes = $photos->create($storage); // We want to format the output to get the full absolute url. $base = basename($storage); $result = array(); foreach ($sizes as $size => $value) { $row = new stdClass(); $row->title = $file['name']; $row->file = $value; $row->path = JPATH_ROOT . '/media/com_easysocial/tmp/' . $base . '/' . $value; $row->uri = rtrim(JURI::root(), '/') . '/media/com_easysocial/tmp/' . $base . '/' . $value; $result[$size] = $row; } return $result; }
public function main() { $db = FD::db(); $sql = $db->sql(); $sql->select('#__social_apps'); $sql->where('type', 'fields'); $db->setQuery($sql); $result = $db->loadObjectList(); foreach ($result as $row) { $file = SOCIAL_FIELDS . '/' . $row->group . '/' . $row->element . '/' . $row->element . '.xml'; if (!JFile::exists($file)) { continue; } $table = FD::table('App'); $table->bind($row); $parser = FD::get('Parser'); $parser->load($file); $val = $parser->xpath('unique'); $unique = 0; if ($val) { $unique = (string) $val[0]; $unique = $unique == 'true' ? 1 : 0; } $table->unique = $unique; $table->store(); } return true; }
/** * Displays the settings form for the respective page. * * @since 1.0 * @access public * @param null * @return null * @author Mark Lee <*****@*****.**> */ public function form() { // Get the current page. $page = JRequest::getVar('page', ''); // Get info object. $info = FD::info(); if (empty($page)) { // @TODO: Log errors here. $info->set(JText::_('No page provided'), SOCIAL_MSG_ERROR); $this->redirect('index.php?option=com_easysocial'); } // Add Joomla toolbar buttons JToolbarHelper::apply(); JToolbarHelper::custom('export', 'export', '', JText::_('COM_EASYSOCIAL_SETTINGS_EXPORT_SETTINGS'), false); JToolbarHelper::custom('import', 'import', '', JText::_('COM_EASYSOCIAL_SETTINGS_IMPORT_SETTINGS'), false); JToolbarHelper::custom('reset', 'default', '', JText::_('COM_EASYSOCIAL_RESET_TO_FACTORY'), false); // We need to include the theme file's header info. $theme = FD::get('Themes'); $paths = $theme->getTemplate('admin/settings/headers/' . $page); if (JFile::exists($paths->file)) { include $paths->file; } // Ensure that page is in proper string format. $page = strtolower($page); // Set the page to the class for other method to access $this->section = $page; // Set the page variable. $this->set('page', $page); // Set settings view variable $this->set('settings', $this); echo parent::display('admin/settings/form.container'); }
/** * Renders the form * * @since 1.0 * @access public * @param null * */ public function render($tabs = false, $sidebarTabs = false, $active = '', $prefix = '', $processActiveTab = true) { // Load our custom theme. $theme = FD::get('Themes'); $type = $tabs ? 'default.tabs' : 'default'; foreach ($this->form as &$form) { foreach ($form->fields as &$field) { // Ensure that the default property exists if (!isset($field->default)) { $field->default = ''; } // Ensure that the suffix exists if (!isset($field->suffix)) { $field->suffix = ''; } $field->inputName = $prefix ? $prefix . '[' . $field->name . ']' : $field->name; // Translate suffix if neccessary $field->suffix = JText::_($field->suffix); // Custom renderer based on type // Need to support apps renderer as well // apps:/path/to/file or apps:/[group]/[element]/renderer/[nameInCamelCase] // class SocialFormRenderer[NameInCamelCase] $rendererType = $field->type; $file = dirname(__FILE__) . '/renderer/' . strtolower($rendererType) . '.php'; // Check for : if (strpos($field->type, ':') !== false) { list($protocol, $path) = explode(':', $field->type); $segments = explode('/', $path); $rendererType = array_pop($segments); $base = defined('SOCIAL_' . strtoupper($protocol)) ? constant('SOCIAL_' . strtoupper($protocol)) : SOCIAL_ADMIN; $file = $base . $path . '.php'; } if (JFile::exists($file)) { require_once $file; $className = 'SocialFormRenderer' . ucfirst($rendererType); if (class_exists($className)) { $renderer = new $className(); $renderer->render($field, $this->params); } } } } // Replacements for invalid keys $invalidKeys = array(' ', ',', '&', '.', '*'); // Generate unique id so multiple tabs form on a single page would not conflict $uid = uniqid(); $theme->set('invalidKeys', $invalidKeys); $theme->set('uid', $uid); $theme->set('processActiveTab', $processActiveTab); $theme->set('prefix', $prefix); $theme->set('active', $active); $theme->set('sidebarTabs', $sidebarTabs); $theme->set('tabs', $tabs); $theme->set('params', $this->params); $theme->set('forms', $this->form); $template = 'admin/forms/' . $type; $contents = $theme->output($template); return $contents; }
public function unarchive() { $errors = $this->getErrors(); // @TODO: Process errors here. if ($errors) { } FD::get('AJAX')->success(); }
/** * Retrieves the recaptcha library * * @since 1.0 * @access public * @param string * @return */ public function getRecaptcha() { $app = $this->field->getApp(); $params = $app->getParams(); $options = array('public' => $params->get('public'), 'secret' => $params->get('private'), 'theme' => $params->get('theme'), 'language' => $params->get('language')); $captcha = FD::get('Captcha', 'Recaptcha', $options); return $captcha; }
/** * Sends a new share to a user. * * @since 1.0 * @access public */ public function send() { FD::checkToken(); $token = JRequest::getString('token', ''); $recipients = JRequest::getVar('recipients', array()); $content = JRequest::getVar('content', ''); // Get the current view. $view = $this->getCurrentView(); // Cleaning if (is_string($recipients)) { $recipients = explode(',', FD::string()->escape($recipients)); } if (is_array($recipients)) { foreach ($recipients as &$recipient) { $recipient = FD::string()->escape($recipient); if (!JMailHelper::isEmailAddress($recipient)) { return $view->call(__FUNCTION__, false, JText::_('COM_EASYSOCIAL_SHARING_EMAIL_INVALID_RECIPIENT')); } } } $content = FD::string()->escape($content); // Check for valid data if (empty($recipients)) { return $view->call(__FUNCTION__, false, JText::_('COM_EASYSOCIAL_SHARING_EMAIL_NO_RECIPIENTS')); } if (empty($token)) { return $view->call(__FUNCTION__, false, JText::_('COM_EASYSOCIAL_SHARING_EMAIL_INVALID_TOKEN')); } $session = JFactory::getSession(); $config = FD::config(); $limit = $config->get('sharing.email.limit', 0); $now = FD::date()->toUnix(); $time = $session->get('easysocial.sharing.email.time'); $count = $session->get('easysocial.sharing.email.count'); if (is_null($time)) { $session->set('easysocial.sharing.email.time', $now); $time = $now; } if (is_null($count)) { $session->set('easysocial.sharing.email.count', 0); } $diff = $now - $time; if ($diff <= 3600) { if ($limit > 0 && $count >= $limit) { return $view->call(__FUNCTION__, false, JText::_('COM_EASYSOCIAL_SHARING_EMAIL_SHARING_LIMIT_MAXED')); } $count++; $session->set('easysocial.sharing.email.count', $count); } else { $session->set('easysocial.sharing.email.time', $now); $session->set('easysocial.sharing.email.count', 1); } $library = FD::get('Sharing'); $library->sendLink($recipients, $token, $content); $view->call(__FUNCTION__, true); }
/** * Displays the share dialog * * @since 1.0 * @access public * @param string * @return */ public function shareDialog() { $ajax = FD::ajax(); $url = JRequest::getVar('url'); $title = JRequest::getVar('title'); $summary = JRequest::getVar('summary'); $sharing = FD::get('Sharing', array('url' => $url, 'title' => $title, 'summary' => $summary)); $contents = $sharing->getContents(); return $ajax->resolve($contents); }
/** * Returns an ajax chain. * * @since 1.0 * @access public * @param */ public function showOthers($users) { $ajax = FD::ajax(); $html = ''; // Get user list $theme = FD::get('Themes'); $theme->set('users', $users); $html = $theme->output('site/users/simplelist'); return $ajax->resolve($html); }
/** * Renders publish / unpublish icon. * * @since 1.0 * @access public * @param object The object to check against. * @param string The controller to be called. * @param string The key for the object. * * @author Mark Lee <*****@*****.**> */ public static function popover($title = '', $content = '', $placement = '', $placeholder = '', $html = false) { $theme = FD::get('Themes'); $theme->set('title', $title); $theme->set('content', $content); $theme->set('placement', $placement); $theme->set('placeholder', $placeholder); $theme->set('html', $html); return $theme->output('admin/html/bootstrap.popover'); }
public function __construct($uid, $group, $element) { $photo = FD::table('Photo'); $photo->load($uid); $this->title = $photo->get('title'); $theme = FD::get('Themes'); $theme->set('photo', $photo); $html = $theme->output('site/repost/preview.photo'); $this->content = $html; }
public function __construct($uid, $group, $element) { $album = FD::table('Album'); $album->load($uid); $this->title = $album->get('title'); $theme = FD::get('Themes'); $theme->set('album', $album); $html = $theme->output('site/repost/preview.album'); $this->content = $html; }
/** * Processes the migration item * * @since 1.0 * @access public * @param string * @return */ public function process() { // Check for request forgeries FD::checkToken(); // Retrieve the view. $view = $this->getCurrentView(); $component = JRequest::getVar('component', ''); $item = JRequest::getVar('item', ''); $mapping = JRequest::getVar('mapping', ''); $updateconfig = JRequest::getBool('updateconfig', 0); $migrator = FD::get('Migrators', $component); // Set the user mapping $migrator->setUserMapping($mapping); // we need to check if we need to update config or not. if (empty($item)) { $configTable = FD::table('Config'); $config = FD::registry(); if ($configTable->load('site')) { $config->load($configTable->value); if ($config->get('points.enabled') == 1) { $config->set('points.enabled', 0); // Convert the config object to a json string. $jsonString = $config->toString(); $configTable->set('value', $jsonString); // Try to store the configuration. if ($configTable->store()) { $updateconfig = true; // we need to reload the config $esConfig = new SocialConfig(); $esConfig->reload(); } } } } // Process the migration $obj = $migrator->process($item); if ($obj->continue == false && $updateconfig == true) { // now we need to re-enable back the points setting. $configTable = FD::table('Config'); $config = FD::registry(); if ($configTable->load('site')) { $config->load($configTable->value); $config->set('points.enabled', 1); // Convert the config object to a json string. $jsonString = $config->toString(); $configTable->set('value', $jsonString); // Try to store the configuration. $configTable->store(); $updateconfig = false; } } // Return the data back to the view. return $view->call(__FUNCTION__, $obj, $updateconfig); }
public function follow() { $app = JFactory::getApplication(); $target_user = $app->input->get('target_user', 0, 'INT'); $type = $app->input->get('type', 'user', 'STRING'); $group = $app->input->get('group', 'user', 'STRING'); $log_user = $this->plugin->get('user')->id; $follow = $app->input->get('follow', 1, 'INT'); $target = FD::user($target_user); $res = new stdClass(); if ($target_user == $log_user) { $res->success = 0; $res->message = "You can not follow yourself"; } // Load subscription table. $subscription = FD::table('Subscription'); // Get subscription library $subscriptionLib = FD::get('Subscriptions'); // Determine if the current user is already a follower $isFollowing = $subscriptionLib->isFollowing($target_user, $type, $group, $log_user); $subscription->uid = $target_user; $subscription->type = $type . '.' . $group; $subscription->user_id = $log_user; $points = FD::points(); if (!$isFollowing) { //$state = $subscription->store(); if ($subscription->store()) { $state = $this->addbadges($target, $log_user, $subscription->id); $res->success = 1; $res->message = "Following " . $target->username; return $res; } else { $res->success = 0; $res->message = "unable to follow " . $target->username; return $res; } } else { if ($subscriptionLib->unfollow($target_user, $type, $group, $log_user)) { // @points: profile.unfollow // Assign points when user starts new conversation $points->assign('profile.unfollow', 'com_easysocial', $log_user); // @points: profile.unfollowed // Assign points when user starts new conversation $points->assign('profile.unfollowed', 'com_easysocial', $user->id); $res->success = 1; $res->message = "successfully unfollow " . $target->username; return $res; } else { $res->success = 0; $res->message = "unable to unfollow " . $target->username; return $res; } } }
/** * Renders the sidebar items. * * @since 1.0 * @access public * @param string The current view. * @return string The html codes. * * @author Mark Lee <*****@*****.**> */ public function render($view) { // Retrieve menu items from the model. $model = FD::model('Sidebar'); $menus = $model->getItems(); $theme = FD::get('Themes'); $theme->set('menus', $menus); $theme->set('view', $view); $output = $theme->output('admin/structure/sidebar'); return $output; }
/** * Checks if the cover photo is a valid image * * @since 1.0 * @access public * @param string * @return */ public static function isValid($filePath) { // Load image library $image = FD::get('Image'); // Generate a temporary name for this image $name = md5($filePath); // Load up the image $image->load($filePath, $name); // Test if it is valid. $valid = $image->isValid(); return $valid; }
public function getVersion() { if (!$this->isComponentExist()) { return false; } // check JomSocial version. $xml = JPATH_ROOT . '/administrator/components/com_kunena/kunena.xml'; $parser = FD::get('Parser'); $parser->load($xml); $version = $parser->xpath('version'); $version = (double) $version[0]; return $version; }
/** * Responsible to output the single stream layout. * * @access public * @return null * */ public function display() { // Unauthorized users should not be allowed to access this page. FD::requireLogin(); // Check for user profile completeness FD::checkCompleteProfile(); // Get the current logged in user. $user = FD::user(); // Get user's privacy $privacy = FD::get('Privacy')->getUserPrivacy($user->id); $this->set('user', $user); $this->set('privacy', $privacy); echo parent::display('site/privacy/default'); }
public function getTarget() { static $nodes = array(); if (!isset($nodes[$this->target])) { // @rule: Allow multiple targets in a single action. $target = FD::json()->decode($this->target); $targets = array(); foreach ($target as $targetId) { $targets[] = FD::get('People', $targetId, SOCIAL_PEOPLE_NODE_ID); } $nodes[$this->target] = $targets; } return $nodes[$this->target]; }