SharePoint2007で発行ページを最大限に活用する(3)〜新規ページ作成〜

 ドキュメントライブラリでもページを配置できるようになったとして、やはり新規にページを作成する際も便利に使いたいものだ。デフォではドキュメントライブラリの新規ボタンでページを選択しても、デフォルトでは「Pages」固定であるためにページライブラリにできてしまう。できれば今いるドキュメントライブラリのフォルダ階層にページを作成したいところである。

どうやってやるのか当時は思案していたが、結局似たようなことをやっている先人の方にお世話になりました。但し、この方のやり方だとWebサイトにある大方のドキュメントライブラリ内にある全フォルダをサーチしてリスト化し、ドロップダウンから選択させる方法であるため、新規ページを作る時点で多少の時間がかかるし、エンドユーザーがたくさんのリストの中から選択するので手間である。そこで私の方で一手間かけ、もっと便利に「現在のドキュメントライブラリのカレントディレクトリにページを作成」するようカスタムしたものを以下に紹介する。
Why should 'one' always save publishing pages in "Pages" list in MOSS !!! Bend It !!!!
How to Customize (Add, Delete or Replace ) the "Site Action" menu items in Publishing site

なお、デフォルトだと、サーバーサイドスクリプト(<script runat="server"/>で記述)はセキュリティの観点からプロジェクトサイトでは動作できないようになっている。これはシェアポイントハイブ内にaspxファイルを配置&iisresetなどをする必要がある(システム管理者との協議・調整が必要)。

==============
[手順]
(前提)SharePointサイトが以下の条件を満たしていることを確認。
 ・サイトコレクションの機能
   「Office SharePoint Server 発行インフラストラクチャ」がアクティブ
 ・サイトの機能
   「Office SharePoint Server 発行機能」がアクティブ
 ・ドキュメントライブラリ
   ページを配置したいドキュメントライブラリに、発行ページに必要な「コンテンツタイプ」と「列」が定義されていること
   (全部を手動でやるのはキツいので、一度ページライブラリでダミーの発行ページを作成し、これをWindowsエクスプローラを使って対象のドキュメントライブラリへコピーすれば、そのときに自動で作成される)
   「新規ボタンの順序と規定のコンテンツタイプ」でページをライブラリから作成できるボタンが押せるようになっていること

(1)CustomCreatePage.aspxの作成
 シェアポイントハイブ(大抵は"C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\")に行き、「CreatePage.aspx」をコピーして、「CustomCreatePage.aspx」ファイルを同ディレクトリに作成する。
 ここからいくつかの変更を行っていく。

 ・OnLoad関数の追加(25行目あたりの<script runat="server">の直後)
  ここでCustomCreatePage.aspxが呼ばれたときに付加されているクエリ文字列を取得します。RootFolderを取得することで、どこのドキュメントライブラリのどのフォルダから「新規ページ作成」アクションが呼ばれたかがわかります。なお、このaspxが呼ばれた時点で(ドキュメントライブラリではなく)既にページライブラリを指していますので、「SPList list = SPContext.Current.List;」を使うのは無意味です。また、参考までに現在のリストライブラリを取得する方法は「string listID = (string)Request.QueryString["List"]; SPList list = SPContext.Current.Web.Lists[new Guid(listID)];」となります。

     // mizop customize
     protected override void OnLoad(EventArgs e)
     {
          base.OnLoad(e);

          // クエリ文字列から"RootFolder"を取得し、アイテムとして追加 --> これがページ作成先のディレクトリとなる
          string rootFolder = (string)Request.QueryString["RootFolder"];
          ddlDocLib.Items.Add(new ListItem(rootFolder, rootFolder));
     }

 ・OnCustomSubmit関数のオーバーライド
  ページ作成ボタンを押した時に呼ばれる関数です。ページをカレントディレクトリに作成し、リダイレクトするよう変更しています。

    protected void OnCustomSubmit(Object sender, EventArgs e)
    {
         //Response.Write("In the same way it should work for other page");
         string newPageUrl = "";
         SPWeb web = SPContext.Current.Web;
         PublishingWeb publishingWeb = PublishingWeb.GetPublishingWeb(web);
         PageLayout[] layouts = publishingWeb.GetAvailablePageLayouts();
         
         int layoutItemId = Convert.ToInt32(pageTemplatePicker.SelectedValue);
         
         //SPListItem itemById = publishingWeb.Web.Site.RootWeb.GetCatalog(SPListTemplateType.MasterPageCatalog).Items.GetItemById(layoutItemId);

         PageLayout layout = FindLayoutById(layoutItemId,publishingWeb);

        // = layouts[itemById];

         string pageName = urlNameTextBox.Text + ".aspx";
         
       //  PublishingPage newPage = publishingWeb.GetPublishingPages().Add(ddlDocLib.SelectedItem + "/" + pageName, layout);
         PublishingPage newPage = publishingWeb.GetPublishingPages().Add(ddlDocLib.SelectedItem.Value + "/" + pageName, layout);
         newPageUrl = web.Url + "/" + newPage.Url;
         
         newPage.Title = titleTextBox.Text;

         newPage.Description = descriptionTextBox.Text;

         newPage.Update();
         Response.Redirect(newPageUrl);
    }

 ・FindLayoutById関数の追加
  クリックイベントで使われるメソッドです。これも追加してください。

    protected PageLayout FindLayoutById(int layoutItemId, PublishingWeb localPublishingweb)
    {
         SPListItem itemById = localPublishingweb.Web.Site.RootWeb.GetCatalog(SPListTemplateType.MasterPageCatalog).Items.GetItemById(layoutItemId);
         if (itemById == null)
         {
             return null;
         }
         return new PageLayout(itemById);
    }

 ・<asp:Label ID="parentUrlLabel" runat="server" />ラベルを探し、Visibleパラメータを"false"に変更します。ここは"Pages"リストがハードコーディングされているラベルです。背後のクラスがプログラム内で参照しているので、このラベルは削除してはいけません(エラーとなるでしょう)。

<asp:Label ID="parentUrlLabel" runat="server" Visible="false" />

 ・上記"parentUrlLabel"ラベルの直後に以下を追加してください。これを追加することでドロップダウンリストを表示できます。

<asp:DropDownList ID="ddlDocLib" runat="server"></asp:DropDownList>

 ・最後に最下行あたりにある、カスタムイベント用の発行ページ作成ボタンServerclickプロパティを変更します。

<asp:Button runat="server" class="ms-ButtonHeightWidth" OnClick="OnCustomSubmit" Text="<%$Resources:cms, createpage_createbutton%>" id="buttonCreatePage" AccessKey="<%$Resources:cms,createbutton_accesskey%>"/>

(2)iisreset
 ・システム担当者に「iisreset」コマンドを実行してもらい、Webサーバ、SharePointサーバの再起動をかけてもらう。
  (これ以降、CustomCreatePage.aspxを変更した後、反映する度に再起動が必要となる)

(3)ページ作成時のテンプレート設定(各ドキュメントライブラリごと)
 ドキュメントライブラリの設定>リストコンテンツタイプ>ページ>詳細設定と辿り、「既存のドキュメントテンプレートのURLを入力する」欄を以下のように変更する。

/_layouts/CustomCreatePage.aspx

(4)本当はCustomSiteAction.xmlの編集も必要とのことだったが、(3)をやれば必要ないみたい(CustomSiteAction.xmlは何も変更せずに新規ページがちゃんとカレントディレクトリに作成できている)。