parser

Написать ответ на текущее сообщение

 

 
   команды управления поиском

Ответ

Misha v.3 21.06.2014 06:01 / 21.06.2014 08:35

на самом деле я обманул: на схеме evgine v.4 не указаны некоторые поля, т.к. они были добавлены только в v.5, но это случилось ещё в 2008 году, просто лень было обновлять описание.

в engine есть встроенный аналог rewrite. для его реализации добавлены поля object.child_handling_type_id -- тип рерайта (бывает два: 1 -- рерайты обрабатывает текущий объект, 2 -- рерайты обрабатывает другой объект) и object.child_handler_object_id -- ссылка на объект, обрабатывающий rewrite-ы типа 2.

программисту в обработчиках (это выполняющийся код на парсере) доступен объект $hRewrite, в котором хранится информация о произошедшем рерайте.

1. рерайты первого типа:
объект САМ перехватывает обращения ко всем несуществующим наследникам. в этом случае в $hRewrite._ помещается нормализованная информация о куске URL, который находится после url текущего объекта.

если есть объект /branches/, у которого указано, что он сам обрабатывает обращения к несуществующим наследникам, при этом обратились по адресу /branches/centre/, то коду в обратотчике объекта /branches/ доступно $hRewrite._[centre].
при обращении по адресу /branches/centre/moscow/ коду в обработчике /branches/ доступно $hRewrite._[centre/moscow]


2. рерайты второго типа:
обработку обращений к несуществующим потомкам будет производить другой объект (какой -- указано в административном интерфейсе, это может быть вообще произвольный объект в другом месте сайта)
например есть объекты /branches/ и /branches/REGION/, первому указали, что обращения к несуществующим наследникам будут переадресовываться объекту /branches/REGION/.
при запросе /branches/ будет обрабатываться сам объект /branches/ (например отображающий список городов) при запросе /branches/centre/ будет обрабатываться объект /branches/REGION/ (с его обработчиком и шаблоном), при этом в обработчиках будет доступна информация: $hRewrite.REGION[centre].
если у нас ещё есть объект /branches/REGION/CITY/ и у объекта /branches/REGION/ указано, что все обращения к его несуществующим потомкам переадресовывать объекту /branches/REGION/CITY/, то всё вышеописанное будет продолжать работать, но вдобавок обращения по адресу /branches/centre/moscow/ будут приводить к обработке запроса объектом /branches/REGION/CITY/ (уже с его обработчиком и шаблоном), при этом в $hRewrite будут доступны $hRewrite.REGION[centre] и $hRewrite.CITY[moscow]. ключами в хеше $hRewrite являются пути объектов (path), которые не должны дублироваться (сделано для простоты), а значениями -- выкусываемые кусочки (один редирект приводит к выкусыванию одного кусочка). если при этом произойдёт обращение по адресу /branches/centre/moscow/tverskaya/, то будет выдана страница с 404 ошибкой, т.к. система не знает что делать с куском URL 'tverskaya'.

3.
предыдущие два пункта можно комбинировать и последнему объекту в цепочке переадресаций указать, что он сам обрабатывает обращения ко всем несуществующим наследникам.
в этом случае, если подобную опцию указать у рассматриваемого выше объекта /branches/REGION/CITY/, то обращение по адресу /branches/centre/moscow/tverskaya/ не будет приводить к 404 ошибке, а информация о последнем кусочке будет доступна: $hRewrite._[tverskaya]
при обращении по адресу /branches/centre/moscow/street/tverskaya/ -- $hRewrite._[street/tverskaya]


ну и код (если он кому-то нужен).
методы getObjectsByFullPath и getObjectsById не имеют ничего общего с живыми методами. в живых реализовано кеширование. метод findObjectByURI также несколько упрощён.
@findObjectByURI[sURI;hParams][...объявление локальных переменных...]
$hParams[^hash::create[$hParams]]
$hRewrite[^hash::create[]]
$bFound(false)
$result[
	$.hRewrite[$hRewrite]
	$.bFound(false)
	$.sError[]
	$.hOrigin[^hash::create[]]
	$.hCurrent[^hash::create[]]
	$.hLog[^hash::create[]]
]

$bContinue(true)
$iWatchDogCount(20)
$hRewrited[^hash::create[]]

^while($bContinue && $iWatchDogCount){
	$bContinue(false)
	$bFound(false)
	$tVisible[^self.getObjectsByFullPath[^self.getParentsFullPaths[$sURI];$hParams]]

	^if($tVisible){
		^if(^tVisible.locate[full_path;$sURI]){
			^rem{ *** object with specified URI exists *** }
			$result.hCurrent[$tVisible.fields]
			$bFound(true)
		}{
			^rem{ *** object with specified URI does not exist. check if engine's rewrites are used *** }
			^tVisible.offset[set](-1)
			$iTypeID($tVisible.child_handling_type_id)
			^if($iTypeID){
				^if($hRewrited.[$tVisible.id]){
					$result.sError[Infinite recursion while processing rewrites is detected]
				}{
					$hRewrited.[$tVisible.id](true)
					$hObject[$tVisible.fields]
					$sOriginURI[$sURI]

					$sTail[^sURI.mid(^hObject.full_path.length[])]

					^if(!def $hRewrite.sTail){
						^rem{ *** the 1st rewrite iteration *** }
						$hRewrite.sTail[$sTail]
						$result.hOrigin[$hObject]
					}
					^switch($iTypeID){
						^case(1){
							^rem{ *** handle nonexistent child by itself *** }
							$hRewrite._[^sTail.trim[both;/]]
							$result.hCurrent[$hObject]
							$bFound(true)
						}

						^case(2){
							^rem{ *** another object will handle nonexistent child => modify URL and search again *** }
							^rem{ *** cut 1st 'subdir' *** }
							$iPieceLength(^sTail.pos[/])
							^if($iPieceLength>0){
								$sPiece[^sTail.left($iPieceLength)]
								$sTail[^sTail.mid($iPieceLength+1)]
							}{
								$sPiece[$sTail]
								$sTail[]
							}

							$hHandler[^self.getObjectById($hObject.child_handler_object_id)]
							^if($hHandler){
								^if(^hRewrite.contains[$hHandler.path]){
									^rem{ *** for simplicity don't allow to have 2 handlers with the same path *** }
									$result.sError[Duplicate path while processing rewrites is found]
								}{
									$hRewrite.[$hHandler.path][$sPiece]
									$sURI[${hHandler.full_path}$sTail]
									$bContinue(true)
								}
							}{
								$result.sError[Link to not existed handler ($hObject.child_handler_object_id) is found]
							}
						}

						^case[DEFAULT]{
							$result.sError[Unknown rewrite type ($iTypeID)]
						}
					}

					$result.hLog.[^result.hLog._count[]][
						$.sOriginURI[$sOriginURI]
						$.iTypeID($iTypeID)
						$.sURI[$sURI]
						$.hRewrite[^hash::create[$hRewrite]]
					]
				}
			}
		}
	}
	^iWatchDogCount.dec[]
}

^if($iWatchDogCount==0){
	$result.sError[Too many cycles while processing rewrites]
}

$result.bFound($bFound)




@getParentsFullPaths[sFullPath][sURI;tURI]
$result[^table::create{sUri
/}]

$sFullPath[^sFullPath.trim[both;/]]

^if(def $sFullPath){
	$sURI[]
	$tURI[^sFullPath.split[/][vl]]
	^tURI.menu{
		$sURI[$sURI/$tURI.piece]
		^result.append{$sURI}
	}
}




@getObjectsByFullPath[tFullPath;hParams]
$reault[^table::sql{
	SELECT
		...
	FROM
		object
	WHERE
		full_path IN (^if($tFullPath){^tFullPath.menu{'$tFullPath.sUri'}[,]}{''})
		...
	ORDER BY
		full_path
}]




@getObjectById[iID]
$reault[^table::sql{
	SELECT
		...
	FROM
		object
	WHERE
		object_id = $iID
		...
}]