レポジトリ種類: Mercurial

<?php
namespace Site\Controller;

use Site\Controller\BlogPost;
use Site\Controller\Mods;
use Site\Lib\Markdown;

class Atom extends BlogPost {
  use Mods;

  private string $domain = 'technicalsuwako.moe';

  /**
   * 最新の5記事のAtomフィードを生成する
   * 
   * @param array $params パラメータ配列
   * @return void
   */
  public function feed(array $params): void {
    try {
      // 最新の投稿を取得
      $posts = $this->getPosts();
      // 最新の5件に制限
      $posts = array_slice($posts, 0, 5);
      
      // サイトのドメインを取得
      $domain = $_SERVER['HTTP_HOST'];
      $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ?
        'https' : 'http';
      $baseUrl = $protocol.'://'.$domain;
      
      // 現在の日時(RFC3339形式)
      $published = date('c');
      
      // XMLヘッダーとコンテンツタイプを設定
      header('Content-Type: application/atom+xml; charset=utf-8');
      
      // Atomフィードの開始部分
      echo '<?xml version="1.0" encoding="utf-8"?>'."\n";
      echo '<feed xmlns="http://www.w3.org/2005/Atom">'."\n";
      
      // フィードの基本情報
      echo '  <title>'.SITEINFO['title'].'</title>'."\n";
      echo '  <link href="'.$baseUrl.'" />'."\n";
      echo '  <link href="'.$baseUrl.'/blog.atom" rel="self" />'."\n";
      echo '  <id>' . $baseUrl.'/</id>'."\n";
      echo '  <published>'.$published.'</published>'."\n";
      echo '  <author>'."\n";
      echo '    <name>'.SITEINFO['title'].'</name>'."\n";
      echo '  </author>'."\n";
      
      // 各エントリー(記事)
      foreach ($posts as $post) {
        // 記事の本文を取得(プレーンテキスト)
        $path = ROOT.'/blog/'.$post['slug'].'.md';
        $content = '';
        $postPublished = date('c', strtotime($post['date']));
        
        if (file_exists($path)) {
          $fileContent = file_get_contents($path);
          $parts = explode('----', $fileContent, 2);
          if (count($parts) > 1) {
            // 本文をHTMLとして準備
            $md = new Markdown($post['slug']);
            $content = $md->parse();
            // HTMLタグを取り除かないようにCDATAで囲む
            $content = '<![CDATA[' . $content . ']]>';
          }
        }
        
        echo '  <entry>'."\n";
        echo '    <title>'.htmlspecialchars($post['title']).'</title>'."\n";
        echo '    <link href="'.$baseUrl.'/blog/'.$post['slug'].'" />'."\n";
        echo '    <id>'.$baseUrl.'/blog/'.$post['slug'].'</id>'."\n";
        echo '    <published>'.$postPublished.'</published>'."\n";
        
        // カテゴリ(タグ)
        if (isset($post['category']) && is_array($post['category'])) {
          foreach ($post['category'] as $category) {
            echo '    <category term="'.htmlspecialchars($category).'" />'."\n";
          }
        }
        
        // 本文(要約または全文)
        echo '    <content type="html">'.$content.'</content>'."\n";
        echo '  </entry>'."\n";
      }
      
      // フィードの終了
      echo '</feed>';
      exit;
    } catch (\Exception $e) {
      header('Content-Type: text/plain; charset=utf-8');
      echo 'フィードの作成に失敗: '.$e->getMessage();
      exit;
    }
  }
}