function testFindValidsByUserReturnsValidConfirmations_Two()
 {
     // 視聴期限ぴったり
     $date_freeze = new DateTime("2015-08-15 00:00:00+09:00");
     timecop_freeze($date_freeze->getTimestamp());
     $settings = plugin_movieviewer_get_global_settings();
     $repo = new MovieViewerDealPackPaymentConfirmationRepositoryInFile($settings);
     $objects = $repo->findValidsByUser("*****@*****.**");
     $this->assertEquals(2, count($objects));
     $this->assertEquals("K1Kiso-1", $objects[0]->getPack()->getId());
     $this->assertEquals("K2Kiso-1", $objects[1]->getPack()->getId());
 }
 function testRestoreDeserializeObjectAndDeleteTempFile()
 {
     $date_freeze = new DateTime("2015-08-14 23:59:59+09:00");
     timecop_freeze($date_freeze->getTimestamp());
     $settings = plugin_movieviewer_get_global_settings();
     $repo = new MovieViewerReviewPackPurchaseRequestRepositoryInFile($settings);
     $object = new MovieViewerReviewPackPurchaseRequest("*****@*****.**", "credit", array("K1Kiso_01"));
     $stash_id = $repo->stash($object);
     $object = $repo->restore($stash_id);
     $this->assertEquals("*****@*****.**", $object->user_id);
     $this->assertFalse(file_exists("test/models/resources/purchase/review_pack/_stash/{$stash_id}.yml"));
 }
 function testStoreSaveToFile()
 {
     $date_freeze = new DateTime("2015-08-14 23:59:59+09:00");
     timecop_freeze($date_freeze->getTimestamp());
     $settings = plugin_movieviewer_get_global_settings();
     $repo = new MovieViewerReviewPackPaymentConfirmationRepositoryInFile($settings);
     $request = new MovieViewerReviewPackPurchaseRequest("*****@*****.**", "credit", array("K1Kiso_01"));
     $object = MovieViewerReviewPackPaymentConfirmation::createFromRequest($request, null);
     $repo->store($object);
     $object = $repo->findBy("*****@*****.**", "20150814235959+0900");
     $this->assertEquals("*****@*****.**", $object->user_id);
     $this->assertEquals("credit", $object->purchase_method);
     $items = $object->getItems();
     $this->assertEquals(1, count($items));
     $this->assertEquals("K1Kiso", $items[0]->course_id);
     $this->assertEquals("01", $items[0]->session_id);
     $viewing_period = $object->getViewingPeriod();
     $this->assertEquals(new DateTime("2015-08-16 00:00:00+09:00"), $viewing_period->date_begin);
     $this->assertEquals(new DateTime("2015-09-15 23:59:59+09:00"), $viewing_period->date_end);
 }
 function findById($id)
 {
     $yaml = Spyc::YAMLLoad($this->getFilePath($id));
     $object = new MovieViewerViewingPeriodsByUser($id);
     $timezone = plugin_movieviewer_get_global_settings()->timezone;
     foreach ($yaml['viewing_periods'] as $period) {
         $date_begin = new DateTime($period["date_begin"], $timezone);
         $date_end = new DateTime($period["date_end"], $timezone);
         $period["session_id"] = sprintf("%02d", $period["session_id"]);
         $object->addPeriod($period["course_id"], $period["session_id"], $date_begin, $date_end);
     }
     return $object;
 }
/**
 * [アクション] 入金を確定させ、結果画面を生成する
 *
 * @return array ページ名, 画面(html)
 */
function plugin_movieviewer_review_purchase_confirm_payment_action_execute()
{
    $page = plugin_movieviewer_get_current_page();
    try {
        plugin_movieviewer_validate_csrf_token();
    } catch (MovieViewerValidationException $ex) {
        return plugin_movieviewer_action_error_response($page, "不正なリクエストです。");
    }
    $ids = filter_input(INPUT_POST, 'purchase_requests', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY);
    foreach ($ids as $req_id) {
        try {
            plugin_movieviewer_validate_review_pack_request_id($req_id);
        } catch (MovieViewerValidationException $ex) {
            return plugin_movieviewer_action_error_response($page, "指定した内容に誤りがあります。");
        }
    }
    $requests = array();
    foreach ($ids as $req_id) {
        try {
            $request = plugin_movieviewer_get_review_pack_purchase_request_repository()->findById($req_id);
        } catch (MovieViewerRepositoryObjectNotFoundException $ex) {
            return plugin_movieviewer_action_error_response($page, "指定した内容に誤りがあります。");
        }
        $requests[] = $request;
    }
    if (count($requests) === 0) {
        return plugin_movieviewer_action_error_response($page, "申し込みが見つかりません。");
    }
    $date_begin = filter_input(INPUT_POST, 'viewing_perod_date_begin', FILTER_DEFAULT);
    try {
        plugin_movieviewer_validate_ymd($date_begin);
    } catch (MovieViewerValidationException $ex) {
        return plugin_movieviewer_action_error_response($page, "指定した内容に誤りがあります。");
    }
    $date_begin = new DateTime($date_begin);
    $settings = plugin_movieviewer_get_global_settings();
    $service = new MovieViewerReviewPackPurchaseConfirmationService($settings);
    $hsc = "plugin_movieviewer_hsc";
    $content_rows = "";
    foreach ($requests as $request) {
        $confirmation = $service->confirm($request, $date_begin);
        $content_row = <<<TEXT
        <tr>
          <td>{$hsc($request->getUser()->lastName)} {$hsc($request->getUser()->firstName)}</td>
          <td>{$hsc($request->getUser()->id)}</td>
          <td>{$hsc($request->describePack())}</td>
          <td>{$hsc($request->getDateRequested()->format("Y/m/d H:m:s"))}</td>
          <td>{$hsc($confirmation->getViewingPeriod()->date_begin->format("Y/m/d"))}</td>
          <td>{$hsc($confirmation->getViewingPeriod()->date_end->format("Y/m/d"))}</td>
        </tr>
TEXT;
        $content_rows .= $content_row;
    }
    $content = <<<TEXT
    <script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
    <script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
    <link href="https://code.jquery.com/ui/1.12.0/themes/cupertino/jquery-ui.css" rel="stylesheet">
    <link href="plugin/movieviewer/assets/css/movieviewer.css" rel="stylesheet">
    <h2>入金確認完了</h2>
    <p>
      以下の申し込みの入金を確定しました。
    </p>
    <p>
    <table class="table purchase-requests">
      <thead>
      <tr>
        <th>名前</th>
        <th>メールアドレス</th>
        <th>受講対象</th>
        <th>申込日</th>
        <th>視聴期限(開始)</th>
        <th>視聴期限(終了)</th>
      </tr>
      </thead>
      <tbody>
        {$content_rows}
      <tbody>
    </table>
    </p>
TEXT;
    return array('msg' => $page, 'body' => $content);
}
/**
 * プラグイン規定関数::ブロック型で呼び出された場合の処理
 * 認証済みの場合: 再視聴対象選択画面を生成する
 * 未認証の場合: エラー画面を生成する
 *
 * 引数: なし
 *
 * @return string 画面(html)
 */
function plugin_movieviewer_review_convert()
{
    try {
        $user = plugin_movieviewer_get_current_user();
    } catch (MovieViewerRepositoryObjectNotFoundException $ex) {
        return plugin_movieviewer_convert_error_response("ログインが必要です。");
    }
    $plugin_args = func_get_args();
    try {
        plugin_movieviewer_review_assert_plugin_arguments($plugin_args);
    } catch (Exception $ex) {
        return plugin_movieviewer_convert_error_response("プラグインの引数が設定されていません。");
    }
    $start_page_bank = $plugin_args[0];
    $start_page_credit = $plugin_args[1];
    $viewing_periods = plugin_movieviewer_get_viewing_periods_by_user_repository()->findById($user->id);
    $requests_not_yet_confirmed = plugin_movieviewer_get_review_pack_purchase_request_repository()->findNotYetConfirmed($user->id);
    $hsc = "plugin_movieviewer_hsc";
    // 期限の切れているものをリストアップ
    $viewing_periods = $viewing_periods->getExpiredPeriods();
    // コースごとに分類
    $viewing_periods_by_course = MovieViewerViewingPeriod::sortByCourse($viewing_periods);
    $courses = plugin_movieviewer_get_courses_repository()->find();
    $content_courses = "";
    foreach ($viewing_periods_by_course as $course_id => $periods) {
        $course = $courses->getCourse($course_id);
        $content_periods = "";
        foreach ($periods as $period) {
            if (MovieViewerReviewPackPurchaseRequest::requestsHasItem($requests_not_yet_confirmed, $course_id, $period->session_id)) {
                continue;
            }
            $session = $course->getSession($period->session_id);
            $field_id = "{$hsc($course->id)}_{$hsc($session->id)}";
            $content_periods .= <<<TEXT
            <label class='movie-session' for="{$field_id}">{$session->describe()}</label>
            <input class='movie-session' type="checkbox" name="sessions" id="{$field_id}" value="{$field_id}">
TEXT;
        }
        if ($content_periods === "") {
            continue;
        }
        $content_course = <<<TEXT
        <div class='movieviewer-course'>
        <h3>{$hsc($course->name)}</h3>
        <fieldset style='border: none;'>
        {$content_periods}
        </fieldset>
        </div>
TEXT;
        $content_courses .= $content_course;
    }
    $uri_start_bank = plugin_movieviewer_get_script_uri() . "?{$start_page_bank}&purchase_method=bank";
    $uri_start_credit = plugin_movieviewer_get_script_uri() . "?{$start_page_credit}&purchase_method=credit";
    $buttons_payment = <<<TEXT
    <a href="{$uri_start_bank}" class='ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only'>銀行振り込みで申し込み</a>
TEXT;
    $settings = plugin_movieviewer_get_global_settings();
    if ($settings->payment->isCreditEnabled()) {
        $buttons_payment .= <<<TEXT
        <a href="{$uri_start_credit}" class='ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only'>クレジットカードで申し込み</a>
TEXT;
    }
    $content = <<<TEXT
    <script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
    <script src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"></script>
    <link href="https://code.jquery.com/ui/1.12.0/themes/cupertino/jquery-ui.css" rel="stylesheet">
    <script src="plugin/movieviewer/assets/js/movieviewer_review.js"></script>
    <link href="plugin/movieviewer/assets/css/movieviewer.css" rel="stylesheet">
    <link href="plugin/movieviewer/assets/css/movieviewer_review.css" rel="stylesheet">
    <style>
    </style>

    <h2>再視聴可能な単元</h2>

    <p>
    再視聴したい単元を選択して、申し込みボタンを押してください。
    </p>
    <p>
    <ul style='margin-left:0;'>
        <li>1回にお申込みいただける回数は最大4回分までです。
        <li>ご入金後のキャンセル、変更はできません。
        <li>視聴可能な単元(通常受講分)がある場合、平行してご覧いただけます。
    </ul>
    </p>

    {$content_courses}

    <div style="margin-top:10px;">
    {$buttons_payment}
    <ul style='margin-left:0;margin-top:1.5em;'>
        <li>再視聴が可能な期間は、1ヵ月のみです。ご入金確認後、約1週間後から視聴が 可能になります。<br>確定した期間については、マイページにてご確認ください。ご自身で期間を指 定することはできません。
        <li>複数回の再視聴をお申込みの場合、すべて同時視聴となり、視聴可能期間は 1ヵ月のみとなります。<br>第1回から第4回までを1回分1ヵ月ずつずらして4か月ご覧になりたい場合は、 お手数ですが1回分ずつお申込み下さい。<br>第1回の再視聴が終了してから第2回をお申込みいただくか、 再視聴期間が終わる頃に第2回をお申込み下さい。
    </ul>
    </div>
TEXT;
    return $content;
}
/**
 * [ブロック] 視聴期限から単元の一覧を生成する
 *
 * @param array $viewing_periods 視聴期限
 *
 * @return string 単元の一覧(html)
 */
function plugin_movieviewer_convert_render_courses($viewing_periods)
{
    if (count($viewing_periods) == 0) {
        return "<div>対象の動画はありません。</div>";
    }
    $body_courses = "";
    $body_course = "";
    $current_course_id = "";
    $hsc = "plugin_movieviewer_hsc";
    $courses = plugin_movieviewer_get_courses_repository()->find();
    $timezone = plugin_movieviewer_get_global_settings()->timezone;
    $date_now = new DateTime(null, $timezone);
    foreach ($viewing_periods as $period) {
        $isValid = $period->isValid($date_now);
        $course = $courses->getCourse($period->course_id);
        $session = $course->getSession($period->session_id);
        $body_chapters = "";
        foreach ($session->chapters as $chapter) {
            $list_item = $hsc($chapter->describe());
            if ($isValid) {
                $list_item = <<<TEXT
                            <a href="#" onclick="return movieviewer_showMovie('{$hsc($course->name)}',
                                '{$hsc($session->describe())}',
                                '{$hsc($chapter->describe())}',
                                '{$hsc($course->id)}',
                                '{$hsc($session->id)}',
                                '{$hsc($chapter->id)}');">{$hsc($chapter->describe())}</a>
TEXT;
            }
            $body_chapters .= <<<TEXT
                        <li>{$list_item}</li>
TEXT;
        }
        if ($isValid) {
            $action = <<<TEXT
                  <button class="movieviewer-course-text-download" id="{$hsc($course->id)}_{$hsc($session->id)}_text_download" style="position:absolute;right:1em;">
                    <span>テキストダウンロード</span>
                  </button>
TEXT;
        }
        $body_session = <<<TEXT
            <div style="position: relative;">
                <h4 class="movieviewer-course-title" id="{$hsc($course->id)}_{$hsc($session->id)}_title">
                  <span>{$hsc($session->describe())}</span>

                  <button class="movieviewer-course-show-chapters" id="{$hsc($course->id)}_{$hsc($session->id)}_show_chapters">
                    <span>チャプター一覧</span>
                  </button>
                  {$action}
                </h4>
                <ul id="{$hsc($course->id)}_{$hsc($session->id)}_list" class="list1" style="display:none;">
                    {$body_chapters}
                </ul>
            </div>
TEXT;
        if ($current_course_id !== $course->id) {
            if ($current_course_id !== "") {
                $body_courses .= $body_course . "</div>";
            }
            $body_course = <<<TEXT
            <div class="movieviewer-course" style="margin-bottom:30px;">
            <h3>{$hsc($course->name)}</h3>
            {$body_session}
TEXT;
            $current_course_id = $course->id;
        } else {
            $body_course .= $body_session;
        }
    }
    if ($body_course !== "") {
        $body_courses .= $body_course . "</div>";
    }
    return $body_courses;
}
 function canView($course_id, $session_id, $date_target = null)
 {
     // 指定のない場合は現在日時
     if ($date_target == null) {
         $timezone = plugin_movieviewer_get_global_settings()->timezone;
         $date_target = new DateTime(null, $timezone);
     }
     $period = $this->_periods[$this->getKey($course_id, $session_id)];
     if ($period == null) {
         return false;
     }
     return $period->isValid($date_target);
 }
/**
 * プラグイン規定関数::アクション型で呼び出された場合の処理
 * 申し込みの確定と通知メール(ユーザ、スタッフ)を送り、結果画面を生成する
 * 
 * 引数: string request_stash_id 申し込み仮ID
 * 
 * 注意: 単独で呼び出さないこと(convertの画面と連携している)
 *
 * @return array ページ名、画面(html)
 */
function plugin_movieviewer_review_purchase_start_action()
{
    $from_external_link = false;
    $test_var = filter_input(INPUT_POST, "request_stash_id");
    if (empty($test_var)) {
        $from_external_link = true;
    }
    if ($from_external_link) {
        $request_stash_id = filter_input(INPUT_GET, "request_stash_id");
    } else {
        $request_stash_id = filter_input(INPUT_POST, "request_stash_id");
    }
    if (!$from_external_link) {
        try {
            plugin_movieviewer_validate_csrf_token();
        } catch (MovieViewerValidationException $ex) {
            return plugin_movieviewer_action_error_response($page, "不正なリクエストです。");
        }
    }
    try {
        $user = plugin_movieviewer_get_current_user();
    } catch (MovieViewerRepositoryObjectNotFoundException $ex) {
        return plugin_movieviewer_action_error_response($page, "ログインが必要です。");
    }
    if ($user->mailAddress === null || $user->mailAddress === "") {
        return plugin_movieviewer_action_error_response($page, "メールアドレスが登録されていません。");
    }
    $settings = plugin_movieviewer_get_global_settings();
    $service = new MovieViewerReviewPackPurchaseRequestService($settings);
    $request = null;
    try {
        $request = $service->doRequest($user, $request_stash_id);
    } catch (Exception $ex) {
        return plugin_movieviewer_action_error_response($page, $ex->getMessage());
    }
    if ($request->purchase_method === "bank") {
        $messages = plugin_movieviewer_review_purchase_start_action_bank($settings, $user, $request);
    } else {
        if ($request->purchase_method === "credit") {
            $messages = plugin_movieviewer_review_purchase_start_action_credit($settings, $user, $request);
        }
    }
    $page = plugin_movieviewer_get_current_page();
    $back_uri = plugin_movieviewer_get_home_uri();
    $content = <<<TEXT
    <link href="https://code.jquery.com/ui/1.11.4/themes/redmond/jquery-ui.css" rel="stylesheet">
    <link href="plugin/movieviewer/assets/css/movieviewer.css" rel="stylesheet">
    <h2>再視聴申し込み完了</h2>
    <p>
    {$messages}
    </p>
    <p>
    <a href="{$back_uri}" class='ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only'>マイページに戻る</a>
    </p>
TEXT;
    return array("msg" => $page, "body" => $content);
}
function plugin_movieviewer_get_auth_manager()
{
    $settings = plugin_movieviewer_get_global_settings();
    return MovieViewerAuthManagerFactory::createInstance($settings->auth_module);
}
/**
 * プラグイン規定関数::アクション型で呼び出された場合の処理
 * 申し込みを確定させる
 * 
 * 引数: string purchase_method 支払い区分(bank, credit)
 *      string deal_pack_id 受講パックID
 * 
 * 注意: 単独で呼び出さないこと(convertの画面と連携している)
 *
 * @return array ページ名、画面(html)
 */
function plugin_movieviewer_purchase_start_action()
{
    $page = plugin_movieviewer_get_current_page();
    $from_external_link = false;
    $test_var = filter_input(INPUT_POST, "purchase_method");
    if (empty($test_var)) {
        $from_external_link = true;
    }
    if ($from_external_link) {
        $deal_pack_id = filter_input(INPUT_GET, "deal_pack_id");
        $purchase_method = filter_input(INPUT_GET, "purchase_method");
    } else {
        $deal_pack_id = filter_input(INPUT_POST, "deal_pack_id");
        $purchase_method = filter_input(INPUT_POST, "purchase_method");
    }
    if (!$from_external_link) {
        try {
            plugin_movieviewer_validate_csrf_token();
        } catch (MovieViewerValidationException $ex) {
            return plugin_movieviewer_action_error_response($page, "不正なリクエストです。");
        }
    }
    try {
        $user = plugin_movieviewer_get_current_user();
    } catch (MovieViewerRepositoryObjectNotFoundException $ex) {
        return plugin_movieviewer_action_error_response($page, "ログインが必要です。");
    }
    if ($user->mailAddress === null || $user->mailAddress === "") {
        return plugin_movieviewer_action_error_response($page, "メールアドレスが登録されていません。");
    }
    try {
        plugin_movieviewer_validate_deal_pack_id($deal_pack_id);
    } catch (MovieViewerValidationException $ex) {
        return plugin_movieviewer_action_error_response($page, "指定した内容に誤りがあります。");
    }
    try {
        plugin_movieviewer_validate_purchase_method($purchase_method);
    } catch (MovieViewerValidationException $ex) {
        return plugin_movieviewer_action_error_response($page, "指定した内容に誤りがあります。");
    }
    $settings = plugin_movieviewer_get_global_settings();
    $offer_maker = new MovieViewerDealPackOfferMaker($settings->payment, $user);
    if (!$offer_maker->canOffer()) {
        return plugin_movieviewer_action_error_response($page, "ご指定のコースはすでに申し込み済み、または、受講できなくなりました。");
    }
    $offer = $offer_maker->getOffer();
    if ($offer->getPackId() !== $deal_pack_id) {
        return plugin_movieviewer_action_error_response($page, "ご指定のコースはすでに申し込み済み、または、受講できなくなりました。");
    }
    $offer->accept();
    if ($purchase_method === "bank") {
        $price_with_notes = plugin_movieviewer_render_dealpack_offer_price($offer, true);
        $mail_builder = new MovieViewerDealPackBankTransferInformationMailBuilder($settings->mail);
        $mail = $mail_builder->build($user, $offer->getPackName(), $price_with_notes, $offer->getPaymentGuide()->bank_transfer, $offer->getPaymentGuide()->deadline);
        $result = $mail->send();
        if (!$result) {
            MovieViewerLogger::getLogger()->addError("案内通知エラー", array("error_statement" => $mail->ErrorInfo));
            return plugin_movieviewer_action_error_response($page, "メールの送信に失敗しました。{$settings->contact['name']}に問い合わせしてください。");
        }
        $messages = <<<TEXT
        ご登録のアドレスに振込先等のご案内をお送りしています。<br>
        ご確認の上、お振込を期限までに完了してください。<br>
        現在の状況をマイページに戻って、ご確認ください。
TEXT;
    } else {
        if ($purchase_method === "credit") {
            $messages = <<<TEXT
        クレジットカードでの支払いが完了しました。<br>
        現在の状況をマイページに戻って、ご確認ください。<br>
        なおシステムの関係上、入金の確認には、しばらくお時間がかかることがありますので、ご了承ください。
TEXT;
        }
    }
    $hsc = "plugin_movieviewer_hsc";
    $back_uri = plugin_movieviewer_get_home_uri();
    $content = <<<TEXT
    <link href="https://code.jquery.com/ui/1.11.4/themes/redmond/jquery-ui.css" rel="stylesheet">
    <link href="plugin/movieviewer/assets/css/movieviewer.css" rel="stylesheet">
    <h2>受講申し込み完了</h2>
    <p>
    {$messages}
    </p>
    <p>
    <a href="{$back_uri}" class='ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only'>マイページに戻る</a>
    </p>
TEXT;
    return array("msg" => $page, "body" => $content);
}
    function generateMessage($user, $context)
    {
        $settings = plugin_movieviewer_get_global_settings();
        $offer_maker = new MovieViewerDealPackOfferMaker($settings->payment, $user);
        if (!$offer_maker->canOffer()) {
            return '';
        }
        $offer = $offer_maker->getOffer();
        $req_params = "&deal_pack_id={$offer->getPackId()}";
        $start_uri_bank = plugin_movieviewer_get_script_uri() . "?{$context['start_page_bank']}&purchase_method=bank{$req_params}";
        $start_uri_credit = plugin_movieviewer_get_script_uri() . "?{$context['start_page_credit']}&purchase_method=credit{$req_params}";
        $hsc = "plugin_movieviewer_hsc";
        $bank_names_with_notes = nl2br($offer->getPaymentGuide()->bank_transfer->bank_names_with_notes);
        $price_with_notes = plugin_movieviewer_render_dealpack_offer_price($offer);
        if ($settings->payment->isCreditEnabled()) {
            $acceptable_brands = "";
            foreach ($offer->getPaymentGuide()->credit_card->acceptable_brands as $brand) {
                $file_name = "logo_" . strtolower($brand) . ".gif";
                $acceptable_brand = <<<TEXT
                <img src="img/{$file_name}" ALT="{$brand}">
TEXT;
                $acceptable_brands .= $acceptable_brand;
            }
            $money_transfer_info = <<<TEXT
            <tr><th rowspan=2>振込先</th><th width=45%>利用可能な銀行</th><th width=45%>利用可能なクレジットカード</th></tr>
            <tr>
            <td>{$bank_names_with_notes}</td>
            <td style='vertical-align:top;'>{$acceptable_brands}</td>
            </tr>
TEXT;
        } else {
            $money_transfer_info = <<<TEXT
            <tr><th>振込先</th><td colspan=2>{$bank_names_with_notes}</td></tr>
TEXT;
        }
        $bank_transfer_info = <<<TEXT
        <p>
        <table class="movieviewer-payment-guide">
        <tr><th>項目</th><td colspan=2>{$hsc($offer->describePack())}</td></tr>
        <tr><th>金額</th><td colspan=2>{$price_with_notes}</td></tr>
        {$money_transfer_info}
        <tr><th>振込期限</th><td colspan=2>{$hsc($offer->getPaymentGuide()->deadline->format("Y年m月d日"))}まで</td></tr>
        </table>
        </p>
TEXT;
        $buttons_payment = <<<TEXT
        <a href="{$start_uri_bank}" class='ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only'>銀行振り込みで申し込み</a>
TEXT;
        if ($settings->payment->isCreditEnabled()) {
            $buttons_payment .= <<<TEXT
            <a href="{$start_uri_credit}" class='ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only'>クレジットカードで申し込み</a>
TEXT;
        }
        if ($offer->canDiscount()) {
            $discount_period = $offer->getDiscountPeriod();
            if ($offer->isFirstPurchase()) {
                $discount_message = "新規特別割引は{$hsc($discount_period->date_end->format('m月d日'))}までになります。この機会にぜひお申し込みください。";
            } else {
                $discount_message = "お得な継続割引は{$hsc($discount_period->date_end->format('m月d日'))}までになります。この機会にぜひ継続ください。";
            }
            $offer_message = <<<TEXT
            <p>
            <h3 id='content_1_1'>{$hsc($offer->describePack())}の受講申し込みができるようになりました。<a class='anchor' id='p77e7264' name='p77e7264'></a></h3>
            </p>
            {$bank_transfer_info}
            <p>
            {$discount_message}
            </p>
            <p>
            {$buttons_payment}
            </p>
TEXT;
        } else {
            $offer_message = <<<TEXT
            <p>
            <h3 id='content_1_1'>{$hsc($offer->describePack())}の受講申し込みができます。<a class='anchor' id='p77e7264' name='p77e7264'></a></h3>
            </p>
            {$bank_transfer_info}
            <p>
            {$buttons_payment}
            </p>
TEXT;
        }
        $content = <<<TEXT
        <div class="movieviewer-notice movieviewer-notice-purchase-offer">
        {$offer_message}
        </div>
TEXT;
        return $content;
    }
 function testGetOffersShouldReturnNextCourseOfferWhenFirstPackEndedBothRoutes()
 {
     $date_freeze = new DateTime("2015-10-15 00:00:00+09:00");
     timecop_freeze($date_freeze->getTimestamp());
     $user = new MovieViewerUser();
     $user->id = "*****@*****.**";
     $user->selected_routes = array(new MovieViewerCourseRoute(array("K1Kiso", "OABunka")), new MovieViewerCourseRoute(array("K2Kiso")));
     $settings = plugin_movieviewer_get_global_settings();
     $maker = new MovieViewerDealPackOfferMaker($settings->payment, $user);
     $offers = $maker->getOffers();
     $this->assertCount(1, $offers);
     $this->assertEquals("OABunka-1", $offers[0]->getPackId());
 }
function plugin_movieviewer_now()
{
    $settings = plugin_movieviewer_get_global_settings();
    return new DateTime(null, $settings->timezone);
}
/**
 * [アクション] パスワードリセットのお知らせメールを送り、結果画面を生成する
 *
 * @return array ページ名, 画面(html)
 */
function plugin_movieviewer_reset_password_action_request()
{
    $page = plugin_movieviewer_get_current_page();
    try {
        plugin_movieviewer_validate_csrf_token();
    } catch (MovieViewerValidationException $ex) {
        return plugin_movieviewer_reset_password_error("不正なリクエストです。");
    }
    $user_id = filter_input(INPUT_POST, 'movieviewer_user');
    try {
        $user = plugin_movieviewer_get_user_repository()->findById($user_id);
    } catch (MovieViewerRepositoryObjectNotFoundException $ex) {
        return plugin_movieviewer_reset_password_error("ユーザ {$user_id} は登録されていません。");
    }
    if ($user->mailAddress === null || $user->mailAddress === '') {
        return plugin_movieviewer_reset_password_error("ユーザ {$user_id} のメールアドレスが登録されていません。");
    }
    $token = $user->generateResetPasswordToken();
    try {
        plugin_movieviewer_get_user_reset_password_token_repository()->store($token);
    } catch (MovieViewerRepositoryObjectCantStoreException $ex) {
        return plugin_movieviewer_reset_password_error("処理に失敗しました。");
    }
    $settings = plugin_movieviewer_get_global_settings();
    $builder = new MovieViewerResetPasswordMailBuilder($settings->mail);
    $reset_uri = plugin_movieviewer_get_script_uri() . "?cmd=movieviewer_reset_password&page={$page}&ope_type=confirm&token=" . $token->id;
    $mail = $builder->build($user->mailAddress, $reset_uri);
    $result = $mail->send();
    $hsc = "plugin_movieviewer_hsc";
    $message = <<<TEXT
    ユーザ {$hsc($user_id)} のメールアドレスにパスワード再設定手続きのお知らせを送りました。<br>
    <br>
    有効期限は1時間です。ご注意ください。<br>
    有効期限を過ぎた場合は、あらためてパスワード再設定のお手続きをお願いします。<br>
TEXT;
    return array("msg" => $page, "body" => $message);
}