문제가 발생하였습니다.

FATAL ERROR : Uncaught TypeError: modules\naddle\coursemos\dtos\ContentBlock::getImageTag(): Argument #1 ($block) must be of type ?object, string given, called in /var/www/html/modules/naddle/coursemos/dtos/ContentBlock.php on line 124 and defined in /var/www/html/modules/naddle/coursemos/dtos/ContentBlock.php:35 /var/www/html/modules/naddle/coursemos/dtos/ContentBlock.php on line 35
  • /var/www/html/modules/naddle/coursemos/dtos/ContentBlock.php
  • 16
        private mixed $_value;
    
  • 17
  • 18
        /**
    
  • 19
         * 인터뷰 내용 블럭 구조체를 정의한다.
    
  • 20
         *
    
  • 21
         * @param object $interview 인터뷰정보
    
  • 22
         */
    
  • 23
        public function __construct(object $block)
    
  • 24
        {
    
  • 25
            $this->_type = $block->type;
    
  • 26
            $this->_value = $block->value;
    
  • 27
        }
    
  • 28
  • 29
        /**
    
  • 30
         * 이미지를 위한 태그를 가져온다.
    
  • 31
         *
    
  • 32
         * @param object $block 이미지블럭 객체
    
  • 33
         * @return string $image
    
  • 34
         */
    
  • 35
        public function getImageTag(object $block = null): string
    
  • 36
        {
    
  • 37
            if ($block === null) {
    
  • 38
                return '';
    
  • 39
            }
    
  • 40
  • 41
            /**
    
  • 42
             * @var \modules\attachment\Attachment $mAttachment
    
  • 43
             */
    
  • 44
            $mAttachment = \Modules::get('attachment');
    
  • 45
            $image = $mAttachment->getAttachment($block->image);
    
  • 46
  • 47
            if ($image === null) {
    
  • 48
                return '';
    
  • 49
            }
    
  • 50
  • 51
            $ratio = 'aspect-ratio: ' . $image->getWidth() . '/' . $image->getHeight() . ';';
    
  • 52
            $background = 'background-image: url(' . $image->getUrl('view') . ');';
    
  • 53
  • 54
            return \Html::element(
    
  • 55
                'div',
    
  • 56
                [
    
  • /var/www/html/modules/naddle/coursemos/dtos/ContentBlock.php
  • 105
                    $rows = [];
    
  • 106
                    foreach ($this->_value ?? [] as $index => $row) {
    
  • 107
                        $rows[] = \Html::tag(
    
  • 108
                            '<li>',
    
  • 109
                            '<b><i>' . ($index + 1) . '</i>' . $row->value->title . '</b>',
    
  • 110
                            '<p>' . $row->value->text . '</p>',
    
  • 111
                            '</li>'
    
  • 112
                        );
    
  • 113
                    }
    
  • 114
                    $ul = \Html::element('ul', null, \Html::tag(...$rows));
    
  • 115
                    $html .= $ul;
    
  • 116
                    break;
    
  • 117
  • 118
                case 'card':
    
  • 119
                    \Html::script(\Modules::get('naddle/coursemos')->getBase() . '/scripts/swiper-bundle.min.js');
    
  • 120
                    \Html::style(\Modules::get('naddle/coursemos')->getBase() . '/styles/swiper-bundle.min.css');
    
  • 121
  • 122
                    $rows = [];
    
  • 123
                    foreach ($this->_value ?? [] as $row) {
    
  • 124
                        $rows[] = \Html::element('div', ['class' => 'swiper-slide'], $this->getImageTag($row->value));
    
  • 125
                    }
    
  • 126
                    $swiper = \Html::element('div', ['class' => 'swiper-wrapper'], \Html::tag(...$rows));
    
  • 127
  • 128
                    $controller = \Html::tag(
    
  • 129
                        '<div class="controller">',
    
  • 130
                        '<div class="scrollbar"></div>',
    
  • 131
                        '<aside>',
    
  • 132
                        '<button type="button" data-role="action" data-action="prev" class="border sm left">',
    
  • 133
                        '<span><i class="mi mi-angle-left"></i></span>',
    
  • 134
                        '</button>',
    
  • 135
                        '<button type="button" data-role="action" data-action="next" class="border sm">',
    
  • 136
                        '<span><i class="mi mi-angle-right"></i></span>',
    
  • 137
                        '</button>',
    
  • 138
                        '</aside>',
    
  • 139
                        '</div>'
    
  • 140
                    );
    
  • 141
  • 142
                    $html .= \Html::tag(
    
  • 143
                        '<div data-role="container" class="widecard">',
    
  • 144
                        '<div>',
    
  • 145
                        \Html::element('div', ['data-role' => 'swiper'], \Html::tag($swiper, $controller)),
    
  • /var/www/html/modules/naddle/coursemos/templates/www/contexts/article.view.html
  • 68
                                    </p>
    
  • 69
                                </li>
    
  • 70
                                <li>
    
  • 71
                                    <b>URL</b>
    
  • 72
                                    <a href="<?php echo $article->getMeta('homepage'); ?>"><?php echo $article->getMeta('homepage'); ?></a>
    
  • 73
                                </li>
    
  • 74
                            </ul>
    
  • 75
                        </div>
    
  • 76
                    </div>
    
  • 77
                </div>
    
  • 78
            </article>
    
  • 79
            <?php } else { ?>
    
  • 80
            <article class="landing">
    
  • 81
                <div data-role="container" class="fullsize">
    
  • 82
                    <div><div class="<?php echo $type; ?> darktone" style="background-image:url(<?php echo $article->getImage()->getUrl('view'); ?>);"></div></div>
    
  • 83
                </div>
    
  • 84
            </article>
    
  • 85
            <?php } ?>
    
  • 86
            
    
  • 87
            <?php foreach ($article->getContent() as $block) { $block->doLayout(); } ?>
    
  • 88
            
    
  • 89
            <?php if ($type == 'case' && $article->getInterview() !== null) { ?>
    
  • 90
            <article class="interview">
    
  • 91
                <i <?php echo $article->getInterview()->getImage() !== null ? ' style="background-image:url(' . $article->getInterview()->getImage()->getUrl('thumbnail') . ');"' : ' '; ?>></i>
    
  • 92
                <div>
    
  • 93
                    <b><?php echo $article->getInterview()->getMeta('interviewee'); ?></b>
    
  • 94
                    <a href="<?php echo $article->getInterview()->getUrl(); ?>">담당자 인터뷰 보러가기<i class="mi mi-external"></i></a>
    
  • 95
                </div>
    
  • 96
            </article>
    
  • 97
            <?php } ?>
    
  • 98
        </div>
    
  • 99
        
    
  • 100
        <div data-role="buttons" class="right">
    
  • 101
            <div>
    
  • 102
                <a href="<?php echo $article->getPrevUrl() ?? 'javascript:void(0);" disabled="disable'; ?>" data-role="action" class="border left">
    
  • 103
                    <span><i class="mi mi-angle-left"></i></span>
    
  • 104
                </a>
    
  • 105
                <a href="<?php echo $article->getNextUrl() ?? 'javascript:void(0);" disabled="disable'; ?>" data-role="action" class="border right">
    
  • 106
                    <span><i class="mi mi-angle-right"></i></span>
    
  • 107
                </a>
    
  • 108
            </div>
    
  • /var/www/html/modules/naddle/coursemos/Coursemos.php
  • 160
                }
    
  • 161
  • 162
                $readed = \Request::session('MODULE_COURSEMOS_ARTICLE_READED') ?? [];
    
  • 163
                if (in_array($article_id, $readed) == false) {
    
  • 164
                    $readed[] = $article_id;
    
  • 165
                    $_SESSION['MODULE_COURSEMOS_ARTICLE_READED'] = $readed;
    
  • 166
  • 167
                    $this->db()
    
  • 168
                        ->update($this->table('articles'), ['hits' => $this->db()->increase()])
    
  • 169
                        ->where('article_id', $article_id)
    
  • 170
                        ->execute();
    
  • 171
                }
    
  • 172
  • 173
                \Html::title($article->getTitle());
    
  • 174
                \Html::image($article->getImage());
    
  • 175
  • 176
                $template->assign('article', $article);
    
  • 177
            }
    
  • 178
  • 179
            return $template->getContext('article.' . $view, $header, $footer);
    
  • 180
        }
    
  • 181
  • 182
        /**
    
  • 183
         * 애뉴얼 리포트 컨텍스트를 가져온다.
    
  • 184
         *
    
  • 185
         * @return string $html
    
  • 186
         */
    
  • 187
        public function getReportContext(): string
    
  • 188
        {
    
  • 189
            $template = $this->getTemplate();
    
  • 190
            return $template->getContext('report');
    
  • 191
        }
    
  • 192
  • 193
        /**
    
  • 194
         * 게시물 객체를 가져온다.
    
  • 195
         *
    
  • 196
         * @param string|object $article_id 게시물고유값
    
  • 197
         * @return \modules\naddle\coursemos\dtos\Article $article
    
  • 198
         */
    
  • 199
        public function getArticle(string|object $article_id): ?\modules\naddle\coursemos\dtos\Article
    
  • 200
        {
    
  • /var/www/html/modules/naddle/coursemos/Coursemos.php
  • 73
         *
    
  • 74
         * @param string $context 컨텍스트명
    
  • 75
         * @param ?object $configs 컨텍스트 설정
    
  • 76
         * @return string $html
    
  • 77
         */
    
  • 78
        public function getContext(string $context, ?object $configs = null): string
    
  • 79
        {
    
  • 80
            /**
    
  • 81
             * 컨텍스트 템플릿을 설정한다.
    
  • 82
             */
    
  • 83
            if (isset($configs?->template) == true && $configs->template->name !== '#') {
    
  • 84
                $this->setTemplate($configs->template);
    
  • 85
            } else {
    
  • 86
                $this->setTemplate($this->getConfigs('template'));
    
  • 87
            }
    
  • 88
  • 89
            $content = '';
    
  • 90
            switch ($context) {
    
  • 91
                case 'article':
    
  • 92
                    $content = $this->getArticleContext($configs?->type ?? null);
    
  • 93
                    break;
    
  • 94
  • 95
                case 'report':
    
  • 96
                    $content = $this->getReportContext();
    
  • 97
                    break;
    
  • 98
  • 99
                default:
    
  • 100
                    $content = \ErrorHandler::get(\ErrorHandler::error('NOT_FOUND_URL'));
    
  • 101
            }
    
  • 102
  • 103
            return $this->getTemplate()->getLayout($content);
    
  • 104
        }
    
  • 105
  • 106
        /**
    
  • 107
         * 게시물 컨텍스트를 가져온다.
    
  • 108
         *
    
  • 109
         * @param ?string $type 게시구분
    
  • 110
         * @return string $html
    
  • 111
         */
    
  • 112
        public function getArticleContext(?string $type = null): string
    
  • 113
        {
    
  • /var/www/html/classes/Module.php
  • 305
         *
    
  • 306
         * @param string $context 컨텍스트
    
  • 307
         * @param ?object $configs 컨텍스트 설정
    
  • 308
         * @return string $html
    
  • 309
         */
    
  • 310
        protected function getContext(string $context, ?object $configs = null): string
    
  • 311
        {
    
  • 312
            return ErrorHandler::get($this->error('NOT_FOUND_CONTEXT_METHOD', $context, $configs));
    
  • 313
        }
    
  • 314
  • 315
        /**
    
  • 316
         * 모듈 컨텍스트의 내용을 모듈 컨테이너와 함께 가져온다.
    
  • 317
         *
    
  • 318
         * @param string $context 컨텍스트
    
  • 319
         * @param ?object $configs 컨텍스트 설정
    
  • 320
         * @return string $html
    
  • 321
         */
    
  • 322
        final public function getContent(string $context, ?object $configs = null): string
    
  • 323
        {
    
  • 324
            $content = $this->getContext($context, $configs);
    
  • 325
  • 326
            $attributes = $this->_contextAttributes;
    
  • 327
            $attributes['data-role'] ??= 'module';
    
  • 328
            $attributes['data-module'] ??= $this->getName();
    
  • 329
            $attributes['data-context'] ??= $context;
    
  • 330
            $attributes['data-template'] ??= $this->getTemplate()->getName();
    
  • 331
  • 332
            return Html::element('div', $attributes, $content);
    
  • 333
        }
    
  • 334
  • 335
        /**
    
  • 336
         * 모듈 콘텐츠 컨테이터의 속성을 추가한다.
    
  • 337
         * 각 모듈 클래스에서 콘텐츠영역에 추가할 속성이 있는 경우 사용한다.
    
  • 338
         *
    
  • 339
         * @param string $name 속성명
    
  • 340
         * @param string $value 속성값
    
  • 341
         */
    
  • 342
        final protected function setContextAttribute(string $name, string $value): void
    
  • 343
        {
    
  • 344
            $this->_contextAttributes[$name] = $value;
    
  • 345
        }
    
  • /var/www/html/classes/Context.php
  • 476
  • 477
                case 'PAGE':
    
  • 478
                    if (
    
  • 479
                        $this->getSite()
    
  • 480
                            ->getTheme()
    
  • 481
                            ->getPathName() == $this->_target
    
  • 482
                    ) {
    
  • 483
                        $theme = $this->getSite()->getTheme();
    
  • 484
                        $theme->assign('site', $this->getSite());
    
  • 485
                        $theme->assign('theme', $this->getSite()->getTheme());
    
  • 486
                        $theme->assign('context', $this);
    
  • 487
                        $theme->assign('route', $route);
    
  • 488
                        $content = $theme->getPage($this->_context);
    
  • 489
                    } else {
    
  • 490
                        $content = '';
    
  • 491
                    }
    
  • 492
                    break;
    
  • 493
  • 494
                case 'MODULE':
    
  • 495
                    $content = Modules::get($this->_target, $route)->getContent($this->_context, $this->_context_configs);
    
  • 496
                    break;
    
  • 497
            }
    
  • 498
  • 499
            return $content;
    
  • 500
        }
    
  • 501
  • 502
        /**
    
  • 503
         * 사이트맵에 포함되는지 여부를 가져온다.
    
  • 504
         *
    
  • 505
         * @return bool $is_sitemap
    
  • 506
         */
    
  • 507
        public function isSitemap(): bool
    
  • 508
        {
    
  • 509
            return $this->_is_sitemap;
    
  • 510
        }
    
  • 511
  • 512
        /**
    
  • 513
         * 사이트 하단메뉴에 포함되는지 여부를 가져온다.
    
  • 514
         *
    
  • 515
         * @return bool $is_footer_menu
    
  • 516
         */
    
  • /var/www/html/classes/Route.php
  • 250
                } else {
    
  • 251
                    $url .= '&';
    
  • 252
                }
    
  • 253
  • 254
                $url .= http_build_query($queryString);
    
  • 255
            }
    
  • 256
  • 257
            return $url;
    
  • 258
        }
    
  • 259
  • 260
        /**
    
  • 261
         * context, html, json 타입의 경로에 해당하는 콘텐츠를 가져온다.
    
  • 262
         *
    
  • 263
         * @return string $content
    
  • 264
         */
    
  • 265
        public function getContent(): string
    
  • 266
        {
    
  • 267
            $values = array_values($this->getValues());
    
  • 268
            array_unshift($values, $this);
    
  • 269
            return call_user_func_array($this->_closure, $values);
    
  • 270
        }
    
  • 271
  • 272
        /**
    
  • 273
         * blob 타입의 경로에 해당하는 콘텐츠를 가져온다.
    
  • 274
         */
    
  • 275
        public function printContent(): void
    
  • 276
        {
    
  • 277
            $values = array_values($this->getValues());
    
  • 278
            array_unshift($values, $this);
    
  • 279
            call_user_func_array($this->_closure, $values);
    
  • 280
        }
    
  • 281
    }
    
  • /var/www/html/classes/iModules.php
  • 445
             */
    
  • 446
            $context = Contexts::get($route);
    
  • 447
  • 448
            /**
    
  • 449
             * 컨텍스트 및 설명에 대한 META 태그 및 고유주소 META 태그를 정의한다. (SEO)
    
  • 450
             */
    
  • 451
            if ($route->getPath() !== '/') {
    
  • 452
                Html::title($context->getTitle() . ' - ' . $context->getSite()->getTitle());
    
  • 453
            }
    
  • 454
            if ($context->getDescription(false)) {
    
  • 455
                Html::description($context->getDescription(false));
    
  • 456
            }
    
  • 457
            if ($context->getKeywords()) {
    
  • 458
                Html::keywords($context->getKeywords());
    
  • 459
            }
    
  • 460
  • 461
            /**
    
  • 462
             * 컨텍스트의 콘텐츠를 가져온다.
    
  • 463
             */
    
  • 464
            $content = $route->getContent();
    
  • 465
  • 466
            /**
    
  • 467
             * 사이트의 레이아웃에 콘텐츠를 포함하여 가져온다.
    
  • 468
             */
    
  • 469
            $theme = $route->getSite()->getTheme();
    
  • 470
            $theme->assign('site', $context->getSite());
    
  • 471
            $theme->assign('context', $context);
    
  • 472
            $layout = $theme->getLayout($context->getLayout(), $content);
    
  • 473
  • 474
            self::loadingTime('doContext');
    
  • 475
  • 476
            /**
    
  • 477
             * HTML 헤더 및 푸터를 포함하여 출력한다.
    
  • 478
             * @todo 이벤트
    
  • 479
             */
    
  • 480
            Html::body('data-context-url', $context->getUrl());
    
  • 481
            Html::body('data-color-scheme', Request::cookie('IM_COLOR_SCHEME') ?? 'auto', false);
    
  • 482
            Html::print(Html::header(), $layout, Html::footer());
    
  • 483
  • 484
            Html::print(
    
  • 485
                Html::tag(
    
  • /var/www/html/classes/iModules.php
  • 391
            }
    
  • 392
  • 393
            self::loadingTime('initContent');
    
  • 394
        }
    
  • 395
  • 396
        /**
    
  • 397
         * 요청에 따른 응답을 처리한다.
    
  • 398
         */
    
  • 399
        public static function respond(): void
    
  • 400
        {
    
  • 401
            self::init();
    
  • 402
  • 403
            $route = Router::get();
    
  • 404
  • 405
            /**
    
  • 406
             * 경로 타입에 따라 응답을 처리한다.
    
  • 407
             */
    
  • 408
            switch ($route->getType()) {
    
  • 409
                case 'context':
    
  • 410
                    self::doContext($route);
    
  • 411
                    break;
    
  • 412
  • 413
                case 'html':
    
  • 414
                    self::doHtml($route);
    
  • 415
                    break;
    
  • 416
  • 417
                case 'blob':
    
  • 418
                    self::doBlob($route);
    
  • 419
                    break;
    
  • 420
            }
    
  • 421
        }
    
  • 422
  • 423
        /**
    
  • 424
         * 컨텍스트 요청을 처리한다.
    
  • 425
         *
    
  • 426
         * @param Route $route
    
  • 427
         */
    
  • 428
        public static function doContext(Route $route): void
    
  • 429
        {
    
  • 430
            /**
    
  • 431
             * 요청된 주소와 경로가 다를 경우, 정상적인 경로로 리다이렉트한다.
    
  • /var/www/html/index.php
  • 1
    <?php
    
  • 2
    /**
    
  • 3
     * 이 파일은 아이모듈의 일부입니다. (https://www.imodules.io)
    
  • 4
     *
    
  • 5
     * 사이트 최초 접속시 실행되는 파일로 기본설정을 불러오고 아이모듈 코어 클래스를 선언하여 요청된 페이지를 반환한다.
    
  • 6
     *
    
  • 7
     * @file /index.php
    
  • 8
     * @author Arzz <arzz@arzz.com>
    
  • 9
     * @license MIT License
    
  • 10
     * @modified 2022. 12. 1.
    
  • 11
     */
    
  • 12
    require_once './configs/init.php';
    
  • 13
  • 14
    /**
    
  • 15
     * 요청에 따라 응답한다.
    
  • 16
     */
    
  • 17
    iModules::respond();