$oPath = new CLearnPath();
    $oPath->ImportUrlencoded($g_learn_parentLessonPath);
    $g_learn_parentLessonId = $oPath->GetBottom();
    if ($g_learn_parentLessonId === false) {
        throw new LearnException('EA_LOGIC: PROPOSE_RETURN_LESSON_PATH given, ' . 'but there is no parent lesson in path', LearnException::EXC_ERR_ALL_LOGIC);
    }
}
// Place to $topCourseLessonId lesson id of top course, if top lesson is course.
$topCourseLessonId = false;
if (isset($g_learn_parentLessonPath) && strlen($g_learn_parentLessonPath)) {
    try {
        $oPath = new CLearnPath();
        $oPath->ImportUrlencoded($g_learn_parentLessonPath);
        $topLessonId = $oPath->GetTop();
        // Is lesson the course?
        if (CLearnLesson::GetLinkedCourse($topLessonId) !== false) {
            $topCourseLessonId = $topLessonId;
        }
    } catch (Exception $e) {
        $topCourseLessonId = false;
    }
    unset($oPath, $topLessonId);
}
// This argument can be transmitted on POST submit of form when creating new lesson
if (isset($_GET['PARENT_LESSON_ID'])) {
    $_POST['PARENT_LESSON_ID'] = $_GET['PARENT_LESSON_ID'];
}
if (isset($_POST['PARENT_LESSON_ID'])) {
    $g_learn_parentLessonId = $_POST['PARENT_LESSON_ID'];
}
$createNewLesson = false;
Beispiel #2
0
 public static function OnSearchReindex($NS = array(), $oCallback = null, $callback_method = '')
 {
     global $DB;
     static $arCourseToSiteCache = array();
     $arResult = array();
     $arAllSitesPathes = array();
     $elementStartId = 0;
     $indexElementType = 'C';
     // start reindex from courses
     $by = $order = '';
     $sites = CLang::GetList($by, $order, array('TYPE' => 'C'));
     while ($site = $sites->Fetch()) {
         $arAllSitesPathes[$site['LID']] = array('C' => CCourse::GetSitePathes($site['LID'], 'C'), 'H' => CCourse::GetSitePathes($site['LID'], 'H'), 'L' => CCourse::GetSitePathes($site['LID'], 'L'));
     }
     $arCoursesFilter = array();
     $arLessonsFilter = array('LINKED_LESSON_ID' => '');
     if ($NS['MODULE'] === 'learning' && strlen($NS['ID']) > 0) {
         $indexElementType = substr($NS['ID'], 0, 1);
         $elementStartId = (int) substr($NS['ID'], 1);
         if (strlen($NS['SITE_ID']) > 0) {
             $arCoursesFilter['SITE_ID'] = $NS['SITE_ID'];
         }
     }
     $arCoursesFilter['>ID'] = $elementStartId;
     if ($indexElementType === 'C') {
         $rsCourse = CCourse::GetList(array('ID' => 'ASC'), $arCoursesFilter);
         while ($arCourse = $rsCourse->Fetch()) {
             try {
                 $arCourse["SITE_ID"] = CCourse::GetSiteId($arCourse['ID']);
                 $arPathes = $arAllSitesPathes[$arCourse['SITE_ID']]['C'];
                 $linkedLessonId = CCourse::CourseGetLinkedLesson($arCourse['ID']);
                 if ($linkedLessonId === false) {
                     continue;
                 }
                 $arGroupPermissions = CLearnAccess::GetSymbolsAccessibleToLesson($linkedLessonId, CLearnAccess::OP_LESSON_READ);
             } catch (LearnException $e) {
                 continue;
                 // skip indexation of this item
             }
             $arSiteIds = array();
             foreach ($arPathes as $k => $path) {
                 $arCourse["PATH"] = $path;
                 $Url = str_replace("#COURSE_ID#", $arCourse["ID"], $arCourse["PATH"]);
                 $arSiteIds[$arCourse['SITE_ID']] = $Url;
             }
             if ($arCourse["DETAIL_TEXT_TYPE"] !== 'text') {
                 $detailText = CSearch::KillTags($arCourse['DETAIL_TEXT']);
             } else {
                 $detailText = strip_tags($arCourse['DETAIL_TEXT']);
             }
             if (strlen($detailText) > 0) {
                 $dataBody = $detailText;
             } else {
                 $dataBody = $arCourse['NAME'];
             }
             $Result = array("ID" => "C" . $arCourse["ID"], "LAST_MODIFIED" => $arCourse["TIMESTAMP_X"], "TITLE" => $arCourse["NAME"], "BODY" => $dataBody, "SITE_ID" => $arSiteIds, "PERMISSIONS" => $arGroupPermissions, "COURSE_ID" => "C" . $arCourse["ID"]);
             if ($oCallback) {
                 $res = call_user_func(array($oCallback, $callback_method), $Result);
                 if (!$res) {
                     return "C" . $arCourse["ID"];
                 }
             } else {
                 $arResult[] = $Result;
             }
         }
         // Reindex of courses finished. Let's reindex lessons now.
         $indexElementType = 'U';
         $elementStartId = 0;
     }
     $arLessonsFilter['>LESSON_ID'] = $elementStartId;
     if ($indexElementType === 'U') {
         $rsLessons = CLearnLesson::GetList(array('LESSON_ID' => 'ASC'), $arLessonsFilter);
         while ($arLessonFromDb = $rsLessons->Fetch()) {
             $arLessonsWithCourse = array();
             // list of lessons in context of some course
             $arOParentPathes = CLearnLesson::GetListOfParentPathes($arLessonFromDb['LESSON_ID']);
             foreach ($arOParentPathes as $oParentPath) {
                 $arParentLessons = $oParentPath->GetPathAsArray();
                 foreach ($arParentLessons as $lessonId) {
                     $linkedCourseId = CLearnLesson::GetLinkedCourse($lessonId);
                     if ($linkedCourseId !== false && $linkedCourseId > 0) {
                         $arLessonsWithCourse[] = array_merge($arLessonFromDb, array('PARENT_COURSE_ID' => $linkedCourseId));
                     }
                 }
             }
             foreach ($arLessonsWithCourse as $arLesson) {
                 try {
                     $arGroupPermissions = CLearnAccess::GetSymbolsAccessibleToLesson($arLesson['LESSON_ID'], CLearnAccess::OP_LESSON_READ);
                     $courseId = $arLesson['PARENT_COURSE_ID'];
                     if (!isset($arCourseToSiteCache[$courseId])) {
                         $strSql = "SELECT SITE_ID FROM b_learn_course_site WHERE COURSE_ID=" . (int) $courseId;
                         $rc = $DB->Query($strSql, true);
                         if ($rc === false) {
                             continue;
                         }
                         $arCourseToSiteCache[$courseId] = array();
                         while ($arCourseSite = $rc->fetch()) {
                             $arCourseToSiteCache[$courseId][] = $arCourseSite['SITE_ID'];
                         }
                     }
                     $arAllowedSites = $arCourseToSiteCache[$courseId];
                     if (empty($arAllowedSites)) {
                         continue;
                     }
                     $arSiteIds = array();
                     $lessonType = 'L';
                     if ($arLesson['IS_CHILDS']) {
                         $lessonType = 'H';
                     }
                     foreach ($arAllSitesPathes as $siteId => $arSitePathesByLessonType) {
                         if (!in_array($siteId, $arAllowedSites, true)) {
                             continue;
                         }
                         foreach ($arSitePathesByLessonType as $someLessonType => $arPathes) {
                             // skip wrong types of lessons
                             if ($lessonType !== $someLessonType) {
                                 continue;
                             }
                             foreach ($arPathes as $k => $path) {
                                 if ($lessonType == 'H') {
                                     $Url = str_replace("#CHAPTER_ID#", '0' . $arLesson['LESSON_ID'], $path);
                                 } else {
                                     $Url = str_replace("#LESSON_ID#", $arLesson['LESSON_ID'], $path);
                                 }
                                 $Url = str_replace("#COURSE_ID#", $arLesson['PARENT_COURSE_ID'], $Url);
                                 $arSiteIds[$siteId] = $Url;
                             }
                         }
                     }
                 } catch (LearnException $e) {
                     continue;
                     // skip indexation of this item
                 }
                 if ($arLesson["DETAIL_TEXT_TYPE"] !== 'text') {
                     $detailText = CSearch::KillTags($arLesson['DETAIL_TEXT']);
                 } else {
                     $detailText = strip_tags($arLesson['DETAIL_TEXT']);
                 }
                 if (strlen($detailText) > 0) {
                     $dataBody = $detailText;
                 } else {
                     $dataBody = $arLesson['NAME'];
                 }
                 $Result = array("ID" => 'U' . $arLesson['LESSON_ID'], "LAST_MODIFIED" => $arLesson['TIMESTAMP_X'], "TITLE" => $arLesson['NAME'], "BODY" => $dataBody, "SITE_ID" => $arSiteIds, "PERMISSIONS" => $arGroupPermissions);
                 if ($oCallback) {
                     $res = call_user_func(array($oCallback, $callback_method), $Result);
                     if (!$res) {
                         return 'U' . $arLesson['LESSON_ID'];
                     }
                 } else {
                     $arResult[] = $Result;
                 }
             }
         }
     }
     if ($oCallback) {
         $rc = false;
     } else {
         $rc = $arResult;
     }
     return $rc;
 }
 public function SaveInlineEditedItems()
 {
     if (!$this->IsNeedSaveInlineEditedItems()) {
         return $this;
     }
     if (check_bitrix_sessid() !== true) {
         throw new CLearnRenderAdminUnilessonListException('', CLearnRenderAdminUnilessonListException::C_ACCESS_DENIED);
     }
     foreach ($_POST['FIELDS'] as $lessonId => $arFields) {
         $arEdgeProperties = array();
         $wasError = false;
         try {
             // skip not changed items
             if (!$this->oList->IsUpdated($lessonId)) {
                 continue;
             }
             // throws exception if access denied
             $this->EnsureLessonUpdateAccess($lessonId);
             $courseId = CLearnLesson::GetLinkedCourse($lessonId);
             // Depends on current list mode, we must update sort index
             // of element (only for course) or sort index of relation between
             // child and parent lessons.
             // So, we must rename SORT to COURSE_SORT or EDGE_SORT
             if (array_key_exists('SORT', $arFields)) {
                 if ($this->IsListAnyCoursesMode() && $courseId !== false) {
                     $arFields['COURSE_SORT'] = $arFields['SORT'];
                 } elseif ($this->IsListChildLessonsMode()) {
                     $arFields['EDGE_SORT'] = $arFields['SORT'];
                 } else {
                     throw new CLearnRenderAdminUnilessonListException('', CLearnRenderAdminUnilessonListException::C_LOGIC | CLearnRenderAdminUnilessonListException::C_ACTION_UPDATE_FAIL);
                 }
                 unset($arFields['SORT']);
             }
             if (isset($arFields['EDGE_SORT'])) {
                 if (isset($_GET['PARENT_LESSON_ID'])) {
                     $arEdgeProperties['SORT'] = $arFields['EDGE_SORT'];
                 }
                 unset($arFields['EDGE_SORT']);
             }
             // PUBLISH_PROHIBITED
             if (array_key_exists('PUBLISH_PROHIBITED', $arFields)) {
                 // PUBLISH_PROHIBITED available in context of most parent course only
                 if ($this->contextCourseLessonId !== false && in_array($arFields['PUBLISH_PROHIBITED'], array('N', 'Y'), true)) {
                     $isProhibited = true;
                     if ($arFields['PUBLISH_PROHIBITED'] === 'N') {
                         $isProhibited = false;
                     }
                     CLearnLesson::PublishProhibitionSetTo($lessonId, $this->contextCourseLessonId, $isProhibited);
                 }
                 unset($arFields['PUBLISH_PROHIBITED']);
             }
             // Courses must be updated throws CCourse::Update();
             if ($courseId === false) {
                 CLearnLesson::Update($lessonId, $arFields);
             } else {
                 $ob = new CCourse();
                 if (!$ob->Update($courseId, $arFields)) {
                     throw new CLearnRenderAdminUnilessonListException('', CLearnRenderAdminUnilessonListException::C_ACTION_UPDATE_FAIL);
                 }
                 unset($ob);
             }
             if (isset($_GET['PARENT_LESSON_ID']) && count($arEdgeProperties) > 0) {
                 CLearnLesson::RelationUpdate($_GET['PARENT_LESSON_ID'], $lessonId, $arEdgeProperties);
             }
         } catch (CLearnRenderAdminUnilessonListException $e) {
             $wasError = true;
             $errorText = $e->getMessage();
             $errorCode = $e->getCode();
         } catch (Exception $e) {
             $wasError = true;
             $errorText = $e->getMessage();
             $errorCode = 0;
             // Because we checks below only CLearnRenderAdminUnilessonListException codes
         }
         if ($wasError) {
             if ($errorCode & CLearnRenderAdminUnilessonListException::C_ACCESS_DENIED) {
                 // Access denied
                 $errmsg = GetMessage('LEARNING_SAVE_ERROR') . ': ' . GetMessage('LEARNING_ACCESS_D');
                 if (strlen($errorText) > 0) {
                     $errmsg .= ': ' . $errorText;
                 }
             } else {
                 // Some error occured during update operation
                 $errmsg = GetMessage('LEARNING_SAVE_ERROR') . $lessonId;
                 if (strlen($errorText) > 0) {
                     $errmsg .= ' (' . $errorText . ')';
                 }
             }
             $this->oList->AddUpdateError($errmsg, $lessonId);
         }
     }
     return $this;
 }
    public static function RenderForm($oAccess, $LESSON_ID, $arOPathes)
    {
        global $APPLICATION;
        $curDir = $APPLICATION->GetCurDir();
        if (substr($curDir, -1) !== '/') {
            $curDir .= '/';
        }
        ?>
		<script type="text/javascript">
		function module_learning_js_admin_function_add_parent(lesson_id, name)
		{
			module_learning_js_admin_function_add_child_or_parent('LEARNING_LIST_OF_PARENTS', 'RELATION_PARENT[]', lesson_id, name);
			//alert ('called: module_learning_js_admin_function_add_parent(' + lesson_id + name + ')');
		}
		function module_learning_js_admin_function_add_child(lesson_id, name)
		{
			module_learning_js_admin_function_add_child_or_parent('LEARNING_LIST_OF_DESCENDANTS', 'RELATION_CHILD[]', lesson_id, name);
			//alert ('called: module_learning_js_admin_function_add_child(' + lesson_id + ')');
		}
		function module_learning_js_admin_function_add_child_or_parent(targetNode, fieldName, lesson_id, name)
		{
			var elemId = 'RELATION_PARENT_LID_' + lesson_id;

			var oDIV = BX.create('DIV', {'props': {'id': elemId}});
			var oA = BX.create(
				'SPAN', 
				{
					'props':
					{
						'className': 'access-delete',
					},
					'style':
					{
						position: 'relative',
						top: '3px',
						marginRight: '1px'
					},
					'events':
					{
						'click': function() {
							document.getElementById(elemId).parentNode.removeChild(document.getElementById(elemId));
						}
					}
				}
			);
			var oINPUT = BX.create(
				'INPUT', 
				{
					'props': 
					{
						'type':  'hidden', 
						'name':  fieldName,
						'value': lesson_id
					}
				}
			);
			var oSPAN = BX.create(
				'SPAN', 
				{
					'text': '[' + lesson_id + '] ' + name
				}
			);
			var oSPAN_space = BX.create(
				'SPAN', 
				{
					'text': ' '
				}
			);

			oDIV.appendChild(oA);
			oDIV.appendChild(oSPAN_space);
			oDIV.appendChild(oINPUT);
			oDIV.appendChild(oSPAN);
			BX(targetNode).appendChild(oDIV);
		}
		</script>
		<?php 
        $arChilds = array();
        $key = 0;
        $isChapter = $isCourse = false;
        $resChilds = CLearnLesson::GetListOfImmediateChilds($LESSON_ID);
        while ($arChild = $resChilds->Fetch()) {
            $isChapter = true;
            // this lesson is chapter, because there is descendants
            $arChilds['RELATION_CHILD_' . $key++] = array('elemName' => 'RELATION_CHILD[]', 'lessonId' => $arChild['LESSON_ID'], 'Name' => '[<a href="' . htmlspecialcharsbx($curDir) . 'learn_unilesson_edit.php?lang=' . LANG . '&LESSON_ID=' . ($arChild['LESSON_ID'] + 0) . '&LESSON_PATH=' . (int) $arChild['LESSON_ID'] . '" target=_blank>' . (int) $arChild['LESSON_ID'] . '</a>] ' . htmlspecialcharsbx($arChild['NAME']));
        }
        // Is course?
        $isCourse = CLearnLesson::GetLinkedCourse($LESSON_ID) !== false;
        ?>
		<div style="padding:10px;">
			<div id="LEARNING_LIST_OF_PARENTS" style="padding:10px 0;">
				<h3><?php 
        echo GetMessage('LEARNING_LIST_OF_PARENTS') . ':';
        ?>
</h3>
			<?php 
        $arParents = array();
        $resParents = CLearnLesson::GetListOfImmediateParents($LESSON_ID);
        while ($arParent = $resParents->Fetch()) {
            $arParents['RELATION_PARENT_' . $key++] = array('elemName' => 'RELATION_PARENT[]', 'lessonId' => $arParent['LESSON_ID'], 'Name' => '[<a href="' . htmlspecialcharsbx($curDir) . 'learn_unilesson_edit.php?lang=' . LANG . '&LESSON_ID=' . ($arParent['LESSON_ID'] + 0) . '&LESSON_PATH=' . (int) $arParent['LESSON_ID'] . '" target=_blank>' . (int) $arParent['LESSON_ID'] . '</a>] ' . htmlspecialcharsbx($arParent['NAME']));
        }
        foreach ($arParents as $elemId => $arElem) {
            ?>
				<div id="<?php 
            echo $elemId;
            ?>
">
					<?php 
            if (($oAccess->IsBaseAccess(CLearnAccess::OP_LESSON_UNLINK_FROM_PARENTS) || $oAccess->IsLessonAccessible($LESSON_ID, CLearnAccess::OP_LESSON_UNLINK_FROM_PARENTS)) && ($oAccess->IsBaseAccess(CLearnAccess::OP_LESSON_UNLINK_DESCENDANTS) || $oAccess->IsLessonAccessible($arElem['lessonId'], CLearnAccess::OP_LESSON_UNLINK_DESCENDANTS))) {
                ?>
						<span
							onclick="document.getElementById('<?php 
                echo $elemId;
                ?>
').parentNode.removeChild(document.getElementById('<?php 
                echo $elemId;
                ?>
'))" 
							class="access-delete"
							style="position:relative; top:3px; margin-right:1px;"
							>&nbsp;</span>
						<?php 
            }
            ?>
					<input type="hidden" name="<?php 
            echo $arElem['elemName'];
            ?>
" value="<?php 
            echo (int) $arElem['lessonId'];
            ?>
">
					<span style="font-style:italic;"><?php 
            echo $arElem['Name'];
            ?>
</span>
				</div>
				<?php 
        }
        ?>
			</div>

			<?php 
        if ($oAccess->IsBaseAccess(CLearnAccess::OP_LESSON_LINK_TO_PARENTS) || $oAccess->IsLessonAccessible($LESSON_ID, CLearnAccess::OP_LESSON_LINK_TO_PARENTS)) {
            ?>
				<div style="padding:0px;">
					<a href="javascript:void(0);" class="bx-action-href"
						onclick="window.open('<?php 
            echo addslashes(htmlspecialcharsbx($curDir));
            ?>
learn_unilesson_admin.php?lang=<?php 
            echo LANGUAGE_ID;
            ?>
&amp;search_retpoint=module_learning_js_admin_function_add_parent&amp;search_mode_type=parents_candidates', 
							'module_learning_js_admin_window_select_lessons_for_relations', 
							'scrollbars=yes,resizable=yes,width=960,height=500,top='+Math.floor((screen.height - 560)/2-14)+',left='+Math.floor((screen.width - 960)/2-5));" 
						><?php 
            echo GetMessage('LEARNING_ADD_ELEMENT');
            ?>
</a>
				</div>
				<?php 
        }
        ?>
			<div style="height:25px;">&nbsp;</div>
			<div id="LEARNING_LIST_OF_DESCENDANTS" style="padding:10px 0;">
				<h3><?php 
        echo GetMessage('LEARNING_LIST_OF_DESCENDANTS') . ':';
        ?>
</h3>
			<?php 
        foreach ($arChilds as $elemId => $arElem) {
            ?>
				<div id="<?php 
            echo $elemId;
            ?>
">
					<?php 
            if (($oAccess->IsBaseAccess(CLearnAccess::OP_LESSON_UNLINK_DESCENDANTS) || $oAccess->IsLessonAccessible($LESSON_ID, CLearnAccess::OP_LESSON_UNLINK_DESCENDANTS)) && ($oAccess->IsBaseAccess(CLearnAccess::OP_LESSON_UNLINK_FROM_PARENTS) || $oAccess->IsLessonAccessible($arElem['lessonId'], CLearnAccess::OP_LESSON_UNLINK_FROM_PARENTS))) {
                ?>
						<a href="javascript:void(0);" 
							onclick="document.getElementById('<?php 
                echo $elemId;
                ?>
').parentNode.removeChild(document.getElementById('<?php 
                echo $elemId;
                ?>
'))" 
							class="access-delete"></a>
						<?php 
            }
            ?>
					<input type="hidden" name="<?php 
            echo $arElem['elemName'];
            ?>
" value="<?php 
            echo (int) $arElem['lessonId'];
            ?>
">
					<span style="font-style:italic;"><?php 
            echo $arElem['Name'];
            ?>
</span>
				</div>
				<?php 
        }
        ?>
			</div>
			<?php 
        if ($oAccess->IsBaseAccess(CLearnAccess::OP_LESSON_LINK_DESCENDANTS) || $oAccess->IsLessonAccessible($LESSON_ID, CLearnAccess::OP_LESSON_LINK_DESCENDANTS)) {
            ?>
				<div style="padding:0px;">
					<a href="javascript:void(0);" class="bx-action-href"
						onclick="window.open('<?php 
            echo addslashes(htmlspecialcharsbx($curDir));
            ?>
learn_unilesson_admin.php?lang=<?php 
            echo LANGUAGE_ID;
            ?>
&amp;search_retpoint=module_learning_js_admin_function_add_child', 
							'module_learning_js_admin_window_select_lessons_for_relations', 
							'scrollbars=yes,resizable=yes,width=960,height=500,top='+Math.floor((screen.height - 560)/2-14)+',left='+Math.floor((screen.width - 960)/2-5));" 
						><?php 
            echo GetMessage('LEARNING_ADD_ELEMENT');
            ?>
</a>
				</div>
				<?php 
        }
        ?>
			<div style="height:25px;">&nbsp;</div>
			<hr>
			<div id="LEARNING_LIST_OF_ALL_PARENT_PATHES" style="padding:10px 0;">
				<?php 
        $cntParentPathes = count($arOPathes);
        $langPhraseBase = 'LEARNING_LIST_OF_ALL_PARENT_PATHES_FOR_';
        $lessonType = 'LESSON';
        if ($isCourse) {
            $lessonType = 'COURSE';
        } elseif ($isChapter) {
            $lessonType = 'CHAPTER';
        }
        $isEmpty = '';
        if ($cntParentPathes === 0) {
            $isEmpty = '_IS_EMPTY';
        }
        echo '<h3>' . GetMessage($langPhraseBase . $lessonType . $isEmpty) . '</h3>';
        if ($cntParentPathes > 0) {
            $pattern = '[<a href="' . addslashes(htmlspecialcharsbx($curDir)) . 'learn_unilesson_edit.php?lang=' . LANG . '&LESSON_ID=#LESSON_ID#&LESSON_PATH=#LESSON_ID#" target="_blank">#LESSON_ID#</a>] #NAME#';
            foreach ($arOPathes as $oPath) {
                echo $oPath->GetPathAsHumanReadableString(' / ', $pattern);
                if ($oPath->Count() >= 1) {
                    if (CLearnLesson::IsPublishProhibited($LESSON_ID, $oPath->GetTop())) {
                        echo ' <span style="color:grey;">(' . GetMessage('LEARNING_LESSON_IS_PUBLISH_PROHIBITED') . ')</span>';
                    }
                }
                echo '<br>';
            }
        }
        ?>
			</div>
		</div>
		<?php 
    }
Beispiel #5
0
function __learning_admin_get_menu($THIS, $arPath = array(), $deep = 0, &$immediateChildsIds, $loadOnlySpecialEntities = false)
{
    $immediateChildsIds = array();
    // puts here ids of all immediate childs
    $deep = (int) $deep;
    // Index in path for current parentLessonId
    $indexInPath = $deep - 1;
    // Path doesn't include top root element ('all courses' or 'all unilessons')
    $arMenu = array();
    //$urlPath = $oPath->ExportUrlencoded();
    // current lesson id (not exists only for top root)
    if (isset($arPath[$deep])) {
        $currentLessonIdInPath = (int) $arPath[$deep];
    } else {
        $currentLessonIdInPath = false;
    }
    // Path to current element
    $arCurrentDeepPath = array();
    foreach ($arPath as $key => $value) {
        if ($key === $deep) {
            break;
        }
        $arCurrentDeepPath[] = $value;
    }
    if ($deep === 0) {
        // We are at the top level, so we must get list of all courses
        $CDBResult = CCourse::GetList(array('COURSE_SORT' => 'ASC'));
    } else {
        // If not parent with such indexInPath => we are deep too much.
        if (!isset($arPath[$indexInPath])) {
            return $arMenu;
        }
        // no items
        $parentLessonId = $arPath[$indexInPath];
        $oCurrentDeepPath = new CLearnPath();
        $oCurrentDeepPath->SetPathFromArray(array_merge($arCurrentDeepPath));
        $urlPath = $oCurrentDeepPath->ExportUrlencoded();
        $arMenu[] = array("text" => GetMessage("LEARNING_QUESTION"), "url" => "learn_question_admin.php?lang=" . LANG . '&PARENT_LESSON_ID=' . ($parentLessonId + 0) . '&LESSON_PATH=' . $urlPath . "&from=learn_menu", "icon" => "learning_icon_question", "more_url" => array("learn_question_admin.php?lang=" . LANG . '&PARENT_LESSON_ID=' . ($parentLessonId + 0) . '&LESSON_PATH=' . $urlPath . "&from=learn_menu", "learn_question_edit.php?lang=" . LANG . '&LESSON_PATH=' . $urlPath . "&from=learn_menu", "learn_question_admin.php?lang=" . LANG . '&PARENT_LESSON_ID=' . ($parentLessonId + 0) . '&LESSON_PATH=' . $urlPath, "learn_question_edit.php?lang=" . LANG . '&LESSON_PATH=' . $urlPath, "learn_question_admin.php?lang=" . LANG . '&LESSON_PATH=' . $urlPath), "title" => GetMessage("LEARNING_QUESTION_LIST"));
        $CDBResult = CLearnLesson::GetListOfImmediateChilds($parentLessonId, array('EDGE_SORT' => 'ASC'));
        // determine, is parent a course (only for courses in subroot level)?
        if ($deep === 1) {
            $immediateParentCourse = CLearnLesson::GetLinkedCourse($parentLessonId);
            if ($immediateParentCourse !== false) {
                // immediate parent is a course, so we must add entity 'Tests'
                $arMenu[] = array('text' => GetMessage('LEARNING_TESTS'), 'url' => 'learn_test_admin.php?lang=' . LANG . '&filter=Y&set_filter=Y' . '&COURSE_ID=' . ($immediateParentCourse + 0) . '&PARENT_LESSON_ID=' . ($parentLessonId + 0) . '&LESSON_PATH=' . $urlPath, 'icon' => 'learning_icon_tests', 'more_url' => array('learn_test_admin.php?lang=' . LANG . '&set_filter=Y' . '&COURSE_ID=' . ($immediateParentCourse + 0) . '&PARENT_LESSON_ID=' . ($parentLessonId + 0) . '&LESSON_PATH=' . $urlPath, 'learn_test_edit.php?lang=' . LANG . '&filter=Y&set_filter=Y' . '&COURSE_ID=' . ($immediateParentCourse + 0) . '&PARENT_LESSON_ID=' . ($parentLessonId + 0) . '&LESSON_PATH=' . $urlPath), 'title' => GetMessage('LEARNING_TESTS_LIST'));
                unset($urlPath);
                unset($oCurrentDeepPath);
            }
        }
    }
    if ($loadOnlySpecialEntities) {
        return $arMenu;
    }
    // When listing courses, limit it's count
    if ($deep === 0) {
        $items = 0;
        $learning_menu_max_courses = (int) COption::GetOptionString("learning", "menu_max_courses", "10");
    }
    while ($arData = $CDBResult->GetNext()) {
        // When listing courses, limit it's count
        if ($deep === 0) {
            if ($items >= $learning_menu_max_courses) {
                // add element 'other courses'
                $arMenu[] = array('text' => GetMessage('LEARNING_MENU_COURSES_OTHER'), 'url' => 'learn_unilesson_admin.php?lang=' . LANG . '&PARENT_LESSON_ID=-1', 'title' => GetMessage('LEARNING_MENU_COURSES_ALT'), 'more_url' => array('learn_test_admin.php', 'learn_test_edit.php', 'learn_unilesson_admin.php', 'learn_unilesson_edit.php', 'learn_question_admin.php', 'learn_question_edit.php'));
                // stop adding courses to menu
                break;
            }
            $items++;
        }
        $arSubImmediateChildsIds = false;
        $arCurItemPath = $arCurrentDeepPath;
        $arCurItemPath[] = $arData['LESSON_ID'] + 0;
        // Remember all immediate childs
        $immediateChildsIds[] = $arData['LESSON_ID'] + 0;
        $oCurItemPath = new CLearnPath();
        $oCurItemPath->SetPathFromArray($arCurItemPath);
        $urlCurItemPath = $oCurItemPath->ExportUrlencoded();
        $arItem = array('text' => $arData['NAME'], 'url' => 'learn_unilesson_admin.php?lang=' . LANG . '&PARENT_LESSON_ID=' . ($arData['LESSON_ID'] + 0) . '&LESSON_PATH=' . $oCurItemPath->ExportUrlencoded(), 'title' => $arData['NAME'], 'items_id' => 'menu_learning_courses_new_' . implode('_', $arCurItemPath), "icon" => "learning_icon_courses", 'module_id' => 'learning', 'more_url' => array('learn_unilesson_admin.php?lang=' . LANG . '&set_filter=Y' . '&PARENT_LESSON_ID=' . ($arData['LESSON_ID'] + 0) . '&LESSON_PATH=' . $urlCurItemPath, 'learn_unilesson_admin.php?lang=' . LANG . '&PARENT_LESSON_ID=' . ($arData['LESSON_ID'] + 0) . '&LESSON_PATH=' . $urlCurItemPath, 'learn_unilesson_admin.php?lang=' . LANG . '&set_filter=Y' . '&LESSON_PATH=' . $urlCurItemPath, 'learn_question_admin.php?lang=' . LANG . '&filter=Y&set_filter=Y' . '&LESSON_PATH=' . $urlCurItemPath, 'learn_question_edit.php?lang=' . LANG . '&set_filter=Y' . '&LESSON_PATH=' . $urlCurItemPath, 'learn_unilesson_edit.php?lang=' . LANG . '&LESSON_ID=' . ($arData['LESSON_ID'] + 0) . '&LESSON_PATH=' . $urlCurItemPath, 'learn_unilesson_edit.php?lang=' . LANG . '&PARENT_LESSON_ID=' . ($arData['LESSON_ID'] + 0) . '&LESSON_PATH=' . $urlCurItemPath));
        $arItem['items'] = array();
        if ($deep === 0 && isset($arData['LINKED_LESSON_ID']) && $arData['LINKED_LESSON_ID'] > 0) {
            $arItem['page_icon'] = $arItem['icon'] = 'learning_icon_courses';
            $arItem['dynamic'] = true;
            $loadOnlySpecialEntities = false;
            // Load child items only for lesson in current path
            if ($arData['LESSON_ID'] == $currentLessonIdInPath) {
                $arItem['items'] = __learning_admin_get_menu($THIS, $arPath, $deep + 1, $arSubImmediateChildsIds);
            }
        } else {
            $loadOnlySpecialEntities = false;
            $childsCnt = CLearnLesson::CountImmediateChilds($arData['LESSON_ID']);
            $questionsCnt = CLQuestion::GetCount(array('LESSON_ID' => (int) $arData['LESSON_ID']));
            if ($childsCnt > 0) {
                $arItem['page_icon'] = $arItem['icon'] = 'learning_icon_chapters';
            } else {
                $arItem['page_icon'] = $arItem['icon'] = 'learning_icon_lessons';
            }
            $arItem['dynamic'] = true;
            // Load child items only for lesson in current path
            if ($arData['LESSON_ID'] == $currentLessonIdInPath) {
                $arItem['items'] = __learning_admin_get_menu($THIS, $arPath, $deep + 1, $arSubImmediateChildsIds);
            }
        }
        // now, adds items into more_url (it needs when edit form for childs opened)
        if (is_array($arSubImmediateChildsIds)) {
            $oSubItemPath = new CLearnPath();
            foreach ($arSubImmediateChildsIds as $k => $v) {
                // determine path for every child
                $arSubItemPath = $arCurItemPath;
                $arSubItemPath[] = $v;
                // child id added to current path
                $oSubItemPath->SetPathFromArray($arSubItemPath);
                $arItem['more_url'][] = 'learn_unilesson_edit.php?lang=' . LANG . '&filter=Y&set_filter=Y' . '&LESSON_ID=' . ($v + 0) . '&LESSON_PATH=' . $oSubItemPath->ExportUrlencoded();
            }
            unset($oSubItemPath);
            $arSubImmediateChildsIds = false;
        }
        $arMenu[] = $arItem;
        unset($oCurItemPath, $arCurItemPath, $urlCurItemPath, $arItem);
    }
    return $arMenu;
}