public function test_set_section_visibility()
 {
     $generator = $this->getDataGenerator();
     // Create topics course
     $generator->create_course(['shortname' => 'testcourse', 'format' => 'topics', 'numsections' => 5], ['createsections' => true]);
     $this->setAdminUser();
     // Hide the section.
     $visibility = $this->courseservice->set_section_visibility('testcourse', 3, false);
     $this->assertTrue(isset($visibility['actionmodel']));
     $this->assertTrue(isset($visibility['toc']));
     $actionmodel = $visibility['actionmodel'];
     $toc = $visibility['toc'];
     $this->assertTrue($actionmodel instanceof theme_snap\renderables\course_action_section_visibility);
     $this->assertTrue($toc instanceof theme_snap\renderables\course_toc);
     // Check that action model has toggled after section hidden.
     $this->assertEquals('snap-visibility snap-show', $actionmodel->class);
     $this->assertEquals('Show topic', $actionmodel->title);
     $this->assertContains('show=3', $actionmodel->url);
     // Unhide the section.
     $visibility = $this->courseservice->set_section_visibility('testcourse', 3, true);
     $actionmodel = $visibility['actionmodel'];
     $this->assertTrue($actionmodel instanceof theme_snap\renderables\course_action_section_visibility);
     // Check that action model now corresponds to unhighlighted state.
     $this->assertEquals('snap-visibility snap-hide', $actionmodel->class);
     $this->assertEquals('Hide topic', $actionmodel->title);
     $this->assertContains('hide=3', $actionmodel->url);
 }
 /**
  * @param string $courseshortname
  * @param string $unavailablesections
  * @param string $unavailablemods
  * @return array
  */
 public static function service($courseshortname, $unavailablesections, $unavailablemods)
 {
     $service = course::service();
     $previouslyunavailablesections = !empty($unavailablesections) ? explode(',', $unavailablesections) : [];
     $previouslyunavailablemods = !empty($unavailablemods) ? explode(',', $unavailablemods) : [];
     $coursecompletion = $service->course_completion($courseshortname, $previouslyunavailablesections, $previouslyunavailablemods);
     return $coursecompletion;
 }
 /**
  * @param string $courseshortname
  * @param string $imagedata
  * @param string $imagefilename
  * @return array
  */
 public static function service($courseshortname, $imagedata, $imagefilename)
 {
     $service = course::service();
     $course = $service->coursebyshortname($courseshortname, 'id');
     $context = \context_course::instance($course->id);
     self::validate_context($context);
     $coverimage = $service->setcoverimage($courseshortname, $imagedata, $imagefilename);
     return $coverimage;
 }
 /**
  * @param string $courseshortname
  * @param string $unavailablesections
  * @param string $unavailablemods
  * @return array
  */
 public static function service($courseshortname, $action, $sectionnumber, $value)
 {
     $service = course::service();
     switch ($action) {
         case 'highlight':
             return $service->highlight_section($courseshortname, $sectionnumber, $value);
         case 'visibility':
             return $service->set_section_visibility($courseshortname, $sectionnumber, $value);
     }
     throw new \coding_exception('Invalid action selected :' . $action);
 }
 /**
  * @param string $courseshortname
  * @param null|int $favorited
  * @return array
  */
 public static function service($courseshortname, $favorited = null)
 {
     $service = course::service();
     $course = $service->coursebyshortname($courseshortname, 'id');
     $context = \context_course::instance($course->id);
     self::validate_context($context);
     if ($favorited !== null) {
         $service->setfavorite($courseshortname, $favorited == 1);
     }
     $coursecard = $service->cardbyshortname($courseshortname);
     // Convert renderable to array and skip protected / private - casting with (array) includes protected / private.
     return (array) json_decode($coursecard->model);
 }
    /**
     * The "fixy" overlay that drops down when the link in the top right corner is clicked. It will say either
     * "login" or "menu" (for signed in users).
     *
     */
    public function fixed_menu()
    {
        global $CFG, $USER;
        $logout = get_string('logout');
        $isguest = isguestuser();
        $courseservice = course::service();
        $output = '';
        if (!isloggedin() || $isguest) {
            $login = get_string('login');
            $cancel = get_string('cancel');
            if (!empty($CFG->loginpasswordautocomplete)) {
                $autocomplete = 'autocomplete="off"';
            } else {
                $autocomplete = '';
            }
            if (empty($CFG->authloginviaemail)) {
                $username = get_string('username');
            } else {
                $username = get_string('usernameemail');
            }
            if (empty($CFG->loginhttps)) {
                $wwwroot = $CFG->wwwroot;
            } else {
                $wwwroot = str_replace("http://", "https://", $CFG->wwwroot);
            }
            $password = get_string('password');
            $loginform = get_string('loginform', 'theme_snap');
            $helpstr = '';
            if (empty($CFG->forcelogin) || $isguest || !isloggedin() || !empty($CFG->registerauth) || is_enabled_auth('none') || !empty($CFG->auth_instructions)) {
                if ($isguest) {
                    $helpstr = '<p class="text-center">' . get_string('loggedinasguest', 'theme_snap') . '</p>';
                    $helpstr .= '<p class="text-center">' . '<a class="btn btn-primary" href="' . s($CFG->wwwroot) . '/login/logout.php?sesskey=' . sesskey() . '">' . $logout . '</a></p>';
                    $helpstr .= '<p class="text-center">' . '<a href="' . s($wwwroot) . '/login/index.php">' . get_string('helpwithloginandguest', 'theme_snap') . '</a></p>';
                } else {
                    if (empty($CFG->forcelogin)) {
                        $help = get_string('helpwithloginandguest', 'theme_snap');
                    } else {
                        $help = get_string('helpwithlogin', 'theme_snap');
                    }
                    $helpstr = "<p class='text-center'><a href='" . s($wwwroot) . "/login/index.php'>{$help}</a></p>";
                }
            }
            if (local::current_url_path() != '/login/index.php') {
                $output .= $this->login_button();
                $altlogins = $this->render_login_alternative_methods(new login_alternative_methods());
                $output .= "<div class='fixy' id='snap-login' role='dialog' aria-label='{$loginform}' tabindex='-1'>\n                    <form action='{$wwwroot}/login/index.php'  method='post'>\n                    <div class=fixy-inner>\n                    <div class=fixy-header>\n                    <a id='fixy-close' class='js-personal-menu-trigger pull-right snap-action-icon' href='#'>\n                        <i class='icon icon-close'></i><small>{$cancel}</small>\n                    </a>\n                    <h1>{$login}</h1>\n                    </div>\n                    <label for='username'>{$username}</label>\n                    <input autocapitalize='off' type='text' name='username' id='username'>\n                    <label for='password'>{$password}</label>\n                    <input type='password' name='password' id='password' {$autocomplete}>\n                    <br>\n                    <input type='submit' value='" . s($login) . "'>\n                    {$helpstr}\n                    {$altlogins}\n                    </div>\n                    </form></div>";
            }
        } else {
            $courselist = "";
            $userpicture = new user_picture($USER);
            $userpicture->link = false;
            $userpicture->alttext = false;
            $userpicture->size = 100;
            $picture = $this->render($userpicture);
            list($favorited, $notfavorited) = $courseservice->my_courses_split_by_favorites();
            // Create courses array with favorites first.
            $mycourses = $favorited + $notfavorited;
            $courselist .= '<section id="fixy-my-courses"><div class="clearfix"><h2>' . get_string('courses') . '</h2>';
            $courselist .= '<div id="fixy-visible-courses">';
            // Default text when no courses.
            if (!$mycourses) {
                $courselist .= "<p>" . get_string('coursefixydefaulttext', 'theme_snap') . "</p>";
            }
            // Visible / hidden course vars.
            $visiblecoursecount = 0;
            // How many courses are in the hidden section (hidden and not favorited).
            $hiddencoursecount = 0;
            $hiddencourselist = '';
            // How many courses are actually hidden.
            $actualhiddencount = 0;
            foreach ($mycourses as $course) {
                $ccard = new course_card($course->id);
                $coursecard = $this->render($ccard);
                // If course is not visible.
                if (!$course->visible) {
                    $actualhiddencount++;
                    // Only add to list of hidden courses if not favorited.
                    if (!isset($favorited[$course->id])) {
                        $hiddencoursecount++;
                        $hiddencourselist .= $coursecard;
                    } else {
                        // OK, this is hidden but it's favorited, so technically visible.
                        $visiblecoursecount++;
                        $courselist .= $coursecard;
                    }
                } else {
                    $visiblecoursecount++;
                    $courselist .= $coursecard;
                }
            }
            $courselist .= '</div>';
            $courselist .= $this->browse_all_courses_button();
            $courselist .= '</div>';
            if ($actualhiddencount && $visiblecoursecount) {
                // Output hidden courses toggle when there are visible courses.
                $togglevisstate = !empty($hiddencourselist) ? ' state-visible' : '';
                $hiddencourses = '<div class="clearfix"><h2 class="header-hidden-courses' . $togglevisstate . '"><a id="js-toggle-hidden-courses" href="#">' . get_string('hiddencoursestoggle', 'theme_snap', $hiddencoursecount) . '</a></h2>';
                $hiddencourses .= '<div id="fixy-hidden-courses" class="clearfix" tabindex="-1">' . $hiddencourselist . '</div>';
                $hiddencourses .= '</div>';
                $courselist .= $hiddencourses;
            } else {
                if (!$visiblecoursecount && $hiddencoursecount) {
                    $hiddencourses = '<div id="fixy-hidden-courses" class="clearfix state-visible">' . $hiddencourselist . '</div>';
                    $courselist .= $hiddencourses;
                }
            }
            $courselist .= '</section>';
            $menu = get_string('menu', 'theme_snap');
            $badge = $this->render_badge_count();
            $linkcontent = $menu . $picture . $badge;
            $attributes = array('aria-haspopup' => 'true', 'class' => 'js-personal-menu-trigger snap-my-courses-menu', 'id' => 'fixy-trigger', 'aria-controls' => 'primary-nav');
            $output .= html_writer::link('#', $linkcontent, $attributes);
            $close = get_string('close', 'theme_snap');
            $viewyourprofile = get_string('viewyourprofile', 'theme_snap');
            $realuserinfo = '';
            if (\core\session\manager::is_loggedinas()) {
                $realuser = \core\session\manager::get_realuser();
                $via = get_string('via', 'theme_snap');
                $fullname = fullname($realuser, true);
                $realuserinfo = html_writer::span($via . ' ' . html_writer::span($fullname, 'real-user-name'), 'real-user-info');
            }
            $output .= '<nav id="primary-nav" class="fixy toggle-details" tabindex="-1">
            <div class="fixy-inner">
            <div class="fixy-header">
            <a id="fixy-close" class="js-personal-menu-trigger pull-right snap-action-icon" href="#">
                <i class="icon icon-close"></i><small>' . $close . '</small>
            </a>

            <div id="fixy-user">' . $picture . '
            <div id="fixy-user-details">
                <a title="' . s($viewyourprofile) . '" href="' . s($CFG->wwwroot) . '/user/profile.php" >' . '<span class="h1" role="heading" aria-level="1">' . format_string(fullname($USER)) . '</span>
                </a> ' . $realuserinfo . '
                <a id="fixy-logout" href="' . s($CFG->wwwroot) . '/login/logout.php?sesskey=' . sesskey() . '">' . $logout . '</a>
            </div>
            </div>
            </div>



        <div id="fixy-content">' . $courselist . $this->render_callstoaction() . '
        </div><!-- end fixy-content -->
        </div><!-- end fixy-inner -->
        </nav><!-- end primary nav -->';
        }
        return $output;
    }
 /**
  * @param string $courseshortname
  * @return array
  */
 public static function service($courseshortname)
 {
     $service = course::service();
     return ['chapters' => $service->course_toc_chapters($courseshortname)];
 }
 /**
  * @param int $courseid
  * @param course | null $service
  */
 public function __construct($courseid, course $service = null)
 {
     $this->courseid = $courseid;
     $this->service = $service ?: course::service();
     $this->apply_properties();
     $this->model = $this;
 }