Пример #1
0
 public function countRelated(One_Relation_Adapter $link, One_Model $model, array $options = array())
 {
     $linkName = $link->getName();
     // identify the target scheme
     $source = One_Repository::getScheme($model->getSchemeName());
     $target = One_Repository::getScheme($link->getTarget());
     $backlinks = $target->getLinks();
     $backlink = $backlinks[$link->getLinkId()];
     if (!$backlink) {
         throw new One_Exception('The role "' . $roleName . '" does not exist for this model');
     }
     $at = $source->getIdentityAttribute()->getName();
     $column = $this->remoteFK($link, $source, $backlink);
     // bind the data using the data
     $localValue = $model->{$at};
     // create query and execute
     $q = One_Repository::selectQuery($link->getTarget());
     $q->setOptions($options);
     if (isset($link->meta['hybrid'])) {
         $var = $link->meta['hybrid'] . '_scheme';
         $q->where($var, 'eq', $source->getName());
     }
     $q->where($column, 'eq', $localValue);
     return $q->getCount();
 }
Пример #2
0
 /**
  * Use the selectors to retrieve a number of objects.
  *
  * @param One_Scheme $scheme
  * @param array $selectors
  * @return array
  */
 public function select(&$scheme, $selectors)
 {
     $query = One_Repository::selectQuery($scheme);
     if (count($selectors)) {
         foreach ($selectors as $sel) {
             list($path, $val, $op) = $sel;
             $query->where($path, $op, $val);
         }
     }
     $selection = $this->executeSchemeQuery($query);
     return count($selection) > 0 ? $selection : NULL;
 }
Пример #3
0
 /**
  * Return the number of One_Models of the specified kind
  *
  * @param string $schemeName
  * @return int
  *
  * //TODO is this useful at all ? total count ?
  */
 public function selectCount()
 {
     $scheme = $this->scheme;
     $query = One_Repository::selectQuery($scheme);
     $behaviors = $scheme->get('behaviors');
     if ($behaviors) {
         foreach ($behaviors as $behavior) {
             $behavior->onSelect($query);
         }
     }
     return $query->getCount();
 }
Пример #4
0
 /**
  * @param One_Scheme $scheme
  *
  * GET schemename
  * Select all items
  *
  * Optional parameters: order, limit, start
  */
 public static function restGetAll(One_Scheme $scheme)
 {
     try {
         $q = One_Repository::selectQuery($scheme->getName());
         $model = $q->execute();
         $response = array();
         foreach ($model as $object) {
             $response[] = $object->asRestResponse();
         }
         echo self::toPrettyJson($response);
     } catch (Exception $e) {
         $this->slim->response()->status(400);
         $this->slim->response()->header('X-Status-Reason', $e->getMessage());
         print_r($e);
     }
 }
Пример #5
0
 /**
  * Select a single instance.
  *
  * @param mixed $scheme Can be the name of a One_Scheme or the One_Scheme object itself
  * @param mixed $identityValue
  * @return One_Model
  */
 public function selectOne(One_Scheme_Interface $scheme, $identityValue)
 {
     $cached = One_Model_IdentityMap::find($scheme->getName(), $identityValue);
     if ($cached) {
         return $cached;
     }
     $db = $this->db($scheme);
     $renderer = $this->getRenderer();
     $query = One_Repository::selectQuery($scheme->getName());
     $idAttr = $scheme->getIdentityAttribute();
     $column = $idAttr->getName();
     $value = $idAttr->toString($identityValue);
     $query->where($column, 'eq', $value);
     $result = $this->executeSchemeQuery($query);
     return count($result) > 0 ? $result[0] : NULL;
 }
Пример #6
0
 /**
  * Parse the given DOMElement into containers and widgets and add them to the form
  *
  * @param DOMElement $element
  * @param One_Form_Container_Abstract $container
  */
 protected static function _parseToForm(DOMElement $element, One_Form_Container_Abstract $container)
 {
     $current = strtolower($element->localName);
     if ($current == 'constraints' || $current == 'constraint') {
         return NULL;
     }
     $widgetClass = self::identifyElement($current);
     if (is_null($widgetClass)) {
         return NULL;
     }
     if (is_object($widgetClass)) {
         $widgetClass = get_class($widgetClass);
     }
     if (preg_match('/^One_Form_Container/', $widgetClass) && $widgetClass != 'One_Form_Container_Form') {
         $attributes = array();
         $rawAttributes = $element->attributes;
         for ($i = 0; $i < $rawAttributes->length; $i++) {
             $attribute = $rawAttributes->item($i);
             $attributes[$attribute->localName] = $attribute->value;
         }
         if (false === isset($attributes['language'])) {
             $attributes['language'] = strtolower(One_Config::get('app.language'));
         }
         $subContainerId = isset($attributes['id']) ? $attributes['id'] : NULL;
         $subContainer = new $widgetClass($subContainerId, $attributes);
         // containers can contain other containers or widgets
         if ($element->hasChildNodes()) {
             foreach ($element->childNodes as $child) {
                 if ($child instanceof DOMElement) {
                     self::_parseToForm($child, $subContainer);
                 }
             }
         }
         $container->addContainer($subContainer);
     } else {
         if ($element->hasAttribute('role')) {
             // Get cache in preparation of possible option-caching
             $session = One_Repository::getSession();
             $parts = explode(':', $element->getAttribute('role'));
             if (count($parts) != 2) {
                 throw new One_Exception('You must define a valid role');
             }
             $relation = One_Repository::getRelation($parts[0]);
             $role = $relation->getRole($parts[1]);
             $relScheme = One_Repository::getScheme($role->schemeName);
             // set the name and id of the so it will be recognised as a related field
             $element->setAttribute('id', 'r__' . $element->getAttribute('role'));
             $element->setAttribute('name', 'r__' . $element->getAttribute('role'));
             if ($element->hasAttribute('optionsFrom')) {
                 $sessionCacheName = md5($relScheme->getName() . '#' . $element->getAttribute('optionsFrom'));
                 if (false === $element->hasAttribute('cacheOptions') || $element->hasAttribute('cacheOptions') && false === $session->varExists($sessionCacheName, 'One_Form_Cache')) {
                     $relView = new One_View($relScheme->getName(), $element->getAttribute('optionsFrom'));
                     $rawOptions = trim($relView->show());
                     $options = json_decode($rawOptions, 1);
                     if (false === is_array($options)) {
                         $options = array();
                     }
                     if ($element->hasAttribute('cacheOptions')) {
                         $session->set($sessionCacheName, $options, 'One_Form_Cache');
                     }
                 } else {
                     $options = $session->get($sessionCacheName, 'One_Form_Cache');
                 }
             } else {
                 if (!$element->hasAttribute('targetAttribute')) {
                     $targetAttr = $relScheme->getIdentityAttribute()->getName();
                 } else {
                     $targetAttr = $element->getAttribute('targetAttribute');
                 }
                 $sessionCacheName = md5($relScheme->getName() . '#' . $targetAttr . '#' . $element->getAttribute('publishedOnly'));
                 if (false === $element->hasAttribute('cacheOptions') || $element->hasAttribute('cacheOptions') && false === $session->varExists($sessionCacheName, 'One_Form_Cache')) {
                     $q = One_Repository::selectQuery($relScheme->getName());
                     $tparts = explode(':', $targetAttr);
                     foreach ($tparts as $tkey => $tval) {
                         if (in_array(substr($tval, 0, 1), array('(', '['))) {
                             $tparts[$tkey] = substr($tval, 1) . '+';
                         } else {
                             $tparts[$tkey] = $tval . '+';
                         }
                     }
                     $q->setOrder($tparts);
                     $results = $q->execute(false);
                     $options = array();
                     foreach ($results as $result) {
                         $idAttr = $relScheme->getIdentityAttribute()->getName();
                         $valAttr = $targetAttr;
                         $val = '';
                         foreach (explode(':', $targetAttr) as $tkey => $tval) {
                             switch (substr($tval, 0, 1)) {
                                 case '(':
                                     $tval = substr($tval, 1);
                                     $val .= '(' . $result->{$tval} . ') ';
                                     break;
                                 case '[':
                                     $tval = substr($tval, 1);
                                     $val .= '[' . $result->{$tval} . '] ';
                                     break;
                                 default:
                                     $val .= $result->{$tval} . ' ';
                                     break;
                             }
                         }
                         $options[$result->{$idAttr}] = trim($val);
                     }
                     if ($element->hasAttribute('cacheOptions')) {
                         $session->set($sessionCacheName, $options, 'One_Form_Cache');
                     }
                 } else {
                     $options = $session->get($sessionCacheName, 'One_Form_Cache');
                 }
             }
             $widget = self::determineWidget($container, $element, $widgetClass);
             if (method_exists($widget, 'setOptionsOnDetermination') && $widget->setOptionsOnDetermination()) {
                 $widget->setOptions($options);
             }
         } else {
             $widget = self::determineWidget($container, $element, $widgetClass);
         }
     }
 }
Пример #7
0
 /**
  * Perform weighted search that returns the results according to matching compatibility
  * @return array
  */
 protected function performWeightSearch()
 {
     $session = One_Repository::getSession();
     $allSearchValues = array();
     $results = array('count' => 0, 'all' => array(), 'most' => array(), 'some' => array());
     // Get all used widgets
     $form = One_Form_Factory::createForm($this->scheme, $this->searchform);
     $widgets = $this->getWidgets($form, $this->scheme);
     $idAttr = $this->scheme->getIdentityAttribute()->getName();
     $searchOptions = $this->scheme->get('behaviorOptions.searchable');
     $conditions = 0;
     $weights = array();
     $conditionByModel = array();
     $specificWeights = array();
     foreach ($widgets as $widget) {
         $widgetData = $widget->getWidgetData();
         // Get the widget's name, value and operator
         // Check whether a widget is a specifier or not
         $specifier = false;
         if ($widget->getCfg('specifier')) {
             $specifier = true;
         }
         if (null !== $widgetData['value']) {
             $allSearchValues[$widgetData['name']] = $widgetData['value'];
             if (false !== strpos($widgetData['name'], ':')) {
                 $parts = explode(':', $widgetData['name'], 2);
                 $relation = One_Repository::getRelation($parts[0]);
                 // get the used relation
                 $link = $this->scheme->getLink($parts[1]);
                 $targetScheme = One_Repository::getScheme($link->getTarget());
                 // get the scheme of the related field
                 $tidAttr = $targetScheme->getIdentityAttribute()->getName();
                 $tSearchOptions = $this->scheme->get('behaviorOptions.searchable');
                 $wOptions = null;
                 if (method_exists($widget, 'getOptions')) {
                     $wOptions = $widget->getOptions();
                 }
                 // Get the role of the current scheme as seen from the relation from the target's side
                 $otherRole = null;
                 foreach ($relation->getRoles() as $role) {
                     if ($parts[1] != $role->name) {
                         $otherRole = $role;
                     }
                 }
                 if (null !== $otherRole) {
                     // Dirty trick to enforce the value(s) as an array so they are easier manageable
                     $values = $widgetData['value'];
                     if (!is_array($widgetData['value'])) {
                         $values = array($widgetData['value']);
                     }
                     if (null !== $widgetData['operator']) {
                         $tmpValues = array();
                         $op = $widgetData['operator'];
                         $allowed = $op->getAllowed();
                         $opVal = $op->getValue();
                         if (!is_null($opVal)) {
                             if (in_array($opVal, $allowed)) {
                                 $op = $opVal;
                             } else {
                                 $op = $allowed['default'];
                             }
                         } else {
                             $op = $allowed['default'];
                         }
                         // Perform special operators
                         foreach ($values as $value) {
                             $tQ = One_Repository::selectQuery($targetScheme->getName());
                             $tQ->setSelect(array($tidAttr));
                             $tQ->where($tidAttr, $op, $value);
                             $tmpResults = $tQ->execute(false);
                             foreach ($tmpResults as $tmpResult) {
                                 $tmpValues[$tmpResult->{$tidAttr}] = $tmpResult->{$tidAttr};
                             }
                         }
                         $values = $tmpValues;
                     }
                     // Get all related data // @TODO in the future it could be possible that you don't always get ID's of the related fields, but works for now
                     foreach ($values as $value) {
                         $current = One_Repository::selectOne($targetScheme->getName(), $value);
                         if (!is_null($current)) {
                             if (isset($tSearchOptions['publishField'])) {
                                 $tPubField = $searchOptions['publishField'];
                                 if (0 == $current->{$tPubField}) {
                                     continue;
                                 }
                             }
                             $conditions++;
                             $relateds = $current->getRelated($otherRole->name);
                             if (null === $relateds) {
                                 continue;
                             }
                             if (!is_array($relateds)) {
                                 $relateds = array($relateds);
                             }
                             foreach ($relateds as $related) {
                                 if (!isset($weights[$related->{$idAttr}])) {
                                     if (false === $specifier) {
                                         $weights[$related->{$idAttr}] = 0;
                                     }
                                     $conditionByModel[$related->{$idAttr}] = array();
                                 }
                                 if (!isset($conditionByModel[$related->{$idAttr}][$widgetData['name']])) {
                                     $conditionByModel[$related->{$idAttr}][$widgetData['name']] = array();
                                 }
                                 if (isset($wOptions[$value])) {
                                     $conditionByModel[$related->{$idAttr}][$widgetData['name']][] = $wOptions[$value];
                                 } else {
                                     $conditionByModel[$related->{$idAttr}][$widgetData['name']][] = $value;
                                 }
                                 // if the current widget is a specifier, maintain the data in a separate array to perform an array_intersect to
                                 if (true == $specifier) {
                                     if (!isset($specificWeights[$related->{$idAttr}])) {
                                         $specificWeights[$related->{$idAttr}] = 0;
                                     }
                                     $specificWeights[$related->{$idAttr}]++;
                                     continue;
                                 }
                                 $weights[$related->{$idAttr}]++;
                             }
                         }
                     }
                 }
             } else {
                 $values = $widgetData['value'];
                 if (!is_array($widgetData['value'])) {
                     $values = array($widgetData['value']);
                 }
                 if (null !== $widgetData['operator']) {
                     $op = $widgetData['operator'];
                     $allowed = $op->getAllowed();
                     $opVal = $op->getValue();
                     if (!is_null($opVal)) {
                         if (in_array($opVal, $allowed)) {
                             $op = $opVal;
                         } else {
                             $op = $allowed['default'];
                         }
                     } else {
                         $op = $allowed['default'];
                     }
                 } else {
                     $op = 'eq';
                 }
                 foreach ($values as $value) {
                     if ('' != trim($value)) {
                         $conditions++;
                         $cQ = One_Repository::selectQuery($this->scheme->getName());
                         $cQ->setSelect(array($idAttr));
                         $cQ->where($widgetData['name'], $op, $value);
                         $tmpResults = $cQ->execute(false);
                         foreach ($tmpResults as $tmpResult) {
                             if (!isset($weights[$tmpResult->{$idAttr}])) {
                                 if (false === $specifier) {
                                     $weights[$tmpResult->{$idAttr}] = 0;
                                 }
                                 $conditionByModel[$tmpResult->{$idAttr}] = array();
                             }
                             if (!isset($conditionByModel[$tmpResult->{$idAttr}][$widgetData['name']])) {
                                 $conditionByModel[$tmpResult->{$idAttr}][$widgetData['name']] = array();
                             }
                             $conditionByModel[$tmpResult->{$idAttr}][$widgetData['name']][] = $value;
                             // if the current widget is a specifier, maintain the data in a separate array to perform an array_intersect to
                             if (true == $specifier) {
                                 if (!isset($specificWeights[$tmpResult->{$idAttr}])) {
                                     $specificWeights[$tmpResult->{$idAttr}] = 0;
                                 }
                                 $specificWeights[$tmpResult->{$idAttr}]++;
                                 continue;
                             }
                             $weights[$tmpResult->{$idAttr}]++;
                         }
                     }
                 }
             }
         }
     }
     $tilt = $this->getSearchTilt($conditions);
     foreach ($weights as $id => $weight) {
         if (0 < count($specificWeights)) {
             if (false === array_key_exists($id, $specificWeights)) {
                 unset($weights[$id]);
                 unset($conditionByModel[$id]);
                 continue;
             } else {
                 $weight += $specificWeights[$id];
             }
         }
         $model = One_Repository::selectOne($this->scheme->getName(), $id);
         // using selectOne as the models needed here are already in cache, a global search by there id would take more resources
         $model->One_Search_Weight = round($weight / $conditions * 100, 2);
         $model->One_Search_Weight_Conditions = $conditions;
         $model->One_Search_Weight_ConditionsMet = $weight;
         $model->One_Search_Weight_ConditionObject = $conditionByModel[$id];
         $type = 'some';
         if ($conditions == $weight) {
             $type = 'all';
         } elseif ($conditions >= $tilt) {
             $type = 'most';
         }
         $results[$type][] = $model;
         $results['count']++;
     }
     foreach (array('all', 'most', 'some') as $type) {
         usort($results[$type], array($this, 'sortResultsByWeight'));
     }
     $session->set('results', $results, 'one_search');
     return $results;
 }
Пример #8
0
require_once JPATH_BASE . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'defines.php';
require_once JPATH_BASE . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'framework.php';
if ($withDB) {
    /* To use Joomla's Database Class */
    require_once JPATH_BASE . DIRECTORY_SEPARATOR . 'libraries' . DIRECTORY_SEPARATOR . 'joomla' . DIRECTORY_SEPARATOR . 'factory.php';
}
$mainframe = JFactory::getApplication('site');
require_once JPATH_BASE . '/plugins/system/one/lib/one.php';
One_Config::getInstance()->setCustomPath(JPATH_BASE . '/media/one');
// require_once( ONE_SCRIPT_PATH . 'tools' . DIRECTORY_SEPARATOR . 'autoload.php' );
require_once ONE_LIB_PATH . '/tools.php';
$scheme = $_POST['searchscheme'];
$tparts = explode(':', $_POST['target']);
$phrase = strip_tags($_POST['phrase']);
$selfId = isset($_POST['selfId']) ? $_POST['selfId'] : NULL;
$query = One_Repository::selectQuery($scheme);
$scheme = $query->getScheme();
$idAttr = $scheme->getIdentityAttribute()->getName();
if (!is_null($selfId)) {
    $query->where($idAttr, 'neq', $selfId);
}
// possibility to implement if the 2 schemes are the same in the manytomany relationship to exclude the current ID
$or = $query->addOr();
foreach ($tparts as $tpart) {
    $or->where($tpart, 'contains', $phrase);
}
if ($tparts > 0) {
    $or->where('joined', 'literal', ' CONCAT_WS( " ", ' . implode(', ', $tparts) . ' ) LIKE "%' . $phrase . '%"');
}
$results = $query->execute();
$toEcho = $_POST['dd'] . '=>%O%';
Пример #9
0
 /**
  * Parse the segments of a URL.
  *
  * @param   array &$segments The segments of the URL to parse.
  *
  * @return  array  The URL attributes to be used by the application.
  *
  * @since   3.3
  */
 public function parse(&$segments)
 {
     // Get the active menu item.
     $app = JFactory::getApplication();
     $menu = $app->getMenu();
     $item = $menu->getActive();
     if (isset($item->query['controller']) && $item->query['controller'] == 'rest') {
         return array();
     }
     $options = One_Routing::getOptionsForAlias(implode('/', $segments));
     //    echo '<pre>';
     //    print_r($options);
     //    echo '</pre>';
     if ($options !== null) {
         $vars = array();
         $vars['scheme'] = $options['schemeName'];
         $vars['task'] = $options['options']['task'];
         $vars['view'] = $options['options']['view'];
         // check and find the alias or id field
         if ($options['useId'] && null !== $options['aliasField']) {
             $regularAlias = $segments[count($segments) - 1];
             $altAlias = preg_replace('/:/', '-', $regularAlias, 1);
             $schemeQuery = One_Repository::selectQuery($options['schemeName']);
             if ($regularAlias == $altAlias) {
                 $schemeQuery->where($options['aliasField'], 'eq', $regularAlias);
             } else {
                 $queryOr = $schemeQuery->addOr();
                 $queryOr->where($options['aliasField'], 'eq', $regularAlias);
                 $queryOr->where($options['aliasField'], 'eq', $altAlias);
             }
             $results = $schemeQuery->execute();
             if (0 < count($results)) {
                 $idAttr = $schemeQuery->getScheme()->getIdentityAttribute()->getName();
                 $vars['id'] = $results[0]->{$idAttr};
             }
             unset($vars['aliasfield']);
         } else {
             if ($options['useId']) {
                 $vars['id'] = $segments[count($segments) - 1];
             }
         }
         //      echo '<pre>';
         //      print_r($vars);
         //      echo '</pre>';
         return $vars;
     }
     /**
      * Since we have no clear routing, we can only work on the standard interpretation. Only change is that we
      * can use the current menu's scheme if that is a com_one menu item.
      */
     $menu_options = array();
     if (($menu = JSite::getMenu()->getActive()) && $menu->component == 'com_one') {
         $menuscheme = $menu->query['scheme'];
         array_unshift($segments, $menuscheme);
     }
     $vars = array();
     $count = count($segments);
     switch ($count) {
         case 4:
             // format : SCHEME / TASK / VIEW / ID
             $vars['scheme'] = str_replace('-', ':', $segments[$count - 4]);
             $vars['task'] = $segments[$count - 3];
             $vars['view'] = $segments[$count - 2];
             $parts = explode(',', $segments[$count - 1]);
             $vars['id'] = $parts[count($parts) - 1];
             break;
         case 3:
             // format : SCHEME / detail / ID
             // format : SCHEME / list / VIEW
             // format : SCHEME / calendar* / VIEW
             // format : SCHEME / view / VIEW
             $vars['scheme'] = str_replace('-', ':', $segments[$count - 3]);
             $vars['task'] = $segments[$count - 2];
             $parts = explode(',', $segments[$count - 1]);
             if (preg_match('/calendar(Day|Month|Week)?/', $vars['task']) > 0) {
                 $vars['view'] = $segments[$count - 1];
             } else {
                 if (count($parts) > 1) {
                     if ($vars['task'] == 'detail' && preg_match('/^(month|week|day)$/', $params->get('view')) > 0) {
                         $vars['view'] = 'detail';
                     }
                     $parts = explode(',', $segments[$count - 1]);
                     $vars['id'] = $parts[count($parts) - 1];
                 } else {
                     if ($vars['task'] == 'detail') {
                         $vars['view'] = 'detail';
                         $vars['id'] = $parts[count($parts) - 1];
                     } else {
                         if ($vars['task'] == 'edit') {
                             $vars['view'] = $parts[count($parts) - 1];
                             $vars['id'] = 0;
                         } else {
                             $vars['view'] = $segments[$count - 1];
                         }
                     }
                 }
             }
             break;
         case 2:
             $vars['scheme'] = str_replace('-', ':', $segments[$count - 2]);
             $vars['task'] = $segments[$count - 1];
             break;
         case 1:
             $vars['scheme'] = str_replace('-', ':', $segments[$count - 1]);
             $vars['task'] = 'list';
             break;
         default:
     }
     return $vars;
 }
Пример #10
0
 public function countRelated(One_Relation_Adapter $link, One_Model $model, array $options = array())
 {
     $nRelated = 0;
     $linkName = $link->getName();
     // identify the target scheme
     $source = One_Repository::getScheme($model->getSchemeName());
     $target = One_Repository::getScheme($link->getTarget());
     $backlinks = $target->getLinks();
     $backlink = $backlinks[$link->getLinkId()];
     if (!$backlink) {
         throw new One_Exception("There is no link with id " . $link->getLinkId() . " in scheme " . $link->getTarget());
     }
     $sourceId = $source->getIdentityAttribute()->getName();
     $localValue = $model[$sourceId];
     $targetId = $target->getIdentityAttribute()->getName();
     // TR20100615 if all stores are equal, do normal join, if not, fetch data in several steps
     // @TODO This should actually be handled in One_Query
     if ($source->getConnection()->getName() == $link->meta['connection'] && $link->meta['connection'] == $target->getConnection()->getName()) {
         $lQ = One_Repository::selectQuery($source);
         $lQ->setSelect(array($linkName . ':*'));
         $lQ->where($sourceId, 'eq', $localValue);
         if (array_key_exists('query', $options) && is_array($options['query']) && count($options['query']) > 0) {
             foreach ($options['query'] as $qKey => $qOption) {
                 if (count($qOption) == 3) {
                     $options['query'][$qKey][0] = $linkName . ':' . $options['query'][$qKey][0];
                 }
             }
         }
         $lQ->setOptions($options);
         $nRelated = $lQ->getCount();
     } else {
         $fkLocal = $link->meta['fk:local'];
         $fkRemote = $link->meta['fk:remote'];
         $omtms = One_Repository::getScheme('onemanytomany');
         $omtms->setConnection(One_Repository::getConnection($link->meta['connection']));
         $omtms->setResources($link->meta);
         $localAtt = new One_Scheme_Attribute($fkLocal, $source->getIdentityAttribute()->getType()->getName());
         $remoteAtt = new One_Scheme_Attribute($fkRemote, $target->getIdentityAttribute()->getType()->getName());
         $omtms->addAttribute($localAtt);
         $omtms->addAttribute($remoteAtt);
         $joinQ = One_Repository::selectQuery($omtms);
         $joinQ->setSelect(array($fkRemote));
         $joinQ->where($fkLocal, 'eq', $localValue);
         $rawRelatedIDs = $joinQ->execute(false);
         $related = array();
         if (count($rawRelatedIDs) > 0) {
             $relatedIDs = array();
             foreach ($rawRelatedIDs as $row) {
                 $relatedIDs[] = $row->{$fkRemote};
             }
             $lQ = One_Repository::selectQuery($target);
             $lQ->where($targetId, 'in', $relatedIDs);
             $lQ->setOptions($options);
             $nRelated = $lQ->getCount();
         }
     }
     return $nRelated;
 }