%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /home/bitrix/www/bitrix/modules/learning/classes/general/
Upload File :
Create Path :
Current File : /home/bitrix/www/bitrix/modules/learning/classes/general/clearnhelper.php

<?php

/**
 * WARNING: nobody shouldn't rely on this code,
 * because it's FOR INTERNAL USE ONLY. Any declared
 * function can be removed or changed in future versions.
 * This code can be changed without any notifications.
 * DON'T USE it nowhere.
 *
 * @deprecated
 *
 * @access private
 */
class CLearnHelper
{
	const GRAPH_STATUS_NOT_SET          = '1';		// status wasn't set yet (we must determine, is our tables updated to graph or not)
	const GRAPH_STATUS_LEGACY           = '2';
	const GRAPH_STATUS_UPDATED_TO_GRAPH = '3';
	const GRAPH_STATUS_UNDEFINED        = '4';

	const MODULE_ID     = 'learning';
	const OPTION_ID     = '~CLearnHelper::isUpdatedToGraph();';
	const DEFAULT_VALUE = self::GRAPH_STATUS_NOT_SET;		// be default
	const SITE_ID       = '';		// request shared options for all sites

	const ACCESS_READ   = 0x001;
	const ACCESS_MODIFY = 0x003;	// includes ACCESS_READ

	/**
	 * Don't relay on this function, it can be removed without any notifications.
	 * @deprecated
	 */
	public static function PatchLessonContentLinks($strContent, $contextCourseId = false)
	{
		static $arCourseLinksPatterns = array(
			'?COURSE_ID={SELF}"',
			'?COURSE_ID={SELF}\'',
			'?COURSE_ID={SELF}&',
			'&COURSE_ID={SELF}"',
			'&COURSE_ID={SELF}\'',
			'&COURSE_ID={SELF}&'
		);

		$argsCheck = is_string($strContent)
			&& ($contextCourseId !== false)
			&& ($contextCourseId > 0);

		if ( ! $argsCheck )
			return ($strContent);

		$arCourseResolvedLinks = str_replace(
			'{SELF}', 
			(string) ((int) $contextCourseId),
			$arCourseLinksPatterns
		);

		$rc = str_replace(
			$arCourseLinksPatterns, 
			$arCourseResolvedLinks, 
			$strContent
		);

		return ($rc);
	}


	/**
	 * @return void
	 */
	public static function FireEvent ($eventName, $eventParams)
	{
		$events = GetModuleEvents('learning', $eventName);
		while ($arEvent = $events->Fetch())
			ExecuteModuleEventEx($arEvent, array($eventParams));
	}


	/**
	 * This function builds subquery (for oracle) or comma-separated
	 * list of lessons IDs (for mysql/mssql) for SQL WHERE clause, 
	 * which selects/contains all child lessons (only childs, 
	 * without parent lesson). This functions prevents cycling.
	 * 
	 * Warning: currently
	 * 
	 * @example
	 * on oracle SQLClauseForAllSubLessons(13) returns subquery:
	 * SELECT b_learn_lesson_edges.TARGET_NODE
	 * FROM b_learn_lesson_edges
	 * START WITH b_learn_lesson_edges.SOURCE_NODE=13
	 * CONNECT BY NOCYCLE PRIOR b_learn_lesson_edges.TARGET_NODE = b_learn_lesson_edges.SOURCE_NODE
	 * 
	 * on mysql/mssql SQLClauseForAllSubLessons(13) returns list of child lessons:
	 * 14, 16, 120, 875, 476
	 * 
	 * Any of this strings can be used in WHERE IN(...our string...) clause.
	 * 
	 * Complete example:
	 * <?php
	 * $parentLessonId = 447;
	 * $clauseChilds = CLearnHelper::SQLClauseForAllSubLessons($parentLessonId);
	 * $strSql = "
	 * SELECT * 
	 * FROM b_learn_lesson 
	 * WHERE ID IN ($clauseChilds) OR (ID = $parentLessonId)";
	 * // Selects list of all childs with parentLessonId included.
	 * $CDBresult = $DB->Query ($strSql);
	 * 
	 * @param int parent lesson id
	 * @return string for using in WHERE IN() clause: sql subquery or 
	 * comma-separated list of lesson's ids.
	 */
	public static function SQLClauseForAllSubLessons ($parentLessonId)
	{
		global $DBType;

		if ( ! (
			is_numeric($parentLessonId) 
			&& is_int($parentLessonId + 0) 
			) 
		)
		{
			throw new LearnException (
				'$parentLessonId must be strictly castable to integer', 
				LearnException::EXC_ERR_ALL_PARAMS);
		}

		if ($DBType === 'oracle')
		{
			// This subquery gets ids of all childs lesson for given $parentLessonId
			$rc = "
				SELECT b_learn_lesson_edges.TARGET_NODE
				FROM b_learn_lesson_edges
				START WITH b_learn_lesson_edges.SOURCE_NODE=" . ($parentLessonId + 0) . "
				CONNECT BY NOCYCLE PRIOR b_learn_lesson_edges.TARGET_NODE = b_learn_lesson_edges.SOURCE_NODE";
		
			return ($rc);
		}
		elseif (($DBType === 'mysql') || ($DBType === 'mssql'))
		{
			// MySQL & MSSQL supports "WHERE IN(...)" clause for more than 10 000 elements

			$oTree = CLearnLesson::GetTree($parentLessonId, array('EDGE_SORT' => 'ASC'), array('CHECK_PERMISSIONS' => 'N'));
			$arChildLessonsIds = $oTree->GetLessonsIdListInTree();	// parent lesson id isn't included

			// We need escape data for SQL
			$arChildLessonsIdsEscaped = array_map('intval', $arChildLessonsIds);

			$sqlChildLessonsIdsList = implode (', ', $arChildLessonsIdsEscaped);
			
			// No childs => nothing must be selected
			if (strlen($sqlChildLessonsIdsList) == 0)
				$sqlChildLessonsIdsList = 'NULL';		// NULL != any value. NULL != NULL too.

			return ($sqlChildLessonsIdsList);
		}
	}


	/**
	 * Linked from CAllCourse::MkOperationFilter($key);
	 * This code writed not by me, but I rely on it in good state
	 */
	public static function MkOperationFilter($key)
	{
		if(substr($key, 0, 1)=="=") //Identical
		{
			$key = substr($key, 1);
			$cOperationType = "I";
		}
		elseif(substr($key, 0, 2)=="!=") //not Identical
		{
			$key = substr($key, 2);
			$cOperationType = "NI";
		}
		elseif(substr($key, 0, 1)=="%") //substring
		{
			$key = substr($key, 1);
			$cOperationType = "S";
		}
		elseif(substr($key, 0, 2)=="!%") //not substring
		{
			$key = substr($key, 2);
			$cOperationType = "NS";
		}
		elseif(substr($key, 0, 1)=="?") //logical
		{
			$key = substr($key, 1);
			$cOperationType = "?";
		}
		elseif(substr($key, 0, 2)=="><") //between
		{
			$key = substr($key, 2);
			$cOperationType = "B";
		}
		elseif(substr($key, 0, 3)=="!><") //not between
		{
			$key = substr($key, 3);
			$cOperationType = "NB";
		}
		elseif(substr($key, 0, 2)==">=") //greater or equal
		{
			$key = substr($key, 2);
			$cOperationType = "GE";
		}
		elseif(substr($key, 0, 1)==">")  //greater
		{
			$key = substr($key, 1);
			$cOperationType = "G";
		}
		elseif(substr($key, 0, 2)=="<=")  //less or equal
		{
			$key = substr($key, 2);
			$cOperationType = "LE";
		}
		elseif(substr($key, 0, 1)=="<")  //less
		{
			$key = substr($key, 1);
			$cOperationType = "L";
		}
		elseif(substr($key, 0, 1)=="!") // not field LIKE val
		{
			$key = substr($key, 1);
			$cOperationType = "N";
		}
		else
			$cOperationType = "E";	// field LIKE val

		return Array("FIELD"=>$key, "OPERATION"=>$cOperationType);
	}

	/**
	 * This code writed not by me, but I rely on it in good state
	 */
	public static function FilterCreate($fname, $vals, $type, &$bFullJoin, $cOperationType=false, $bSkipEmpty = true)
	{
		global $DB;
		if(!is_array($vals))
			$vals=Array($vals);

		if(count($vals)<1)
			return "";

		if(is_bool($cOperationType))
		{
			if($cOperationType===true)
				$cOperationType = "N";
			else
				$cOperationType = "E";
		}

		if($cOperationType=="G")
			$strOperation = ">";
		elseif($cOperationType=="GE")
			$strOperation = ">=";
		elseif($cOperationType=="LE")
			$strOperation = "<=";
		elseif($cOperationType=="L")
			$strOperation = "<";
		else
			$strOperation = "=";

		$bFullJoin = false;
		$bWasLeftJoin = false;

		$res = Array();
		for($i=0; $i<count($vals); $i++)
		{
			$val = $vals[$i];

			if(!$bSkipEmpty || strlen($val)>0 || (is_bool($val) && $val===false))
			{
				switch ($type)
				{
				case "string_equal":
					if(strlen($val)<=0)
						$res[] =
						($cOperationType=="N"?"NOT":"").
						"(".
						$fname." IS NULL OR ".$DB->Length($fname).
						"<=0)";
					else
						$res[] =
						"(".
						($cOperationType=="N"?" ".$fname." IS NULL OR NOT (":"").
						CCourse::_Upper($fname).$strOperation.CCourse::_Upper("'".$DB->ForSql($val)."'").
						($cOperationType=="N"?")":"").
						")";
					break;
				case "string":
					if($cOperationType=="?")
					{
						if(strlen($val)>0)
							$res[] = GetFilterQuery($fname, $val, "Y",array(),"N");
					}
					elseif(strlen($val)<=0)
					{
						$res[] = ($cOperationType=="N"?"NOT":"")."(".$fname." IS NULL OR ".$DB->Length($fname)."<=0)";
					}
					else
					{
						if($strOperation=="=")
							$res[] =
							"(".
							($cOperationType=="N"?" ".$fname." IS NULL OR NOT (":"").
							(strtoupper($DB->type)=="ORACLE"?CCourse::_Upper($fname)." LIKE ".CCourse::_Upper("'".$DB->ForSqlLike($val)."'")." ESCAPE '\\'" : $fname." ".($strOperation=="="?"LIKE":$strOperation)." '".$DB->ForSqlLike($val)."'").
							($cOperationType=="N"?")":"").
							")";
						else
							$res[] =
							"(".
							($cOperationType=="N"?" ".$fname." IS NULL OR NOT (":"").
							(strtoupper($DB->type)=="ORACLE"?CCourse::_Upper($fname).
							" ".$strOperation." ".CCourse::_Upper("'".$DB->ForSql($val)."'")." " : $fname." ".$strOperation." '".$DB->ForSql($val)."'").
							($cOperationType=="N"?")":"").
							")";
					}
					break;
				case "date":
					if(strlen($val)<=0)
						$res[] = ($cOperationType=="N"?"NOT":"")."(".$fname." IS NULL)";
					else
						$res[] =
						"(".
						($cOperationType=="N"?" ".$fname." IS NULL OR NOT (":"").
						$fname." ".$strOperation." ".$DB->CharToDateFunction($DB->ForSql($val), "FULL").
						($cOperationType=="N"?")":"").
						")";
					break;
				case "number":
					if(strlen($val)<=0)
						$res[] = ($cOperationType=="N"?"NOT":"")."(".$fname." IS NULL)";
					else
						$res[] =
						"(".
						($cOperationType=="N"?" ".$fname." IS NULL OR NOT (":"").
						$fname." ".$strOperation." '".DoubleVal($val).
						($cOperationType=="N"?"')":"'").
						")";
					break;
				/*
				case "number_above":
					if(strlen($val)<=0)
						$res[] = ($cOperationType=="N"?"NOT":"")."(".$fname." IS NULL)";
					else
						$res[] = ($cOperationType=="N"?" ".$fname." IS NULL OR NOT ":"")."(".$fname." ".$strOperation." '".$DB->ForSql($val)."')";
					break;
				*/
				}

				// INNER JOIN in this case
				if(strlen($val)>0 && $cOperationType!="N")
					$bFullJoin = true;
				else
					$bWasLeftJoin = true;
			}
		}

		$strResult = "";
		for($i=0; $i<count($res); $i++)
		{
			if($i>0)
				$strResult .= ($cOperationType=="N"?" AND ":" OR ");
			$strResult .= $res[$i];
		}

		if (count($res) > 1)
			$strResult = "(".$strResult.")";


		if($bFullJoin && $bWasLeftJoin && $cOperationType!="N")
			$bFullJoin = false;

		return $strResult;
	}

	/**
	 * @return boolean true, if data tables updated to graph (new native mode)
	 *                 otherwise returns false (it means, we must work in legacy mode)
	 */
	public static function isUpdatedToGraph()
	{
		if (self::getUpdatedToGraphStatus() === self::GRAPH_STATUS_UPDATED_TO_GRAPH)
			return true;
		else
			return false;
	}

	/**
	 * @param string $status one of this values:
	 *    self::GRAPH_STATUS_LEGACY - if not updated to grpah yet (legacy mode)
	 *    self::GRAPH_STATUS_UPDATED_TO_GRAPH - if updated to graph,
	 *    self::GRAPH_STATUS_UNDEFINED - if status is undefined (update in progress or interrupted)
	 * @return boolean true if saved successfully, false otherwise.
	 */
	public static function setUpdatedToGraphStatus($status)
	{
		$description = '';

		$isSaved = COption::SetOptionString(self::MODULE_ID, self::OPTION_ID,
			$status, $description, self::SITE_ID);

		return ($isSaved);
	}

	/**
	 * @return string $status one of this values:
	 *    self::GRAPH_STATUS_LEGACY - if not updated to graph (it means, we must work in legacy mode)
	 *    self::GRAPH_STATUS_UPDATED_TO_GRAPH - if update to graph,
	 *    self::GRAPH_STATUS_UNDEFINED - if status is undefined (update in progress or interrupted)
	 */
	public static function getUpdatedToGraphStatus()
	{

		$rc = COption::GetOptionString(self::MODULE_ID, self::OPTION_ID, self::DEFAULT_VALUE, self::SITE_ID);

		// status wasn't set yet (we must determine, is our tables updated to graph or not)
		if ($rc === self::DEFAULT_VALUE)
		{
			// Set determined mode in global options
			self::setUpdatedToGraphStatus(self::GRAPH_STATUS_LEGACY);
		}

		$allowed_statuses = array (
			self::GRAPH_STATUS_LEGACY,
			self::GRAPH_STATUS_UPDATED_TO_GRAPH,
			self::GRAPH_STATUS_UNDEFINED
			);

		if ( ! in_array($rc, $allowed_statuses, true) )
		{
			AddMessage2Log('Invalid COption ~CLearnHelper::isUpdatedToGraph();: `'
				. $rc . '`;', 'learning');

			$rc = self::GRAPH_STATUS_UNDEFINED;
		}

		return ($rc);
	}


	public static function IsBaseFilenameSafe($filename)
	{

		$isUnSafe = IsFileUnsafe($filename) 
			|| HasScriptExtension($filename)
			|| ( ! (preg_match("#^[^\\\/:*?\"\'~%<>|]+$#is", $filename) > 0) );

		return ( ! $isUnSafe );
	}


	public static function CopyDirFiles($path_from, $path_to, $ReWrite = True, $Recursive = False)
	{
		if (strpos($path_to."/", $path_from."/")===0 || realpath($path_to) === realpath($path_from))
			return false;

		if (is_dir($path_from))
		{
			CheckDirPath($path_to."/");
		}
		elseif(is_file($path_from))
		{
			$p = bxstrrpos($path_to, "/");
			$path_to_dir = substr($path_to, 0, $p);
			CheckDirPath($path_to_dir."/");

			if (file_exists($path_to) && !$ReWrite)
				return False;

			@copy($path_from, $path_to);
			if(is_file($path_to))
				@chmod($path_to, BX_FILE_PERMISSIONS);

			return True;
		}
		else
		{
			return True;
		}

		if ($handle = @opendir($path_from))
		{
			while (($file = readdir($handle)) !== false)
			{
				if ($file == "." || $file == "..")
					continue;

				// skip files with non-safe names
				if ( ! CLearnHelper::IsBaseFilenameSafe($file) )
					continue;

				if (is_dir($path_from."/".$file) && $Recursive)
				{
					self::CopyDirFiles($path_from."/".$file, $path_to."/".$file, $ReWrite, $Recursive);
				}
				elseif (is_file($path_from."/".$file))
				{
					if (file_exists($path_to."/".$file) && !$ReWrite)
						continue;

					@copy($path_from."/".$file, $path_to."/".$file);
					@chmod($path_to."/".$file, BX_FILE_PERMISSIONS);
				}
			}
			@closedir($handle);

			return true;
		}

		return false;
	}
}

Zerion Mini Shell 1.0