librewiki / liberty-skin

Liberty skin
GNU General Public License v3.0
19 stars 51 forks source link

미디어위키:Liberty-Navbar의 형식과 맞지 않게 Navbar가 출력되는 문제 #31

Open gaon12 opened 3 months ago

gaon12 commented 3 months ago

미디어위키:Liberty-Navbar는 다음과 같이 적용했습니다.

* icon=comments | display=게시판
** icon=pencil-alt | display=위키방 | link=https://bbs.gaonwiki.com | title=https://bbs.gaonwiki.com
** icon=copyright | display=저작권 처리 게시판 | link=https://bbs.gaonwiki.com/copyrights | title=https://bbs.gaonwiki.com/copyrights
** icon=comments | display=자유게시판 | link=https://bbs.gaonwiki.com/free | title=https://bbs.gaonwiki.com/free
* icon=exclamation | display=버그/기능 개선
** icon=bullhorn | display=이슈 등록 | link=https://bbs.gaonwiki.com/issue | title=https://bbs.gaonwiki.com/issue
** icon=hands-helping | display=기능 구현 도움 | link=https://www.gaonwiki.com/w/가온_위키:기능_구현_불가-누가_해결책을_알려주세요! | title=https://www.gaonwiki.com/w/가온_위키:기능_구현_불가-누가_해결책을_알려주세요!
** icon=bug | display=알려진 문제들 | link=https://www.gaonwiki.com/w/가온_위키/알려진_문제들 | title=https://www.gaonwiki.com/w/가온_위키/알려진_문제들
* icon=gear | display=도구
** icon=wrench | display=특수 문서 목록 | link=특수:특수문서 | title=특수:특수문서
** icon=upload | display=파일 올리기
*** icon=cloud-upload-alt | display=(기존) 업로드 | link=특수:올리기 | title=특수:올리기
*** icon=file-upload | display=(신규) 업로드 마법사 | link=특수:UploadWizard | title=특수:UploadWizard
** icon=flag | display=이슈 트래커 | link=https://bbs.gaonwiki.com/issue/ | title=https://bbs.gaonwiki.com/issue/
** icon=flask | display=가온 위키 베타 | link=https://beta.gaonwiki.com | title=https://beta.gaonwiki.com
* icon=book | display=도움말
** icon=spell-check | display=위키 문법 | link=도움말:위키_문법 | title=도움말:위키_문법
** icon=book | display=설명서 | link=도움말:설명서 | title=도움말:설명서

이후 리버티 스킨 178653922dab071a26caac48fc3a590a0aa5a272 커밋을 적용하면 첨부한 이미지와 같이 각 드롭다운 메뉴의 마지막 항목이 다음 드롭다운 타이틀로 적용되는 문제가 있습니다. image

현재 미디어위키 버전은 1.39.8 사용중이고, a15075a 커밋에서는 문제가 없습니다. 즉, a15075a 이후 커밋 중에 문제가 발생하는 것 같습니다(정확히 어떤 커밋에서 발생하는지는 모르겠습니다).


[환경]

문제가 발생하지 않은 a15075a 커밋을 바탕으로 다음과 같이 수정하면 정상 동작합니다.

protected function parseNavbar() {
    global $wgArticlePath;

    $headings = [];
    $skin = $this->getSkin();
    $userName = $skin->getUser()->getName();
    $userLang = $skin->getLanguage()->mCode;
    $globalData = ContentHandler::getContentText( WikiPage::factory(
        Title::newFromText( 'Liberty-Navbar', NS_MEDIAWIKI )
    )->getContent( RevisionRecord::RAW ) );
    $globalLangData = ContentHandler::getContentText( WikiPage::factory(
        Title::newFromText( 'Liberty-Navbar/' . $userLang, NS_MEDIAWIKI )
    )->getContent( RevisionRecord::RAW ) );
    $userData = ContentHandler::getContentText( WikiPage::factory(
        Title::newFromText( $userName . '/Liberty-Navbar', NS_USER )
    )->getContent( RevisionRecord::RAW ) );
    if ( !empty( $userData ) ) {
        $data = $userData;
    } elseif ( !empty( $globalLangData ) ) {
        $data = $globalLangData;
    } else {
        $data = $globalData;
    }
    if ( empty( $data ) ) {
        return $headings;
    }

    $lines = explode( "\n", $data );

    $types = [ 'icon', 'display', 'title', 'link', 'access', 'class' ];

    foreach ( $lines as $line ) {
        $line = rtrim( $line, "\r" );
        if ( $line[0] !== '*' ) {
            continue;
        }
        if ( $line[1] !== '*' ) {
            // First level menu
            $data = [];
            $split = explode( '|', $line );
            $split[0] = substr( $split[0], 1 );
            foreach ( $split as $key => $value ) {
                $valueArr = explode( '=', trim( $value ) );
                if ( isset( $valueArr[1] ) ) {
                    $data[$valueArr[0]] = $valueArr[1];
                } else {
                    $data[$types[$key]] = trim( $value );
                }
            }

            $icon = isset( $data['icon'] ) ? htmlentities( $data['icon'], ENT_QUOTES, 'UTF-8' ) : null;
            $group = isset( $data['group'] ) ? htmlentities( $data['group'], ENT_QUOTES, 'UTF-8' ) : null;
            $right = isset( $data['right'] ) ? htmlentities( $data['right'], ENT_QUOTES, 'UTF-8' ) : null;

            if ( isset( $data['display'] ) ) {
                $textObj = $skin->msg( $data['display'] );
                if ( $textObj->isDisabled() ) {
                    $text = htmlentities( $data['display'], ENT_QUOTES, 'UTF-8' );
                } else {
                    $text = $textObj->text();
                }
            } else {
                $text = '';
            }

            if ( empty( $icon ) && empty( $text ) ) {
                continue;
            }

            if ( isset( $data['title'] ) ) {
                $titleObj = $skin->msg( $data['title'] );
                if ( $titleObj->isDisabled() ) {
                    $title = htmlentities( $data['title'], ENT_QUOTES, 'UTF-8' );
                } else {
                    $title = $titleObj->text();
                }
            } else {
                $title = $text;
            }

            if ( isset( $data['link'] ) ) {
                if ( preg_match( '/^((?:(?:http(?:s)?)?:)?\/\/(?:.{4,}))$/i', $data['link'] ) ) {
                    $href = htmlentities( $data['link'], ENT_QUOTES, 'UTF-8' );
                } else {
                    $href = str_replace( '%3A', ':', urlencode( $data['link'] ) );
                    $href = str_replace( '$1', $href, $wgArticlePath );
                }
            } else {
                $href = null;
            }

            $access = isset( $data['access'] ) ? preg_match( '/^([0-9a-z]{1})$/i', $data['access'] ) ? $data['access'] : '' : null;

            $classes = isset( $data['class'] ) ? array_map( 'trim', explode( ',', htmlentities( $data['class'], ENT_QUOTES, 'UTF-8' ) ) ) : [];protected function parseNavbar() {
        global $wgArticlePath;

        $headings = [];
        $currentHeading = null;
        $skin = $this->getSkin();
        $userName = $skin->getUser()->getName();
        $userLang = $skin->getLanguage()->mCode;
        $globalData = ContentHandler::getContentText( WikiPage::factory(
            Title::newFromText( 'Liberty-Navbar', NS_MEDIAWIKI )
        )->getContent( RevisionRecord::RAW ) );
        $globalLangData = ContentHandler::getContentText( WikiPage::factory(
            Title::newFromText( 'Liberty-Navbar/' . $userLang, NS_MEDIAWIKI )
        )->getContent( RevisionRecord::RAW ) );
        $userData = ContentHandler::getContentText( WikiPage::factory(
            Title::newFromText( $userName . '/Liberty-Navbar', NS_USER )
        )->getContent( RevisionRecord::RAW ) );
        if ( !empty( $userData ) ) {
            $data = $userData;
        } elseif ( !empty( $globalLangData ) ) {
            $data = $globalLangData;
        } else {
            $data = $globalData;
        }
        // Well, [[MediaWiki:Liberty-Navbar]] *should* have some content, but
        // if it doesn't, bail out here so that we don't trigger E_NOTICEs
        // about undefined indexes later on
        if ( empty( $data ) ) {
            return $headings;
        }

        $lines = explode( "\n", $data );

        $types = [ 'icon', 'display', 'title', 'link', 'access', 'class' ];

        foreach ( $lines as $line ) {
            $line = rtrim( $line, "\r" );
            if ( $line[0] !== '*' ) {
                // Line does not start with '*'
                continue;
            }
            if ( $line[1] !== '*' ) {
                // First level menu
                $data = [];
                $split = explode( '|', $line );
                $split[0] = substr( $split[0], 1 );
                foreach ( $split as $key => $value ) {
                    $valueArr = explode( '=', trim( $value ) );
                    if ( isset( $valueArr[1] ) ) {
                        $data[$valueArr[0]] = $valueArr[1];
                    } else {
                        $data[$types[$key]] = trim( $value );
                    }
                }

                // Icon
                $icon = isset( $data['icon'] ) ? htmlentities( $data['icon'], ENT_QUOTES, 'UTF-8' ) : null;

                // Group
                $group = isset( $data['group'] ) ? htmlentities( $data['group'], ENT_QUOTES, 'UTF-8' ) : null;

                // Right
                $right = isset( $data['right'] ) ? htmlentities( $data['right'], ENT_QUOTES, 'UTF-8' ) : null;

                // support the usual [[MediaWiki:Sidebar]] syntax of
                // ** link target|<some MW: message name> and if the
                // thing on the right side of the pipe isn't the name of a MW:
                // message, then and _only_ then render it as-is
                if ( isset( $data['display'] ) ) {
                    $textObj = $skin->msg( $data['display'] );
                    if ( $textObj->isDisabled() ) {
                        $text = htmlentities( $data['display'], ENT_QUOTES, 'UTF-8' );
                    } else {
                        $text = $textObj->text();
                    }
                } else {
                    $text = '';
                }

                // If icon and text both empty
                if ( empty( $icon ) && empty( $text ) ) {
                    continue;
                }

                // Title
                if ( isset( $data['title'] ) ) {
                    $titleObj = $skin->msg( $data['title'] );
                    if ( $titleObj->isDisabled() ) {
                        $title = htmlentities( $data['title'], ENT_QUOTES, 'UTF-8' );
                    } else {
                        $title = $titleObj->text();
                    }
                } else {
                    $title = $text;
                }

                // Link href
                if ( isset( $data['link'] ) ) {
                    // @todo CHECKME: Should this use wfUrlProtocols() or somesuch instead?
                    if ( preg_match( '/^((?:(?:http(?:s)?)?:)?\/\/(?:.{4,}))$/i', $data['link'] ) ) {
                        $href = htmlentities( $data['link'], ENT_QUOTES, 'UTF-8' );
                    } else {
                        $href = str_replace( '%3A', ':', urlencode( $data['link'] ) );
                        $href = str_replace( '$1', $href, $wgArticlePath );
                    }
                } else {
                    $href = null;
                }

                if ( isset( $data['access'] ) ) {
                    // Access
                    $access = preg_match( '/^([0-9a-z]{1})$/i', $data['access'] ) ? $data['access'] : '';
                } else {
                    $access = null;
                }

                if ( isset( $data['class'] ) ) {
                    // Classes
                    $classes = explode( ',', htmlentities( $data['class'], ENT_QUOTES, 'UTF-8' ) );
                    foreach ( $classes as $key => $value ) {
                        $classes[$key] = trim( $value );
                    }
                } else {
                    $classes = [];
                }

                $item = [
                    'access' => $access,
                    'classes' => $classes,
                    'href' => $href,
                    'icon' => $icon,
                    'text' => $text,
                    'title' => $title,
                    'group' => $group,
                    'right' => $right
                ];
                $level2Children = &$item['children'];
                $headings[] = $item;
                continue;
            }
            if ( $line[2] !== '*' ) {
                // Second level menu
                $data = [];
                $split = explode( '|', $line );
                $split[0] = substr( $split[0], 2 );
                foreach ( $split as $key => $value ) {
                    $valueArr = explode( '=', trim( $value ) );
                    if ( isset( $valueArr[1] ) ) {
                        $data[$valueArr[0]] = $valueArr[1];
                    } else {
                        $data[$types[$key]] = trim( $value );
                    }
                }

                // Icon
                $icon = isset( $data['icon'] ) ? htmlentities( $data['icon'], ENT_QUOTES, 'UTF-8' ) : null;

                // Group
                $group = isset( $data['group'] ) ? htmlentities( $data['group'], ENT_QUOTES, 'UTF-8' ) : null;

                // Right
                $right = isset( $data['right'] ) ? htmlentities( $data['right'], ENT_QUOTES, 'UTF-8' ) : null;

                // support the usual [[MediaWiki:Sidebar]] syntax of
                // ** link target|<some MW: message name> and if the
                // thing on the right side of the pipe isn't the name of a MW:
                // message, then and _only_ then render it as-is
                if ( isset( $data['display'] ) ) {
                    $textObj = $skin->msg( $data['display'] );
                    if ( $textObj->isDisabled() ) {
                        $text = htmlentities( $data['display'], ENT_QUOTES, 'UTF-8' );
                    } else {
                        $text = $textObj->text();
                    }
                } else {
                    $text = '';
                }

                // If icon and text both empty
                if ( empty( $icon ) && empty( $text ) ) {
                    continue;
                }

                // Title
                if ( isset( $data['title'] ) ) {
                    $titleObj = $skin->msg( $data['title'] );
                    if ( $titleObj->isDisabled() ) {
                        $title = htmlentities( $data['title'], ENT_QUOTES, 'UTF-8' );
                    } else {
                        $title = $titleObj->text();
                    }
                } else {
                    $title = $text;
                }

                if ( isset( $data['link'] ) ) {
                    // Link href
                    // @todo CHECKME: Should this use wfUrlProtocols() or somesuch instead?
                    if ( preg_match( '/^((?:(?:http(?:s)?)?:)?\/\/(?:.{4,}))$/i', $data['link'] ) ) {
                        $href = htmlentities( $data['link'], ENT_QUOTES, 'UTF-8' );
                    } else {
                        $href = str_replace( '%3A', ':', urlencode( $data['link'] ) );
                        $href = str_replace( '$1', $href, $wgArticlePath );
                    }
                }

                if ( isset( $data['access'] ) ) {
                    // Access
                    $access = preg_match( '/^([0-9a-z]{1})$/i', $data['access'] ) ? $data['access'] : '';
                } else {
                    $access = null;
                }

                if ( isset( $data['class'] ) ) {
                    // Classes
                    $classes = explode( ',', htmlentities( $data['class'], ENT_QUOTES, 'UTF-8' ) );
                    foreach ( $classes as $key => $value ) {
                        $classes[$key] = trim( $value );
                    }
                } else {
                    $classes = [];
                }

                $item = [
                    'access' => $access,
                    'classes' => $classes,
                    'href' => $href,
                    'icon' => $icon,
                    'text' => $text,
                    'title' => $title,
                    'group' => $group,
                    'right' => $right
                ];
                $level3Children = &$item['children'];
                $level2Children[] = $item;
                continue;
            }
            if ( $line[3] !== '*' ) {
                // Third level menu
                $data = [];
                $split = explode( '|', $line );
                $split[0] = substr( $split[0], 3 );
                foreach ( $split as $key => $value ) {
                    $valueArr = explode( '=', trim( $value ) );
                    if ( isset( $valueArr[1] ) ) {
                        $data[$valueArr[0]] = $valueArr[1];
                    } else {
                        $data[$types[$key]] = trim( $value );
                    }
                }

                // Icon
                $icon = isset( $data['icon'] ) ? htmlentities( $data['icon'], ENT_QUOTES, 'UTF-8' ) : null;

                // Group
                $group = isset( $data['group'] ) ? htmlentities( $data['group'], ENT_QUOTES, 'UTF-8' ) : null;

                // Right
                $right = isset( $data['right'] ) ? htmlentities( $data['right'], ENT_QUOTES, 'UTF-8' ) : null;

                // support the usual [[MediaWiki:Sidebar]] syntax of
                // ** link target|<some MW: message name> and if the
                // thing on the right side of the pipe isn't the name of a MW:
                // message, then and _only_ then render it as-is
                if ( isset( $data['display'] ) ) {
                    $textObj = $skin->msg( $data['display'] );
                    if ( $textObj->isDisabled() ) {
                        $text = htmlentities( $data['display'], ENT_QUOTES, 'UTF-8' );
                    } else {
                        $text = $textObj->text();
                    }
                } else {
                    $text = '';
                }

                // If icon and text both empty
                if ( empty( $icon ) && empty( $text ) ) {
                    continue;
                }

                // Title
                if ( isset( $data['title'] ) ) {
                    $titleObj = $skin->msg( $data['title'] );
                    if ( $titleObj->isDisabled() ) {
                        $title = htmlentities( $data['title'], ENT_QUOTES, 'UTF-8' );
                    } else {
                        $title = $titleObj->text();
                    }
                } else {
                    $title = $text;
                }

                // Link href
                // @todo CHECKME: Should this use wfUrlProtocols() or somesuch instead?
                if ( preg_match( '/^((?:(?:http(?:s)?)?:)?\/\/(?:.{4,}))$/i', $data['link'] ) ) {
                    $href = htmlentities( $data['link'], ENT_QUOTES, 'UTF-8' );
                } else {
                    $href = str_replace( '%3A', ':', urlencode( $data['link'] ) );
                    $href = str_replace( '$1', $href, $wgArticlePath );
                }

                // Access
                if ( isset( $data['access'] ) ) {
                    $access = preg_match( '/^([0-9a-z]{1})$/i', $data['access'] ) ? $data['access'] : '';
                } else {
                    $access = null;
                }

                if ( isset( $data['class'] ) ) {
                    // Classes
                    $classes = explode( ',', htmlentities( $data['class'], ENT_QUOTES, 'UTF-8' ) );
                    foreach ( $classes as $key => $value ) {
                        $classes[$key] = trim( $value );
                    }
                } else {
                    $classes = [];
                }

                $item = [
                    'access' => $access,
                    'classes' => $classes,
                    'href' => $href,
                    'icon' => $icon,
                    'text' => $text,
                    'title' => $title,
                    'group' => $group,
                    'right' => $right
                ];
                $level3Children[] = $item;
                continue;
            } else {
                // Not supported
                continue;
            }
        }

        return $headings;
    }

다만 a15075a 커밋 이후의 몇개의 수정사항이 반영되어 있지 않을 수 있어서 이 부분은 확인해 주시면 감사하겠습니다.

Hoto-Cocoa commented 1 month ago

image 재현되지 않는데 최신 버전의 코드에서도 재발하는지 확인 부탁드립니다.

gaon12 commented 1 month ago

image 재현되지 않는데 최신 버전의 코드에서도 재발하는지 확인 부탁드립니다.


  1. 최신 버전 사용중입니다. 혹시 몰라서 새로 git clone 했습니다. image

  2. 여전히 동일합니다. (로고 짤리는건 css 문제라 무시하서도 됩니다.) image

  3. https://beta.gaonwiki.com 확인을 위해 링크를 남겨드립니다.

추석 연휴인데 고생 많으십니다.