<commit_before><?php

// Copyright (C) 2010-2015 Combodo SARL
//
//   This file is part of iTop.
//
//   iTop is free software; you can redistribute it and/or modify	
//   it under the terms of the GNU Affero General Public License as published by
//   the Free Software Foundation, either version 3 of the License, or
//   (at your option) any later version.
//
//   iTop is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU Affero General Public License for more details.
//
//   You should have received a copy of the GNU Affero General Public License
//   along with iTop. If not, see <http://www.gnu.org/licenses/>

namespace Combodo\iTop\Portal\Controller;

use \Silex\Application;
use \Symfony\Component\HttpFoundation\Request;
use \UserRights;
use \CMDBSource;
use \MetaModel;
use \AttributeDefinition;
use \AttributeDate;
use \AttributeDateTime;
use \DBSearch;
use \DBObjectSearch;
use \DBObjectSet;
use \FieldExpression;
use \BinaryExpression;
use \VariableExpression;
use \SQLExpression;
use \UnaryExpression;
use \Dict;
use \Combodo\iTop\Portal\Helper\ApplicationHelper;
use \Combodo\iTop\Portal\Helper\SecurityHelper;
use \Combodo\iTop\Portal\Brick\AbstractBrick;
use \Combodo\iTop\Portal\Brick\ManageBrick;

class ManageBrickController extends BrickController
{

	public function DisplayAction(Request $oRequest, Application $oApp, $sBrickId, $sGroupingTab, $sDataLoading = null)
	{
		$oBrick = ApplicationHelper::GetLoadedBrickFromId($oApp, $sBrickId);

		$aData = array();
		$aGroupingTabsValues = array();
		$aGroupingAreasValues = array();
		$aQueries = array();

		// Getting current dataloading mode (First from router parameter, then query parameter, then default brick value)
		$sDataLoading = ($sDataLoading !== null) ? $sDataLoading : ( ($oRequest->query->get('sDataLoading') !== null) ? $oRequest->query->get('sDataLoading') : $oBrick->GetDataLoading() );
		// Getting search value
		$sSearchValue = $oRequest->get('sSearchValue', null);

		// Starting to build query
		$oQuery = DBSearch::FromOQL($oBrick->GetOql());

		// - Adding search clause if necessary
		// Note : This is a very naive search at the moment
		if ($sSearchValue !== null)
		{
			$aSearchListItems = MetaModel::GetZListItems($oQuery->GetClass(), 'standard_search');
			$oFullBinExpr = null;
			for ($i = 0; $i < count($aSearchListItems); $i++)
			{
				$sSearchItemAttr = $aSearchListItems[$i];
				$oBinExpr = new BinaryExpression(new FieldExpression($sSearchItemAttr, $oQuery->GetClassAlias()), 'LIKE', new VariableExpression('search_value'));

				// At each iteration we build the complete expression for the search like ( (field1 LIKE %search%) OR (field2 LIKE %search%) OR (field3 LIKE %search%) ...)
				if ($i === 0)
				{
					$oFullBinExpr = $oBinExpr;
				}
				else
				{
					$oFullBinExpr = new BinaryExpression($oFullBinExpr, 'OR', $oBinExpr);
				}

				// Then on the last iteration we add the complete expression to the query
				// Note : We don't do it after the loop as there could be an empty search ZList
				if ($i === (count($aSearchListItems) - 1))
				{
					// - Adding expression to the query
					$oQuery->AddConditionExpression($oFullBinExpr);
					// - Setting expression parameters
					// Note : This could be way more simpler if we had a SetInternalParam($sParam, $value) verb
					$aQueryParams = $oQuery->GetInternalParams();
					$aQueryParams['search_value'] = '%' . $sSearchValue . '%';
					$oQuery->SetInternalParams($aQueryParams);
				}
			}
		}

		// Preparing tabs
		// - We need to retrieve distinct values for the grouping attribute
		if ($oBrick->HasGroupingTabs())
		{
			$aGroupingTabs = $oBrick->GetGroupingTabs();

			// If tabs are made of the distinct values of an attribute, we have a find them via a query
			if ($oBrick->IsGroupingTabsByDistinctValues())
			{
				$sGroupingTabAttCode = $aGroupingTabs['attribute'];

				$oDistinctQuery = DBSearch::FromOQL($oBrick->GetOql());
				$oFieldExp = new FieldExpression($sGroupingTabAttCode, $oDistinctQuery->GetClassAlias());
				$sDistinctSql = $oDistinctQuery->MakeGroupByQuery(array(), array('grouped_by_1' => $oFieldExp), true);
				$aDistinctResults = CMDBSource::QueryToArray($sDistinctSql);

				if (!empty($aDistinctResults))
				{
					foreach ($aDistinctResults as $aDistinctResult)
					{
						$oConditionQuery = DBSearch::CloneWithAlias($oQuery, 'GTAB');
						$oExpression = new BinaryExpression(new FieldExpression($sGroupingTabAttCode, $oDistinctQuery->GetClassAlias()), '=', new UnaryExpression($aDistinctResult['grouped_by_1']));
						$oConditionQuery->AddConditionExpression($oExpression);

						$aGroupingTabsValues[$aDistinctResult['grouped_by_1']] = array(
							'value' => $aDistinctResult['grouped_by_1'],
							'label' => strip_tags($oFieldExp->MakeValueLabel($oDistinctQuery, $aDistinctResult['grouped_by_1'], '')),
							'condition' => $oConditionQuery,
							'count' => $aDistinctResult['_itop_count_']
						);
						unset($oConditionQuery);
					}
					unset($aDistinctResults);
				}
				else
				{
					$aGroupingTabsValues['undefined'] = array(
						'value' => 'undefined',
						'label' => '',
						'condition' => null,
						'count' => null
					);
				}
			}
			// Otherwise we create the tabs from the SQL expressions
			else
			{
				foreach ($aGroupingTabs['groups'] as $aGroup)
				{
					$aGroupingTabsValues[$aGroup['id']] = array(
						'value' => $aGroup['id'],
						'label' => Dict::S($aGroup['title']),
						'condition' => DBSearch::FromOQL($aGroup['condition']),
						'count' => null
					);
				}
			}
		}
		// - Retrieving the current grouping tab to display and altering the query to do so
		if ($sGroupingTab === null)
		{
			if ($oBrick->HasGroupingTabs())
			{
				reset($aGroupingTabsValues);
				$sGroupingTab = key($aGroupingTabsValues);
				if ($aGroupingTabsValues[$sGroupingTab]['condition'] !== null)
				{
					$oQuery = $oQuery->Intersect($aGroupingTabsValues[$sGroupingTab]['condition']);
				}
			}
			else
			{
				// Do not group by tabs, display all in the same page
			}
		}
		else
		{
			if ($aGroupingTabsValues[$sGroupingTab]['condition'] !== null)
			{
				$oQuery = $oQuery->Intersect($aGroupingTabsValues[$sGroupingTab]['condition']);
			}
		}

		// Preparing areas
		// - We need to retrieve distinct values for the grouping attribute
		// Note : Will have to be changed when we consider grouping on something else than the finalclass
		$sParentAlias = $oQuery->GetClassAlias();
		if (true)
		{
			$sGroupingAreaAttCode = 'finalclass';

			// For root classes
			if (MetaModel::IsValidAttCode($oQuery->GetClass(), $sGroupingAreaAttCode))
			{
				$oDistinctQuery = DBSearch::FromOQL($oBrick->GetOql());
				$oFieldExp = new FieldExpression($sGroupingAreaAttCode, $sParentAlias);
				$sDistinctSql = $oDistinctQuery->MakeGroupByQuery(array(), array('grouped_by_1' => $oFieldExp), true);
				$aDistinctResults = CMDBSource::QueryToArray($sDistinctSql);

				foreach ($aDistinctResults as $aDistinctResult)
				{
					$oConditionQuery = DBSearch::CloneWithAlias($oQuery, 'GARE');
					$oExpression = new BinaryExpression(new FieldExpression($sGroupingAreaAttCode, 'GARE'), '=', new UnaryExpression($aDistinctResult['grouped_by_1']));
					$oConditionQuery->AddConditionExpression($oExpression);

					$aGroupingAreasValues[$aDistinctResult['grouped_by_1']] = array(
						'value' => $aDistinctResult['grouped_by_1'],
						'label' => MetaModel::GetName($aDistinctResult['grouped_by_1']), // Caution : This works only because we froze the grouping areas on the finalclass attribute.
						'condition' => $oConditionQuery,
						'count' => $aDistinctResult['_itop_count_']
					);
					unset($oConditionQuery);
				}<commit_msg>Customer portal : Fixed exception in ManageBrick that was looking for objects out of its scope<commit_after><?php

// Copyright (C) 2010-2015 Combodo SARL
//
//   This file is part of iTop.
//
//   iTop is free software; you can redistribute it and/or modify	
//   it under the terms of the GNU Affero General Public License as published by
//   the Free Software Foundation, either version 3 of the License, or
//   (at your option) any later version.
//
//   iTop is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU Affero General Public License for more details.
//
//   You should have received a copy of the GNU Affero General Public License
//   along with iTop. If not, see <http://www.gnu.org/licenses/>

namespace Combodo\iTop\Portal\Controller;

use \Silex\Application;
use \Symfony\Component\HttpFoundation\Request;
use \UserRights;
use \CMDBSource;
use \MetaModel;
use \AttributeDefinition;
use \AttributeDate;
use \AttributeDateTime;
use \DBSearch;
use \DBObjectSearch;
use \DBObjectSet;
use \FieldExpression;
use \BinaryExpression;
use \VariableExpression;
use \SQLExpression;
use \UnaryExpression;
use \Dict;
use \Combodo\iTop\Portal\Helper\ApplicationHelper;
use \Combodo\iTop\Portal\Helper\SecurityHelper;
use \Combodo\iTop\Portal\Brick\AbstractBrick;
use \Combodo\iTop\Portal\Brick\ManageBrick;

class ManageBrickController extends BrickController
{

	public function DisplayAction(Request $oRequest, Application $oApp, $sBrickId, $sGroupingTab, $sDataLoading = null)
	{
		$oBrick = ApplicationHelper::GetLoadedBrickFromId($oApp, $sBrickId);

		$aData = array();
		$aGroupingTabsValues = array();
		$aGroupingAreasValues = array();
		$aQueries = array();

		// Getting current dataloading mode (First from router parameter, then query parameter, then default brick value)
		$sDataLoading = ($sDataLoading !== null) ? $sDataLoading : ( ($oRequest->query->get('sDataLoading') !== null) ? $oRequest->query->get('sDataLoading') : $oBrick->GetDataLoading() );
		// Getting search value
		$sSearchValue = $oRequest->get('sSearchValue', null);

		// Starting to build query
		$oQuery = DBSearch::FromOQL($oBrick->GetOql());

		// - Adding search clause if necessary
		// Note : This is a very naive search at the moment
		if ($sSearchValue !== null)
		{
			$aSearchListItems = MetaModel::GetZListItems($oQuery->GetClass(), 'standard_search');
			$oFullBinExpr = null;
			for ($i = 0; $i < count($aSearchListItems); $i++)
			{
				$sSearchItemAttr = $aSearchListItems[$i];
				$oBinExpr = new BinaryExpression(new FieldExpression($sSearchItemAttr, $oQuery->GetClassAlias()), 'LIKE', new VariableExpression('search_value'));

				// At each iteration we build the complete expression for the search like ( (field1 LIKE %search%) OR (field2 LIKE %search%) OR (field3 LIKE %search%) ...)
				if ($i === 0)
				{
					$oFullBinExpr = $oBinExpr;
				}
				else
				{
					$oFullBinExpr = new BinaryExpression($oFullBinExpr, 'OR', $oBinExpr);
				}

				// Then on the last iteration we add the complete expression to the query
				// Note : We don't do it after the loop as there could be an empty search ZList
				if ($i === (count($aSearchListItems) - 1))
				{
					// - Adding expression to the query
					$oQuery->AddConditionExpression($oFullBinExpr);
					// - Setting expression parameters
					// Note : This could be way more simpler if we had a SetInternalParam($sParam, $value) verb
					$aQueryParams = $oQuery->GetInternalParams();
					$aQueryParams['search_value'] = '%' . $sSearchValue . '%';
					$oQuery->SetInternalParams($aQueryParams);
				}
			}
		}

		// Preparing tabs
		// - We need to retrieve distinct values for the grouping attribute
		if ($oBrick->HasGroupingTabs())
		{
			$aGroupingTabs = $oBrick->GetGroupingTabs();

			// If tabs are made of the distinct values of an attribute, we have a find them via a query
			if ($oBrick->IsGroupingTabsByDistinctValues())
			{
				$sGroupingTabAttCode = $aGroupingTabs['attribute'];

				$oDistinctQuery = DBSearch::FromOQL($oBrick->GetOql());
				$oFieldExp = new FieldExpression($sGroupingTabAttCode, $oDistinctQuery->GetClassAlias());
				$sDistinctSql = $oDistinctQuery->MakeGroupByQuery(array(), array('grouped_by_1' => $oFieldExp), true);
				$aDistinctResults = CMDBSource::QueryToArray($sDistinctSql);

				if (!empty($aDistinctResults))
				{
					foreach ($aDistinctResults as $aDistinctResult)
					{
						$oConditionQuery = DBSearch::CloneWithAlias($oQuery, 'GTAB');
						$oExpression = new BinaryExpression(new FieldExpression($sGroupingTabAttCode, $oDistinctQuery->GetClassAlias()), '=', new UnaryExpression($aDistinctResult['grouped_by_1']));
						$oConditionQuery->AddConditionExpression($oExpression);

						$aGroupingTabsValues[$aDistinctResult['grouped_by_1']] = array(
							'value' => $aDistinctResult['grouped_by_1'],
							'label' => strip_tags($oFieldExp->MakeValueLabel($oDistinctQuery, $aDistinctResult['grouped_by_1'], '')),
							'condition' => $oConditionQuery,
							'count' => $aDistinctResult['_itop_count_']
						);
						unset($oConditionQuery);
					}
					unset($aDistinctResults);
				}
				else
				{
					$aGroupingTabsValues['undefined'] = array(
						'value' => 'undefined',
						'label' => '',
						'condition' => null,
						'count' => null
					);
				}
			}
			// Otherwise we create the tabs from the SQL expressions
			else
			{
				foreach ($aGroupingTabs['groups'] as $aGroup)
				{
					$aGroupingTabsValues[$aGroup['id']] = array(
						'value' => $aGroup['id'],
						'label' => Dict::S($aGroup['title']),
						'condition' => DBSearch::FromOQL($aGroup['condition']),
						'count' => null
					);
				}
			}
		}
		// - Retrieving the current grouping tab to display and altering the query to do so
		if ($sGroupingTab === null)
		{
			if ($oBrick->HasGroupingTabs())
			{
				reset($aGroupingTabsValues);
				$sGroupingTab = key($aGroupingTabsValues);
				if ($aGroupingTabsValues[$sGroupingTab]['condition'] !== null)
				{
					$oQuery = $oQuery->Intersect($aGroupingTabsValues[$sGroupingTab]['condition']);
				}
			}
			else
			{
				// Do not group by tabs, display all in the same page
			}
		}
		else
		{
			if ($aGroupingTabsValues[$sGroupingTab]['condition'] !== null)
			{
				$oQuery = $oQuery->Intersect($aGroupingTabsValues[$sGroupingTab]['condition']);
			}
		}

		// Preparing areas
		// - We need to retrieve distinct values for the grouping attribute
		// Note : Will have to be changed when we consider grouping on something else than the finalclass
		$sParentAlias = $oQuery->GetClassAlias();
		if (true)
		{
			$sGroupingAreaAttCode = 'finalclass';

			// For root classes
			if (MetaModel::IsValidAttCode($oQuery->GetClass(), $sGroupingAreaAttCode))
			{
				$oDistinctQuery = DBSearch::FromOQL($oBrick->GetOql());
				// Checking if there is a scope to apply
				$oDistinctScopeQuery = $oApp['scope_validator']->GetScopeFilterForProfiles(UserRights::ListProfiles(), $oQuery->GetClass(), UR_ACTION_READ);
				if ($oDistinctScopeQuery != null)
				{
					$oDistinctQuery = $oDistinctQuery->Intersect($oDistinctScopeQuery);
				}
				// Adding grouping conditions
				$oFieldExp = new FieldExpression($sGroupingAreaAttCode, $sParentAlias);
				$sDistinctSql = $oDistinctQuery->MakeGroupByQuery(array(), array('grouped_by_1' => $oFieldExp), true);
				$aDistinctResults = CMDBSource::QueryToArray($sDistinctSql);

				foreach ($aDistinctResults as $aDistinctResult)
				{
					$oConditionQuery = DBSearch::CloneWithAlias($oQuery, 'GARE');
					$oExpression = new BinaryExpression(new FieldExpression($sGroupingAreaAttCode, 'GARE'), '=', new UnaryExpression($aDistinctResult['grouped_by_1']));
					$oConditionQuery->AddConditionExpression($oExpression);

					$aGroupingAreasValues[$aDistinctResult['grouped_by_1']] = array(
						'value' => $aDistinctResult['grouped_by_1'],
						'label' => MetaModel::GetName($aDistinctResult['grouped_by_1']), // Caution : This works only because we froze the grouping areas on the finalclass attribute.
						'condition' => $oConditionQuery,
						'count' => $aDistinctResult['_itop_count_']
					);
					unset($oConditionQuery);
				}
{'fraction_non_alphanumeric': 0.13355654761904762, 'fraction_numerical': 0.0031001984126984125, 'mean_word_length': 3.9919529557412567, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 102, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '987504', 'n_tokens_mistral': 6002, 'n_tokens_neox': 5041, 'n_words': 1240}