+ $aNewSearches = array();
+
+ if (($sPhraseType == '' || $sPhraseType == 'country')
+ && is_a($oSearchTerm, '\Nominatim\Token\Country')
+ ) {
+ if (!$this->sCountryCode) {
+ $oSearch = clone $this;
+ $oSearch->iSearchRank++;
+ $oSearch->sCountryCode = $oSearchTerm->sCountryCode;
+ // Country is almost always at the end of the string
+ // - increase score for finding it anywhere else (optimisation)
+ if (!$bLastToken) {
+ $oSearch->iSearchRank += 5;
+ }
+ $aNewSearches[] = $oSearch;
+ }
+ } elseif (($sPhraseType == '' || $sPhraseType == 'postalcode')
+ && is_a($oSearchTerm, '\Nominatim\Token\Postcode')
+ ) {
+ if (!$this->sPostcode) {
+ // If we have structured search or this is the first term,
+ // make the postcode the primary search element.
+ if ($this->iOperator == Operator::NONE && $bFirstToken) {
+ $oSearch = clone $this;
+ $oSearch->iSearchRank++;
+ $oSearch->iOperator = Operator::POSTCODE;
+ $oSearch->aAddress = array_merge($this->aAddress, $this->aName);
+ $oSearch->aName =
+ array($oSearchTerm->iId => $oSearchTerm->sPostcode);
+ $aNewSearches[] = $oSearch;
+ }
+
+ // If we have a structured search or this is not the first term,
+ // add the postcode as an addendum.
+ if ($this->iOperator != Operator::POSTCODE
+ && ($sPhraseType == 'postalcode' || !empty($this->aName))
+ ) {
+ $oSearch = clone $this;
+ $oSearch->iSearchRank++;
+ if (strlen($oSearchTerm->sPostcode) < 4) {
+ $oSearch->iSearchRank += 4 - strlen($oSearchTerm->sPostcode);
+ }
+ $oSearch->sPostcode = $oSearchTerm->sPostcode;
+ $aNewSearches[] = $oSearch;
+ }
+ }
+ } elseif (($sPhraseType == '' || $sPhraseType == 'street')
+ && is_a($oSearchTerm, '\Nominatim\Token\HouseNumber')
+ ) {
+ if (!$this->sHouseNumber && $this->iOperator != Operator::POSTCODE) {
+ $oSearch = clone $this;
+ $oSearch->iSearchRank++;
+ $oSearch->sHouseNumber = $oSearchTerm->sToken;
+ // sanity check: if the housenumber is not mainly made
+ // up of numbers, add a penalty
+ if (preg_match('/\\d/', $oSearch->sHouseNumber) === 0
+ || preg_match_all('/[^0-9]/', $oSearch->sHouseNumber, $aMatches) > 2) {
+ $oSearch->iSearchRank++;
+ }
+ if (empty($oSearchTerm->iId)) {
+ $oSearch->iSearchRank++;
+ }
+ // also must not appear in the middle of the address
+ if (!empty($this->aAddress)
+ || (!empty($this->aAddressNonSearch))
+ || $this->sPostcode
+ ) {
+ $oSearch->iSearchRank++;
+ }
+ $aNewSearches[] = $oSearch;
+ // Housenumbers may appear in the name when the place has its own
+ // address terms.
+ if ($oSearchTerm->iId !== null
+ && ($this->iNamePhrase >= 0 || empty($this->aName))
+ && empty($this->aAddress)
+ ) {
+ $oSearch = clone $this;
+ $oSearch->iSearchRank++;
+ $oSearch->aAddress = $this->aName;
+ $oSearch->bRareName = false;
+ $oSearch->aName = array($oSearchTerm->iId => $oSearchTerm->iId);
+ $aNewSearches[] = $oSearch;
+ }
+ }
+ } elseif ($sPhraseType == ''
+ && is_a($oSearchTerm, '\Nominatim\Token\SpecialTerm')
+ ) {
+ if ($this->iOperator == Operator::NONE) {
+ $oSearch = clone $this;
+ $oSearch->iSearchRank++;
+
+ $iOp = $oSearchTerm->iOperator;
+ if ($iOp == Operator::NONE) {
+ if (!empty($this->aName) || $this->oContext->isBoundedSearch()) {
+ $iOp = Operator::NAME;
+ } else {
+ $iOp = Operator::NEAR;
+ }
+ $oSearch->iSearchRank += 2;
+ }
+
+ $oSearch->setPoiSearch(
+ $iOp,
+ $oSearchTerm->sClass,
+ $oSearchTerm->sType
+ );
+ $aNewSearches[] = $oSearch;
+ }
+ } elseif ($sPhraseType != 'country'
+ && is_a($oSearchTerm, '\Nominatim\Token\Word')
+ ) {
+ $iWordID = $oSearchTerm->iId;
+ // Full words can only be a name if they appear at the beginning
+ // of the phrase. In structured search the name must forcably in
+ // the first phrase. In unstructured search it may be in a later
+ // phrase when the first phrase is a house number.
+ if (!empty($this->aName) || !($bFirstPhrase || $sPhraseType == '')) {
+ if (($sPhraseType == '' || !$bFirstPhrase) && !$bHasPartial) {
+ $oSearch = clone $this;
+ $oSearch->iSearchRank += 3 * $oSearchTerm->iTermCount;
+ $oSearch->aAddress[$iWordID] = $iWordID;
+ $aNewSearches[] = $oSearch;
+ }
+ } else {
+ $oSearch = clone $this;
+ $oSearch->iSearchRank++;
+ $oSearch->aName = array($iWordID => $iWordID);
+ if (CONST_Search_NameOnlySearchFrequencyThreshold) {
+ $oSearch->bRareName =
+ $oSearchTerm->iSearchNameCount
+ < CONST_Search_NameOnlySearchFrequencyThreshold;
+ }
+ $aNewSearches[] = $oSearch;
+ }
+ }
+
+ return $aNewSearches;