/** * 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); } } }
/** * 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; }
/** * Get the value * * @param One_Model $model * @return Mixed */ public function getValue($model) { if (!$model) { return null; } // pick up vars entered entered from an invalidly filled in form $session = One_Repository::getSession(); $posted = $session->get('posted', 'OneFormErrors'); if (!in_array($this->getCfg('one'), array('one', 'yes', 'true', '1')) && isset($posted['oneForm'][$this->getName()])) { return $posted['oneForm'][$this->getName()]; } else { if (isset($posted[$this->getName()])) { return $posted[$this->getName()]; } else { $role = $this->getCfg('role'); if (!is_null($role) && $model instanceof One_Model) { $parts = explode(':', $role); $related = $model->getRelated($parts[1]); $relation = One_Repository::getRelation($parts[0]); $role = $relation->getRole($parts[1]); $relScheme = One_Repository::getScheme($role->schemeName); if ($related instanceof One_Model) { return $related[$relScheme->getIdentityAttribute()->getName()]; } elseif (is_array($related)) { // $related is an array of One_Models $returnValues = array(); foreach ($related as $r) { $returnValues[] = $r[$relScheme->getIdentityAttribute()->getName()]; } return $returnValues; } } else { //PD16FEB10 : add option to pick this up from request if ($this->getCfg('from') != "") { list($source, $key) = preg_split("/:/", $this->getCfg('from')); switch ($source) { case 'request': $from = $_REQUEST; if (!in_array($this->getCfg('one'), array('one', 'yes', 'true', '1'))) { $from = $_REQUEST['oneForm']; } if (isset($from[$key])) { return $from[$key]; } break; } } if ($this->getCfg('novalue') != "novalue") { return $model[$this->getOriginalName()]; } } } } }
/** * Set links for the scheme when present * * @param One_Scheme $scheme * @param DOMXPath $xpath * @param DOMElement $meta */ protected static function setRelationships(One_Scheme $scheme, DOMXPath $xpath, DOMElement $meta) { // create the link set for this scheme $relations = $xpath->query($meta->getNodePath() . '/relations/relation'); for ($i = 0; $i < $relations->length; $i++) { $relationSpec = $relations->item($i); $relation = One_Repository::getRelation($relationSpec->getAttribute('name')); $relation->createLinks($scheme); } }