From 42bcff9d1714cb4d1ee870eb1e830379919804a1 Mon Sep 17 00:00:00 2001
From: goto
Date: Wed, 28 Aug 2013 16:16:39 +0900
Subject: [PATCH 1/2] =?UTF-8?q?=E3=82=B9=E3=83=9E=E3=83=9B=E5=AF=BE?=
=?UTF-8?q?=E5=BF=9C=20IE=E4=BB=A5=E5=A4=96=E3=81=A7=E3=83=81=E3=83=A3?=
=?UTF-8?q?=E3=83=B3=E3=83=8D=E3=83=AB=E7=B7=A8=E9=9B=86=E3=83=AA=E3=83=B3?=
=?UTF-8?q?=E3=82=AF=E3=82=92=E3=82=AF=E3=83=AA=E3=83=83=E3=82=AF=E3=81=97?=
=?UTF-8?q?=E3=81=9F=E9=9A=9B=E3=81=AB=E3=80=81=E3=83=96=E3=83=AD=E3=83=83?=
=?UTF-8?q?=E3=82=AF=E3=81=8C=E8=A1=A8=E7=A4=BA=E3=81=95=E3=82=8C=E3=81=AA?=
=?UTF-8?q?=E3=81=8F=E3=81=AA=E3=82=8B=E3=83=90=E3=82=B0=E3=82=92=E4=BF=AE?=
=?UTF-8?q?=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
multimedia/CHANGES.txt | 7 +
.../action/main/album/delete/Delete.class.php | 74 +-
.../action/main/album/entry/Entry.class.php | 134 +-
.../action/main/album/jacket/Jacket.class.php | 40 +-
.../main/comment/delete/Delete.class.php | 80 +-
.../action/main/comment/entry/Entry.class.php | 114 +-
.../action/main/item/delete/Delete.class.php | 72 +-
.../action/main/item/edit/Edit.class.php | 132 +-
.../action/main/item/play/Play.class.php | 149 +-
multimedia/action/main/item/play/maple.ini | 2 +-
.../main/item/sequence/Sequence.class.php | 152 +-
.../action/main/item/upload/Upload.class.php | 54 +-
.../action/main/item/vote/Vote.class.php | 140 +-
multimedia/components/Action.class.php | 1204 ++++----
multimedia/components/View.class.php | 1930 ++++++------
multimedia/config/main.ini | 10 +-
multimedia/files/css/default/style.css | 535 +++-
multimedia/files/images/Jplayer.swf | Bin 0 -> 13674 bytes
.../images/jplayer/jplayer.blue.monday.jpg | Bin 0 -> 23189 bytes
.../jplayer/jplayer.blue.monday.seeking.gif | Bin 0 -> 3284 bytes
.../jplayer.blue.monday.video.play.png | Bin 0 -> 17692 bytes
.../images/jplayer/jplayer.netcommons.jpg | Bin 0 -> 6900 bytes
.../jplayer/jplayer.netcommons.video.play.png | Bin 0 -> 1718 bytes
multimedia/files/images/jquery-1.7.1.min.js | 4 +
multimedia/files/images/jquery-1.8.3.min.js | 2 +
multimedia/files/images/jquery.jplayer.js | 2663 +++++++++++++++++
multimedia/files/js/default/multimedia.js | 898 +++---
multimedia/language/english/main.ini | 10 +-
multimedia/language/japanese/main.ini | 10 +-
.../default/multimedia_player_list.xml | 2 +-
.../default/multimedia_view_main_channel.html | 6 +-
.../multimedia_view_main_item_detail.html | 13 +-
.../multimedia_view_main_item_detail.html.bak | 195 ++
.../multimedia_view_main_item_iframe.html | 2 +
.../default/multimedia_view_main_list.html | 3 +
.../default/multimedia_view_main_play.html | 77 +
.../multimedia_view_main_toolbar.html.bk | 122 +
.../templates/multimedia_jquery_script.html | 26 +
.../validator/Validator_AlbumExist.class.php | 90 +-
.../Validator_CommentExist.class.php | 84 +-
.../validator/Validator_ItemExist.class.php | 90 +-
.../validator/Validator_ItemUpload.class.php | 382 ++-
.../Validator_ItemUpload.class.php.org | 191 ++
.../Validator_MultimediaCount.class.php | 90 +-
.../Validator_MultimediaExist.class.php | 144 +-
.../Validator_MultimediaView.class.php | 118 +-
.../Validator_MultimediaXml.class.php | 104 +-
multimedia/view/edit/entry/Entry.class.php | 6 -
.../view/main/album/entry/Entry.class.php | 122 +-
.../view/main/album/jacket/Jacket.class.php | 112 +-
.../view/main/channel/Channel.class.php | 160 +-
.../view/main/comment/Comment.class.php | 108 +-
multimedia/view/main/init/Init.class.php | 73 +-
.../view/main/item/detail/Detail.class.php | 181 +-
multimedia/view/main/item/edit/Edit.class.php | 100 +-
.../view/main/item/iframe/Iframe.class.php | 309 ++
multimedia/view/main/item/iframe/maple.ini | 19 +
multimedia/view/main/item/init/Init.class.php | 194 +-
.../main/item/thumbnail/Thumbnail.class.php | 74 +-
.../view/main/item/upload/Upload.class.php | 102 +-
multimedia/view/main/list/List.class.php | 326 +-
multimedia/view/main/xml/Xml.class.php | 84 +-
62 files changed, 8299 insertions(+), 3826 deletions(-)
create mode 100644 multimedia/files/images/Jplayer.swf
create mode 100644 multimedia/files/images/jplayer/jplayer.blue.monday.jpg
create mode 100644 multimedia/files/images/jplayer/jplayer.blue.monday.seeking.gif
create mode 100644 multimedia/files/images/jplayer/jplayer.blue.monday.video.play.png
create mode 100644 multimedia/files/images/jplayer/jplayer.netcommons.jpg
create mode 100644 multimedia/files/images/jplayer/jplayer.netcommons.video.play.png
create mode 100644 multimedia/files/images/jquery-1.7.1.min.js
create mode 100644 multimedia/files/images/jquery-1.8.3.min.js
create mode 100644 multimedia/files/images/jquery.jplayer.js
create mode 100644 multimedia/templates/default/multimedia_view_main_item_detail.html.bak
create mode 100644 multimedia/templates/default/multimedia_view_main_item_iframe.html
create mode 100644 multimedia/templates/default/multimedia_view_main_play.html
create mode 100644 multimedia/templates/default/multimedia_view_main_toolbar.html.bk
create mode 100644 multimedia/templates/multimedia_jquery_script.html
create mode 100644 multimedia/validator/Validator_ItemUpload.class.php.org
create mode 100644 multimedia/view/main/item/iframe/Iframe.class.php
create mode 100644 multimedia/view/main/item/iframe/maple.ini
diff --git a/multimedia/CHANGES.txt b/multimedia/CHANGES.txt
index 29bd2c4..cb5bc9d 100644
--- a/multimedia/CHANGES.txt
+++ b/multimedia/CHANGES.txt
@@ -1,6 +1,13 @@
NetComomns2-multimedia Changelog
===============================
+/* FIXME */
+2013/08/28: Version 2.4.0.1
+===============================
+- スマホ対応(Android、iOS)
+- IE以外で、一覧表示の状態でチャンネル編集リンクをクリックした際にブロックが表示されなくなるバグを修正
+
+
2013/05/20: Version 2.4.0.1
===============================
- ルームのリストア時にタグデータの重複エラーが発生することがあるバグを修正
diff --git a/multimedia/action/main/album/delete/Delete.class.php b/multimedia/action/main/album/delete/Delete.class.php
index ca3f34b..a2f98a2 100644
--- a/multimedia/action/main/album/delete/Delete.class.php
+++ b/multimedia/action/main/album/delete/Delete.class.php
@@ -1,37 +1,37 @@
-multimediaAction->deleteAlbum($this->album['multimedia_id'], $this->album['album_id'])) {
- return 'error';
- }
-
- return 'success';
- }
-}
-?>
+multimediaAction->deleteAlbum($this->album['multimedia_id'], $this->album['album_id'])) {
+ return 'error';
+ }
+
+ return 'success';
+ }
+}
+?>
diff --git a/multimedia/action/main/album/entry/Entry.class.php b/multimedia/action/main/album/entry/Entry.class.php
index f79b2fd..9f2075a 100644
--- a/multimedia/action/main/album/entry/Entry.class.php
+++ b/multimedia/action/main/album/entry/Entry.class.php
@@ -1,67 +1,67 @@
-upload_id)) {
- $imageSize = $this->multimediaView->getImageSize($this->album_jacket);
- } else {
- $imageSize = $this->multimediaView->getImageSize($this->upload_id);
- }
-
- $params = array(
- "album_name" => $this->album_name,
- "upload_id" => $this->upload_id,
- "album_jacket" => $this->album_jacket,
- "width" => $imageSize[0],
- "height" => $imageSize[1],
- "album_description" => $this->album_description,
- "public_flag" => intval($this->public_flag)
- );
-
- if (empty($this->album_id)) {
- $params["multimedia_id"] = $this->multimedia_id;
- $albumSequence = $this->db->maxExecute("multimedia_album", "album_sequence", array("multimedia_id" => $this->multimedia_id));
- $params["album_sequence"] = $albumSequence + 1;
- $result = $this->db->insertExecute("multimedia_album", $params, true, "album_id");
- } else {
- $result = $this->db->updateExecute("multimedia_album", $params, array("album_id" => $this->album_id), true);
- }
- if ($result === false) {
- return 'error';
- }
-
- return 'success';
- }
-}
-?>
+upload_id)) {
+ $imageSize = $this->multimediaView->getImageSize($this->album_jacket);
+ } else {
+ $imageSize = $this->multimediaView->getImageSize($this->upload_id);
+ }
+
+ $params = array(
+ "album_name" => $this->album_name,
+ "upload_id" => $this->upload_id,
+ "album_jacket" => $this->album_jacket,
+ "width" => $imageSize[0],
+ "height" => $imageSize[1],
+ "album_description" => $this->album_description,
+ "public_flag" => intval($this->public_flag)
+ );
+
+ if (empty($this->album_id)) {
+ $params["multimedia_id"] = $this->multimedia_id;
+ $albumSequence = $this->db->maxExecute("multimedia_album", "album_sequence", array("multimedia_id" => $this->multimedia_id));
+ $params["album_sequence"] = $albumSequence + 1;
+ $result = $this->db->insertExecute("multimedia_album", $params, true, "album_id");
+ } else {
+ $result = $this->db->updateExecute("multimedia_album", $params, array("album_id" => $this->album_id), true);
+ }
+ if ($result === false) {
+ return 'error';
+ }
+
+ return 'success';
+ }
+}
+?>
diff --git a/multimedia/action/main/album/jacket/Jacket.class.php b/multimedia/action/main/album/jacket/Jacket.class.php
index 04f2c4c..57d685f 100644
--- a/multimedia/action/main/album/jacket/Jacket.class.php
+++ b/multimedia/action/main/album/jacket/Jacket.class.php
@@ -1,21 +1,21 @@
-uploadsAction->uploads();
- $this->session->setParameter("multimedia_jacket_upload_id", $files[0]["upload_id"]);
-
- return true;
- }
-}
+uploadsAction->uploads();
+ $this->session->setParameter("multimedia_jacket_upload_id", $files[0]["upload_id"]);
+
+ return true;
+ }
+}
?>
\ No newline at end of file
diff --git a/multimedia/action/main/comment/delete/Delete.class.php b/multimedia/action/main/comment/delete/Delete.class.php
index bd6b707..8251dfd 100644
--- a/multimedia/action/main/comment/delete/Delete.class.php
+++ b/multimedia/action/main/comment/delete/Delete.class.php
@@ -1,40 +1,40 @@
- $this->comment_id
- );
- if (!$this->db->deleteExecute("multimedia_comment", $params)) {
- return 'error';
- }
-
- return 'success';
- }
-}
-?>
+ $this->comment_id
+ );
+ if (!$this->db->deleteExecute("multimedia_comment", $params)) {
+ return 'error';
+ }
+
+ return 'success';
+ }
+}
+?>
diff --git a/multimedia/action/main/comment/entry/Entry.class.php b/multimedia/action/main/comment/entry/Entry.class.php
index ff81422..04487db 100644
--- a/multimedia/action/main/comment/entry/Entry.class.php
+++ b/multimedia/action/main/comment/entry/Entry.class.php
@@ -1,57 +1,57 @@
-comment_id)) {
- $params = array(
- "item_id" => $this->item['item_id'],
- "album_id" => $this->album['album_id'],
- "multimedia_id" => $this->album['multimedia_id'],
- "comment_value" => $this->comment_value
- );
- $result = $this->db->insertExecute("multimedia_comment", $params, true, "comment_id");
- } else {
- $params = array(
- "comment_id" => $this->comment_id,
- "comment_value" => $this->comment_value
- );
- $result = $this->db->updateExecute("multimedia_comment", $params, "comment_id", true);
- }
- if (!$result) {
- return 'error';
- }
-
- return 'success';
- }
-}
-?>
+comment_id)) {
+ $params = array(
+ "item_id" => $this->item['item_id'],
+ "album_id" => $this->album['album_id'],
+ "multimedia_id" => $this->album['multimedia_id'],
+ "comment_value" => $this->comment_value
+ );
+ $result = $this->db->insertExecute("multimedia_comment", $params, true, "comment_id");
+ } else {
+ $params = array(
+ "comment_id" => $this->comment_id,
+ "comment_value" => $this->comment_value
+ );
+ $result = $this->db->updateExecute("multimedia_comment", $params, "comment_id", true);
+ }
+ if (!$result) {
+ return 'error';
+ }
+
+ return 'success';
+ }
+}
+?>
diff --git a/multimedia/action/main/item/delete/Delete.class.php b/multimedia/action/main/item/delete/Delete.class.php
index 69f449e..d37f8b0 100644
--- a/multimedia/action/main/item/delete/Delete.class.php
+++ b/multimedia/action/main/item/delete/Delete.class.php
@@ -1,37 +1,37 @@
-multimediaAction->deleteItem($this->item_id)) {
- return 'error';
- }
-
- return 'success';
- }
-}
+multimediaAction->deleteItem($this->item_id)) {
+ return 'error';
+ }
+
+ return 'success';
+ }
+}
?>
\ No newline at end of file
diff --git a/multimedia/action/main/item/edit/Edit.class.php b/multimedia/action/main/item/edit/Edit.class.php
index f9cfbf1..40e3368 100644
--- a/multimedia/action/main/item/edit/Edit.class.php
+++ b/multimedia/action/main/item/edit/Edit.class.php
@@ -1,66 +1,66 @@
- $this->album_id,
- "item_name" => $this->item_name,
- "item_description" => $this->item_description,
- "privacy" => $this->privacy
- );
- $where_params = array(
- "item_id" => $this->item_id
- );
- $result = $this->db->updateExecute("multimedia_item", $params, $where_params, true);
- if ($result === false) {
- return 'error';
- }
-
- if($this->album_id != $this->item['album_id']) {
- if(!$this->multimediaAction->setItemCount($this->album_id, 1)) {
- return 'error';
- }
- if(!$this->multimediaAction->setItemCount($this->item['album_id'], -1)) {
- return 'error';
- }
- }
-
- if(!empty($this->item_tag)) {
- if(!$this->multimediaAction->setItemTag($this->item_id, $this->item_tag)) {
- return 'error';
- }
- }
-
- return 'success';
- }
-}
-?>
+ $this->album_id,
+ "item_name" => $this->item_name,
+ "item_description" => $this->item_description,
+ "privacy" => $this->privacy
+ );
+ $where_params = array(
+ "item_id" => $this->item_id
+ );
+ $result = $this->db->updateExecute("multimedia_item", $params, $where_params, true);
+ if ($result === false) {
+ return 'error';
+ }
+
+ if($this->album_id != $this->item['album_id']) {
+ if(!$this->multimediaAction->setItemCount($this->album_id, 1)) {
+ return 'error';
+ }
+ if(!$this->multimediaAction->setItemCount($this->item['album_id'], -1)) {
+ return 'error';
+ }
+ }
+
+ if(!empty($this->item_tag)) {
+ if(!$this->multimediaAction->setItemTag($this->item_id, $this->item_tag)) {
+ return 'error';
+ }
+ }
+
+ return 'success';
+ }
+}
+?>
diff --git a/multimedia/action/main/item/play/Play.class.php b/multimedia/action/main/item/play/Play.class.php
index 043456c..d164632 100644
--- a/multimedia/action/main/item/play/Play.class.php
+++ b/multimedia/action/main/item/play/Play.class.php
@@ -14,22 +14,21 @@
*/
class Multimedia_Action_Main_Item_Play extends Action
{
- // リクエストパラメータを受け取るため
-
- // バリデートによりセット
- var $item = null;
- var $uploadsView = null;
-
-
- // 値をセットするため
-
- /**
- * [[機能説明]]
- *
- * @access public
- */
- function execute()
- {
+ // 使用コンポーネントを受け取るため
+ var $session = null;
+ var $uploadsView = null;
+ var $db = null;
+
+ // バリデートによりセット
+ var $item = null;
+
+ /**
+ * [[機能説明]]
+ *
+ * @access public
+ */
+ function execute()
+ {
list($pathname,$filename,$physical_file_name, $cache_flag) = $this->uploadsView->downloadCheck($this->item['upload_id'], null);
if (!isset($pathname)) {
exit;
@@ -41,8 +40,120 @@ function execute()
$caching = false;
}
- $this->uploadsView->headerOutput($pathname, $filename, $physical_file_name, $caching);
- exit;
- }
+ //Rangeヘッダが設定されている場合(iOS)
+ if(isset($_SERVER['HTTP_RANGE'])) {
+ //動画ファイルサイズ取得
+ $file = $pathname . $filename;
+ $file_size = filesize($file) - 1; //Rangeヘッダのオフセットが0であるため、-1
+//error_log(print_r($file_size, true)."<-file_size\n\n", 3, LOG_DIR."/error.log");
+
+ //Rangeヘッダを解析
+ list($range_header, $range) = explode('=', $_SERVER['HTTP_RANGE']);
+ list($range_offset, $range_limit) = explode('-', $range);
+//error_log(print_r($_SERVER['HTTP_RANGE'], true)."<-p\n\n", 3, LOG_DIR."/error.log");
+ $playback_session_id_array = array();
+
+ //Rangeヘッダが0からファイル終端の場合(ファイル存在確認後、1度のみリクエストされる)
+ if($range_offset == 0 && $range_limit == $file_size - 1) {
+ //再生回数更新
+ $params = array(
+ $this->item['item_id']
+ );
+ $sql = "UPDATE {multimedia_item} ".
+ "SET item_play_count = item_play_count + 1 ".
+ "WHERE item_id = ? ";
+ $result = $this->db->execute($sql, $params);
+ if ($result === false) {
+ return 'error';
+ }
+ }
+
+ // Rangeヘッダの終了値が省略されている場合はファイルサイズを設定
+ if(is_null($range_limit)) {
+ $range_limit = $file_size;
+ }
+
+ //Rangeヘッダが指定するコンテンツの長さを設定(Rangeヘッダのオフセットが0であるため、+1)
+ $content_length = $range_limit - $range_offset + 1;
+
+ //Rangeヘッダで指定された範囲の動画を取得
+ $content = file_get_contents($file, FILE_BINARY, null, $range_offset, $range_limit);
+
+ //ヘッダ出力
+ @ob_end_clean();
+ header('Content-type: video/mp4');
+ header('Content-Disposition: attachment; filename="' . $filename . '"');
+ header('Content-Transfer-Encoding: binary');
+ header('Accept-Ranges: bytes');
+ header('HTTP/1.1 206 Partial Content');
+ header('Content-Length: ' . $content_length);
+ header('Content-Range: bytes ' . $range_offset . '-' . $range_limit . '/' . $file_size);
+// header("Etag: \"" . md5( $_SERVER["REQUEST_URI"] ) . $file_size . "\"" );
+ header("Last-Modified: " . gmdate( "D, d M Y H:i:s", filemtime($file)) . " GMT");
+
+// 以下、webapp/components/uploads/View.class.php の function _headerOutput より
+ $stats = stat($file);
+ $etag = sprintf( '"%x-%x-%x"', $stats['ino'], $stats['size'], $stats['mtime'] );
+ header('Etag: '.$etag);
+
+ if($caching == true) {
+ // 1Week
+ header("Cache-Control: max-age=604800, public");
+ header('Pragma: cache'); //no-cache以外の文字列をセット
+ $offset = 60 * 60 * 24 * 7; // 1Week
+ header('Expires: '.gmdate('D, d M Y H:i:s', time() + $offset).' GMT');
+ if (isset( $_SERVER['HTTP_IF_NONE_MATCH'] ) &&
+ stripcslashes( $_SERVER['HTTP_IF_NONE_MATCH'] ) == $etag ) {
+ header( 'HTTP/1.1 304 Not Modified' );
+ $status_code = "304";
+ }
+ //} else if (isset($_SERVER['HTTPS']) && stristr($_SERVER['HTTP_USER_AGENT'], "MSIE")) {
+ // // IE + サイト全体SSLの場合、ダウンロードが正常に行われない。
+ // // ダウンロードさせるためには、以下コメントをはずす必要があるが、
+ // // アップロードした画像ファイル等をローカルキャッシュにとられてしまう弊害がある。
+ // // 1Week
+ // header("Cache-Control: max-age=604800, public");
+ // header('Pragma: cache'); //no-cache以外の文字列をセット
+ // $offset = 60 * 60 * 24 * 7; // 1Week
+ // header('Expires: '.gmdate('D, d M Y H:i:s', time() + $offset).' GMT');
+ } else {
+ header("Cache-Control: no-store, no-cache, must-revalidate");
+ header("Pragma: no-cache");
+ }
+// 以上、webapp/components/uploads/View.class.php の function _headerOutput より
+
+//error_log(print_r($filename, true)."<-filename\n\n", 3, LOG_DIR."/error.log");
+//error_log(print_r($file_size, true)."<-file_size\n\n", 3, LOG_DIR."/error.log");
+//error_log(print_r($content_length, true)."<-content_length\n\n", 3, LOG_DIR."/error.log");
+
+ //ファイル出力
+// echo $content;
+ $fp = fopen($file, "rb");
+ fseek($fp, $range_offset, SEEK_SET);
+ echo fread($fp, $content_length);
+ exit;
+ }
+ //Rangeヘッダが設定されていない場合
+ else {
+ //HTTP_USER_AGENTが設定されている場合のみ再生数をカウント(Android Chrome対策)
+ if(isset($_SERVER['HTTP_USER_AGENT'])) {
+ //再生回数更新
+ $params = array(
+ $this->item['item_id']
+ );
+ $sql = "UPDATE {multimedia_item} ".
+ "SET item_play_count = item_play_count + 1 ".
+ "WHERE item_id = ? ";
+ $result = $this->db->execute($sql, $params);
+ if ($result === false) {
+ return 'error';
+ }
+ }
+
+ //動画出力
+ $this->uploadsView->headerOutput($pathname, $filename, $physical_file_name, $caching);
+ exit;
+ }
+ }
}
?>
\ No newline at end of file
diff --git a/multimedia/action/main/item/play/maple.ini b/multimedia/action/main/item/play/maple.ini
index 95258cb..40e7c9d 100644
--- a/multimedia/action/main/item/play/maple.ini
+++ b/multimedia/action/main/item/play/maple.ini
@@ -11,7 +11,7 @@ request = BOTH
upload_id.multimedia.playCheck = "1:lang.multimedia_err_incorrectauth"
[Action]
-actionChain = "ref:ActionChain"
+db = "ref:DbObject"
uploadsView = "ref:uploadsView"
session = "ref:Session"
diff --git a/multimedia/action/main/item/sequence/Sequence.class.php b/multimedia/action/main/item/sequence/Sequence.class.php
index 05b5cb9..3ca3d7a 100644
--- a/multimedia/action/main/item/sequence/Sequence.class.php
+++ b/multimedia/action/main/item/sequence/Sequence.class.php
@@ -1,77 +1,77 @@
-album_id,
- $this->drag_sequence,
- $this->drop_sequence
- );
-
- if ($this->drag_sequence > $this->drop_sequence) {
- $sql = "UPDATE {multimedia_item} ".
- "SET item_sequence = item_sequence + 1 ".
- "WHERE album_id = ? ".
- "AND item_sequence < ? ".
- "AND item_sequence > ?";
- } else {
- $sql = "UPDATE {multimedia_item} ".
- "SET item_sequence = item_sequence - 1 ".
- "WHERE album_id = ? ".
- "AND item_sequence > ? ".
- "AND item_sequence <= ?";
- }
-
- $result = $this->db->execute($sql, $params);
- if($result === false) {
- return 'error';
- }
-
- if ($this->drag_sequence > $this->drop_sequence) {
- $this->drop_sequence++;
- }
- $params = array(
- $this->drop_sequence,
- $this->drag_item_id
- );
-
- $sql = "UPDATE {multimedia_item} ".
- "SET item_sequence = ? ".
- "WHERE item_id = ?";
- $result = $this->db->execute($sql, $params);
- if($result === false) {
- return 'error';
- }
-
- return 'success';
- }
-}
+album_id,
+ $this->drag_sequence,
+ $this->drop_sequence
+ );
+
+ if ($this->drag_sequence > $this->drop_sequence) {
+ $sql = "UPDATE {multimedia_item} ".
+ "SET item_sequence = item_sequence + 1 ".
+ "WHERE album_id = ? ".
+ "AND item_sequence < ? ".
+ "AND item_sequence > ?";
+ } else {
+ $sql = "UPDATE {multimedia_item} ".
+ "SET item_sequence = item_sequence - 1 ".
+ "WHERE album_id = ? ".
+ "AND item_sequence > ? ".
+ "AND item_sequence <= ?";
+ }
+
+ $result = $this->db->execute($sql, $params);
+ if($result === false) {
+ return 'error';
+ }
+
+ if ($this->drag_sequence > $this->drop_sequence) {
+ $this->drop_sequence++;
+ }
+ $params = array(
+ $this->drop_sequence,
+ $this->drag_item_id
+ );
+
+ $sql = "UPDATE {multimedia_item} ".
+ "SET item_sequence = ? ".
+ "WHERE item_id = ?";
+ $result = $this->db->execute($sql, $params);
+ if($result === false) {
+ return 'error';
+ }
+
+ return 'success';
+ }
+}
?>
\ No newline at end of file
diff --git a/multimedia/action/main/item/upload/Upload.class.php b/multimedia/action/main/item/upload/Upload.class.php
index cde0f54..a11cdb3 100644
--- a/multimedia/action/main/item/upload/Upload.class.php
+++ b/multimedia/action/main/item/upload/Upload.class.php
@@ -1,28 +1,28 @@
-
\ No newline at end of file
diff --git a/multimedia/action/main/item/vote/Vote.class.php b/multimedia/action/main/item/vote/Vote.class.php
index 23bdf91..25a7fa6 100644
--- a/multimedia/action/main/item/vote/Vote.class.php
+++ b/multimedia/action/main/item/vote/Vote.class.php
@@ -1,71 +1,71 @@
-session->getParameter("_user_id");
-
- if (empty($user_id)) {
- $votes = $this->session->getParameter("multimedia_votes");
- $votes[] = $this->item_id;
- $session->setParameter("multimedia_votes", $votes);
- } else {
- $params = array(
- "user_id" => $user_id,
- "item_id" => $this->item_id,
- "vote_flag" => _ON
- );
- if (!$this->db->insertExecute("mutlimedia_user_item", $params, true)) {
- return 'error';
- }
- }
-
- $params = array($this->item_id);
- $sql = "UPDATE {multimedia_item} ".
- "SET item_vote_count = item_vote_count + 1 ".
- "WHERE item_id = ?";
- $result = $this->db->execute($sql, $params);
- if ($result === false) {
- return 'error';
- }
-
- $params = array($this->album_id);
- $sql = "UPDATE {multimedia_album} ".
- "SET album_vote_count = album_vote_count + 1 ".
- "WHERE album_id = ?";
- $result = $this->db->execute($sql, $params);
- if ($result === false) {
- return 'error';
- }
-
- return 'success';
- }
-}
+session->getParameter("_user_id");
+
+ if (empty($user_id)) {
+ $votes = $this->session->getParameter("multimedia_votes");
+ $votes[] = $this->item_id;
+ $session->setParameter("multimedia_votes", $votes);
+ } else {
+ $params = array(
+ "user_id" => $user_id,
+ "item_id" => $this->item_id,
+ "vote_flag" => _ON
+ );
+ if (!$this->db->insertExecute("mutlimedia_user_item", $params, true)) {
+ return 'error';
+ }
+ }
+
+ $params = array($this->item_id);
+ $sql = "UPDATE {multimedia_item} ".
+ "SET item_vote_count = item_vote_count + 1 ".
+ "WHERE item_id = ?";
+ $result = $this->db->execute($sql, $params);
+ if ($result === false) {
+ return 'error';
+ }
+
+ $params = array($this->album_id);
+ $sql = "UPDATE {multimedia_album} ".
+ "SET album_vote_count = album_vote_count + 1 ".
+ "WHERE album_id = ?";
+ $result = $this->db->execute($sql, $params);
+ if ($result === false) {
+ return 'error';
+ }
+
+ return 'success';
+ }
+}
?>
\ No newline at end of file
diff --git a/multimedia/components/Action.class.php b/multimedia/components/Action.class.php
index 165e255..4b5716a 100644
--- a/multimedia/components/Action.class.php
+++ b/multimedia/components/Action.class.php
@@ -1,575 +1,631 @@
-_db =& $container->getComponent("DbObject");
- $this->_request =& $container->getComponent("Request");
- }
-
- function hasFfmpegLib() {
- $extension_fullname = PHP_EXTENSION_DIR . "/" . MULTIMEDIA_EXTENSION.".".PHP_SHLIB_SUFFIX;
- if (!extension_loaded(MULTIMEDIA_EXTENSION)) {
- //dl($extension_soname) or die("Can't load extension $extension_fullname\n");
- return false;
- }
- return true;
- }
-
- function deleteMultimedia() {
- $params = array(
- "multimedia_id" => $this->_request->getParameter("multimedia_id")
- );
-
- if (!$this->_db->deleteExecute("multimedia_block", $params)) {
- return false;
- }
-
- if (!$this->_db->deleteExecute("multimedia_comment", $params)) {
- return false;
- }
-
- $sql = "SELECT item_id, upload_id, file_path ".
- "FROM {multimedia_item} ".
- "WHERE multimedia_id = ?";
- $items = $this->_db->execute($sql, $params);
- if ($items === false) {
- $this->_db->addError();
- return false;
- }
- if (!$this->deleteItemFile($items)) {
- return false;
- }
- if (!$this->_db->deleteExecute("multimedia_item", $params)) {
- return false;
- }
- if (!$this->_db->deleteExecute("multimedia_album", $params)) {
- return false;
- }
- if (!$this->_db->deleteExecute("multimedia", $params)) {
- return false;
- }
-
- return true;
- }
-
- //動画ファイル削除
- function deleteItemFile($items)
- {
- if (empty($items)) {
- return true;
- }
-
- $container =& DIContainerFactory::getContainer();
- $commonMain =& $container->getComponent("commonMain");
- $uploads =& $commonMain->registerClass(WEBAPP_DIR.'/components/uploads/Action.class.php', "Uploads_Action", "uploadsAction");
- $item_ids = array();
- foreach ($items as $item) {
- if (!$uploads->delUploadsById($item['upload_id'])) {
- return false;
- }
- //動画のサムネイル画像があれば、削除
- $thumbnail_path = FILEUPLOADS_DIR.$item['file_path'].$item['upload_id']."_thumbnail.jpg";
- if(file_exists($thumbnail_path)) {
- @chmod($thumbnail_path, 0777);
- unlink($thumbnail_path);
- }
- //タグ削除
- $sql = "SELECT tag_id "
- . "FROM {multimedia_item_tag} "
- . "WHERE item_id = ?;";
- $params = array(
- "item_id" => $item['item_id']
- );
- $tag_id_string = $this->_db->execute($sql, $params, $limit = null, $offset = null, false, array($this, "_makeImplodeString"));
- if ($tag_id_string === false) {
- $this->_db->addError();
- return false;
- }
- if (!empty($tag_id_string)) {
- if(!$this->_db->deleteExecute("multimedia_item_tag", $params)) {
- return false;
- }
- }
- $this->_tagReCount($tag_id_string);
-
- if (!$this->_db->deleteExecute("multimedia_item_tag", $params)) {
- return false;
- }
- }
-
- return true;
- }
-
- //カテゴリ削除
- function deleteAlbum($multimedia_id, $album_id) {
- $params = array(
- "album_id" => $album_id
- );
-
- if (!$this->_db->deleteExecute("multimedia_comment", $params)) {
- return false;
- }
-
- $sql = "SELECT item_id, upload_id, file_path ".
- "FROM {multimedia_item} ".
- "WHERE album_id = ?";
- $items = $this->_db->execute($sql, $params);
- if ($items === false) {
- $this->_db->addError();
- return false;
- }
- if (!$this->deleteItemFile($items)) {
- return false;
- }
- if (!$this->_db->deleteExecute("multimedia_item", $params)) {
- return false;
- }
-
- $sql = "SELECT album_sequence, upload_id ".
- "FROM {multimedia_album} ".
- "WHERE album_id = ?";
- $albums = $this->_db->execute($sql, $params);
- if ($albums === false) {
- $this->_db->addError();
- return false;
- }
-
- if (!$this->_db->deleteExecute("multimedia_album", $params)) {
- return false;
- }
-
- if(!empty($albums[0]['upload_id'])) {
- $container =& DIContainerFactory::getContainer();
- $commonMain =& $container->getComponent("commonMain");
- $uploads =& $commonMain->registerClass(WEBAPP_DIR.'/components/uploads/Action.class.php', "Uploads_Action", "uploadsAction");
- if (!$uploads->delUploadsById($albums[0]['upload_id'])) {
- return false;
- }
- }
-
- $params = array(
- "multimedia_id" => $multimedia_id
- );
- $sequenceParam = array(
- "album_sequence" => $albums[0]['album_sequence']
- );
- if (!$this->_db->seqExecute("multimedia_album", $params, $sequenceParam)) {
- return false;
- }
-
- return true;
- }
-
- //動画削除
- function deleteItem($item_id) {
- $params = array(
- "item_id" => $item_id
- );
-
- //コメント削除
- if (!$this->_db->deleteExecute("multimedia_comment", $params)) {
- return false;
- }
-
- //動画削除
- $sql = "SELECT item_id, album_id, upload_id, file_path ".
- "FROM {multimedia_item} ".
- "WHERE item_id = ?";
- $item = $this->_db->execute($sql, $params);
- if ($item === false) {
- $this->_db->addError();
- return false;
- }
- if (!$this->deleteItemFile($item)) {
- return false;
- }
- if (!$this->_db->deleteExecute("multimedia_item", $params)) {
- return false;
- }
-
- if(!$this->setItemCount($item[0]['album_id'], -1)) {
- return false;
- }
-
- return true;
- }
-
- //アルバムの動画件数を計算
- function setItemCount($album_id, $count) {
- if(empty($album_id)) {
- return false;
- }
-
- $params = array(
- "album_id" => $album_id
- );
-
- $album = $this->_db->selectExecute("multimedia_album", $params);
- if(empty($album) || !isset($album[0])) {
- return false;
- }
-
- $sql = "UPDATE {multimedia_album} ".
- "SET item_count = item_count + ".($count)." ".
- "WHERE album_id = ?";
- $result = $this->_db->execute($sql, $params);
- if ($result === false) {
- $this->_db->addError();
- return false;
- }
-
- return true;
- }
-
- /**
- * 動画タグデータを登録する
- *
- * @param string $item_id 対象の動画ID
- * @return boolean true or false
- * @access public
- */
- function setItemTag($item_id, $item_tag) {
- if(empty($item_id)) {
- return false;
- }
-
- $container =& DIContainerFactory::getContainer();
-
- $tag_values = array();
- if (!empty($item_tag)) {
- $item_tag = str_replace(',', MULTIMEDIA_TAG_SEPARATOR, $item_tag);
- $item_tag = str_replace('、', MULTIMEDIA_TAG_SEPARATOR, $item_tag);
- $item_tag = str_replace('、', MULTIMEDIA_TAG_SEPARATOR, $item_tag);
- $tag_values = split(MULTIMEDIA_TAG_SEPARATOR, $item_tag);
- }
-
- foreach ($tag_values as $key => $value) {
- $value = preg_replace("/^[ ]+/u","",$value);
- $value = preg_replace("/[ ]+$/u","",$value);
- $tag_values[$key] = $value;
- }
-
- $tag_values = array_unique($tag_values);
-
- $sql = "SELECT R.tag_id "
- . "FROM {multimedia_item_tag} AS R "
- . "INNER JOIN {multimedia_tag} AS T "
- . "ON R.tag_id = T.tag_id "
- . "WHERE R.item_id = ? ";
- $params = array(
- $item_id
- );
- $tag_id_string = $this->_db->execute($sql, $params, $limit = null, $offset = null, false, array($this, "_makeImplodeString"));
-
- if ($tag_id_string === false) {
- $this->_db->addError();
- return false;
- }
- if (!empty($tag_id_string)) {
- $sql = "DELETE FROM {multimedia_item_tag} "
- . "WHERE item_id = ? "
- . "AND tag_id IN (" . $tag_id_string . ") ";
- $params = array(
- $item_id
- );
- if ($this->_db->execute($sql, $params) === false) {
- $this->_db->addError();
- return false;
- }
- }
-
- $sequence = 1;
- $tag_ids = array();
- foreach ($tag_values as $tag_value) {
- if (empty($tag_value)) {
- continue;
- }
- $sql = "SELECT tag_id "
- . "FROM {multimedia_tag} "
- . "WHERE tag_value = ? AND room_id = ? ";
- $params = array(
- $this->getSynonym($tag_value),
- $this->_request->getParameter("room_id")
- );
- $item_tag_ids = $this->_db->execute($sql, $params);
- if ($item_tag_ids === false) {
- $this->_db->addError();
- return false;
- }
- if (empty($item_tag_ids)) {
- $params = array(
- 'tag_value' => $this->getSynonym($tag_value),
- 'used_number' => 1
- );
-
- $tag_id = $this->_db->insertExecute('multimedia_tag', $params, true, 'tag_id');
- if (empty($tag_id)) {
- return false;
- }
-
- } else {
- $tag_id = $item_tag_ids[0]['tag_id'];
- }
- $tag_ids[] = $tag_id;
-
- $item_tag = array(
- 'item_id' => $item_id,
- 'tag_id' => $tag_id,
- 'tag_value' => $tag_value,
- 'sequence' => $sequence
- );
- if (!$this->_db->insertExecute('multimedia_item_tag', $item_tag, true)){
- return false;
- }
- $sequence++;
- }
-
- if (!empty($tag_id_string) && !empty($tag_ids)) {
- $tag_id_string .= ',';
- }
- $tag_id_string .= implode(',', $tag_ids);
-
- if (!$this->_tagReCount($tag_id_string)) {
- return false;
- }
-
- return true;
- }
-
- /**
- * 動画タグの使用回数を再カウント。0件ならmultimedia_tagから削除。
- *
- * @param string $tagIDString 区切り文字
- * @return boolean true or false
- * @access private
- */
- function _tagReCount($tag_id_string) {
- $counted_tag_ids = array();
- if (!empty($tag_id_string)) {
- $sql = "SELECT tag_id, "
- . "COUNT(DISTINCT item_id) AS tag_count "
- . "FROM {multimedia_item_tag} "
- . "WHERE tag_id IN (" . $tag_id_string . ") "
- . "GROUP BY tag_id;";
- $tags = $this->_db->execute($sql);
- if ($tags === false) {
- $this->_db->addError();
- return false;
- }
- if(!empty($tags)) {
- foreach ($tags as $tag) {
- $tag_used_number = array(
- 'tag_id' => $tag['tag_id'],
- 'used_number' => $tag['tag_count']
- );
- if (!$this->_db->updateExecute('multimedia_tag', $tag_used_number, 'tag_id', true)) {
- return false;
- }
-
- $counted_tag_ids[] = $tag['tag_id'];
- }
- }
- }
-
- $tag_ids = explode(',', $tag_id_string);
- $tag_ids = array_diff($tag_ids, $counted_tag_ids);
- foreach ($tag_ids as $tag_id) {
- $tag_used_number = array(
- 'tag_id' => $tag_id
- );
- if (!$this->_db->deleteExecute('multimedia_tag', $tag_used_number)) {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * ADORecordSetの1カラム目を指定文字区切りの文字列にする
- *
- * @param array $recordSet ADORecordSet
- * @param array $glue 区切り文字
- * @return array 指定文字区切りの文字列
- * @access private
- */
- function &_makeImplodeString(&$recordSet, $glue = ",") {
- $string = "";
- if ($recordSet->EOF) {
- return $string;
- }
-
- while ($row = $recordSet->fetchRow()) {
- $string .= $row[0] . $glue;
- }
- if (!empty($glue)) {
- $string = substr($string, 0, strlen($glue) * -1);
- }
-
- return $string;
- }
-
- function getSynonym($str) {
- //半角カナ(濁点付き)→全角カナに変換
- $replace_of = array('ヴ', 'ガ', 'ギ', 'グ',
- 'ゲ', 'ゴ', 'ザ', 'ジ',
- 'ズ', 'ゼ', 'ゾ', 'ダ',
- 'ヂ', 'ヅ', 'デ', 'ド',
- 'バ', 'ビ', 'ブ', 'ベ',
- 'ボ', 'パ', 'ピ', 'プ', 'ペ', 'ポ');
-
- $replace_by = array('ヴ', 'ガ', 'ギ', 'グ',
- 'ゲ', 'ゴ', 'ザ', 'ジ',
- 'ズ', 'ゼ', 'ゾ', 'ダ',
- 'ヂ', 'ヅ', 'デ', 'ド',
- 'バ', 'ビ', 'ブ', 'ベ',
- 'ボ', 'パ', 'ピ', 'プ', 'ペ', 'ポ');
- $_result = str_replace($replace_of, $replace_by, $str);
-
- //半角カナ→全角カナに変換
- $replace_of = array('ア', 'イ', 'ウ', 'エ', 'オ',
- 'カ', 'キ', 'ク', 'ケ', 'コ',
- 'サ', 'シ', 'ス', 'セ', 'ソ',
- 'タ', 'チ', 'ツ', 'テ', 'ト',
- 'ナ', 'ニ', 'ヌ', 'ネ', 'ノ',
- 'ハ', 'ヒ', 'フ', 'ヘ', 'ホ',
- 'マ', 'ミ', 'ム', 'メ', 'モ',
- 'ヤ', 'ユ', 'ヨ', 'ラ', 'リ',
- 'ル', 'レ', 'ロ', 'ワ', 'ヲ',
- 'ン', 'ァ', 'ィ', 'ゥ', 'ェ',
- 'ォ', 'ヵ', 'ヶ', 'ャ', 'ュ',
- 'ョ', 'ッ', '、', '。', 'ー',
- '「', '」', '゙', '゚');
-
- $replace_by = array('ア', 'イ', 'ウ', 'エ', 'オ',
- 'カ', 'キ', 'ク', 'ケ', 'コ',
- 'サ', 'シ', 'ス', 'セ', 'ソ',
- 'タ', 'チ', 'ツ', 'テ', 'ト',
- 'ナ', 'ニ', 'ヌ', 'ネ', 'ノ',
- 'ハ', 'ヒ', 'フ', 'ヘ', 'ホ',
- 'マ', 'ミ', 'ム', 'メ', 'モ',
- 'ヤ', 'ユ', 'ヨ', 'ラ', 'リ',
- 'ル', 'レ', 'ロ', 'ワ', 'ヲ',
- 'ン', 'ァ', 'ィ', 'ゥ', 'ェ',
- 'ォ', 'ヶ', 'ヶ', 'ャ', 'ュ',
- 'ョ', 'ッ', '、', '。', 'ー',
- '「', '」', '”', '');
-
- $_result = str_replace($replace_of, $replace_by, $_result);
-
- //全角数字→半角数字に変換
- $replace_of = array('1', '2', '3', '4', '5',
- '6', '7', '8', '9', '0');
-
- $replace_by = array('1', '2', '3', '4', '5',
- '6', '7', '8', '9', '0');
-
- $_result = str_replace($replace_of, $replace_by, $_result);
-
- //全角英字→半角英字に変換
- $replace_of = array('A', 'B', 'C', 'D', 'E',
- 'F', 'G', 'H', 'I', 'J',
- 'K', 'L', 'M', 'N', 'O',
- 'P', 'Q', 'R', 'S', 'T',
- 'U', 'V', 'W', 'X', 'Y',
- 'Z',
- 'a', 'b', 'c', 'd', 'e',
- 'f', 'g', 'h', 'i', 'j',
- 'k', 'l', 'm', 'n', 'o',
- 'p', 'q', 'r', 's', 't',
- 'u', 'v', 'w', 'x', 'y',
- 'z');
-
- $replace_by = array('A', 'B', 'C', 'D', 'E',
- 'F', 'G', 'H', 'I', 'J',
- 'K', 'L', 'M', 'N', 'O',
- 'P', 'Q', 'R', 'S', 'T',
- 'U', 'V', 'W', 'X', 'Y',
- 'Z',
- 'a', 'b', 'c', 'd', 'e',
- 'f', 'g', 'h', 'i', 'j',
- 'k', 'l', 'm', 'n', 'o',
- 'p', 'q', 'r', 's', 't',
- 'u', 'v', 'w', 'x', 'y',
- 'z');
-
- $_result = str_replace($replace_of, $replace_by, $_result);
-
-/*
- //小文字ひらがな→小文字カナに変換
- $replace_of = array('ぁ', 'ぃ', 'ぅ', 'ぇ', 'ぉ',
- 'ゃ', 'ゅ', 'ょ', 'っ');
-
- $replace_by = array('ァ', 'ィ', 'ゥ', 'ェ', 'ォ',
- 'ャ', 'ュ', 'ョ', 'ッ');
-
- $_result = str_replace($replace_of, $replace_by, $_result);
-*/
- //その他記号に変換
- $replace_of = array('ー', '-', '-', '~', ',',
- '、', ',', '・', '・', '=',
- '=', ' ', ' ', '。', '.',
- '.', '/', '/', '―', '‐',
- '’', '′', '´', '‘', '゜',
- '\'', '"', '〝', '″', '゛',
- '“', '”', 'ッ', 'ュ', 'ィ',
- 'ゅ', 'ぃ');
-
- $replace_by = array('', '', '', '', '',
- '', '', '', '', '',
- '', '', '', '', '',
- '', '', '', '', '',
- '', '', '', '', '',
- '', '', '', '', '',
- '', '', '', '', '',
- '', '');
-
- $_result = str_replace($replace_of, $replace_by, $_result);
-
-/*
- //小文字カナ→大文字カナに変換
- $replace_of = array('ァ', 'ィ', 'ゥ', 'ェ', 'ォ',
- 'ヶ', 'ヶ', 'ャ', 'ュ', 'ョ', 'ッ');
-
- $replace_by = array('ア', 'イ', 'ウ', 'エ', 'オ',
- 'ケ', 'ケ', 'ヤ', 'ユ', 'ヨ', 'ツ');
-
- $_result = str_replace($replace_of, $replace_by, $_result);
-*/
- return $_result;
- }
-}
+_db =& $container->getComponent("DbObject");
+ $this->_request =& $container->getComponent("Request");
+ }
+
+ /**
+ * ffmpegインストールチェック処理
+ *
+ * @param void
+ * @return boolean true or false
+ * @access public
+ */
+ function hasFfmpeg() {
+ if (!file_exists(MULTIMEDIA_FFMPEG_PATH)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * MP4Bpxインストールチェック処理
+ *
+ * @param void
+ * @return boolean true or false
+ * @access public
+ */
+ function hasMp4box() {
+ if (!file_exists(MULTIMEDIA_MP4BOX_PATH)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * サムネイル画像及び仮サムネイル画像削除処理
+ *
+ * @param string $thumbnail_path サムネイル画像のパス(縮小後)
+ * @param string $temp_thumbnail_path キャプチャ画像のパス(縮小前)
+ * @return void
+ * @access public
+ */
+# function deleteImages($thumbnail_path, $temp_thumbnail_path) {
+# //画像削除
+# unlink($thumbnail_path);
+# unlink($temp_thumbnail_path);
+# }
+
+ /**
+ * ファイル削除処理
+ *
+ * @param array $image_paths 削除対象ファイルパス
+ * @return void
+ * @access public
+ */
+ function deleteFiles($file_paths) {
+ foreach($file_paths as $path) {
+ //ファイル削除
+ unlink($path);
+ }
+ }
+
+ function hasFfmpegLib() {
+ $extension_fullname = PHP_EXTENSION_DIR . "/" . MULTIMEDIA_EXTENSION.".".PHP_SHLIB_SUFFIX;
+ if (!extension_loaded(MULTIMEDIA_EXTENSION)) {
+ //dl($extension_soname) or die("Can't load extension $extension_fullname\n");
+ return false;
+ }
+ return true;
+ }
+
+ function deleteMultimedia() {
+ $params = array(
+ "multimedia_id" => $this->_request->getParameter("multimedia_id")
+ );
+
+ if (!$this->_db->deleteExecute("multimedia_block", $params)) {
+ return false;
+ }
+
+ if (!$this->_db->deleteExecute("multimedia_comment", $params)) {
+ return false;
+ }
+
+ $sql = "SELECT item_id, upload_id, file_path ".
+ "FROM {multimedia_item} ".
+ "WHERE multimedia_id = ?";
+ $items = $this->_db->execute($sql, $params);
+ if ($items === false) {
+ $this->_db->addError();
+ return false;
+ }
+ if (!$this->deleteItemFile($items)) {
+ return false;
+ }
+ if (!$this->_db->deleteExecute("multimedia_item", $params)) {
+ return false;
+ }
+ if (!$this->_db->deleteExecute("multimedia_album", $params)) {
+ return false;
+ }
+ if (!$this->_db->deleteExecute("multimedia", $params)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ //動画ファイル削除
+ function deleteItemFile($items)
+ {
+ if (empty($items)) {
+ return true;
+ }
+
+ $container =& DIContainerFactory::getContainer();
+ $commonMain =& $container->getComponent("commonMain");
+ $uploads =& $commonMain->registerClass(WEBAPP_DIR.'/components/uploads/Action.class.php', "Uploads_Action", "uploadsAction");
+ $item_ids = array();
+ foreach ($items as $item) {
+ if (!$uploads->delUploadsById($item['upload_id'])) {
+ return false;
+ }
+ //動画のサムネイル画像があれば、削除
+ $thumbnail_path = FILEUPLOADS_DIR.$item['file_path'].$item['upload_id']."_thumbnail.jpg";
+ if(file_exists($thumbnail_path)) {
+ @chmod($thumbnail_path, 0777);
+ unlink($thumbnail_path);
+ }
+ //タグ削除
+ $sql = "SELECT tag_id "
+ . "FROM {multimedia_item_tag} "
+ . "WHERE item_id = ?;";
+ $params = array(
+ "item_id" => $item['item_id']
+ );
+ $tag_id_string = $this->_db->execute($sql, $params, $limit = null, $offset = null, false, array($this, "_makeImplodeString"));
+ if ($tag_id_string === false) {
+ $this->_db->addError();
+ return false;
+ }
+ if (!empty($tag_id_string)) {
+ if(!$this->_db->deleteExecute("multimedia_item_tag", $params)) {
+ return false;
+ }
+ }
+ $this->_tagReCount($tag_id_string);
+
+ if (!$this->_db->deleteExecute("multimedia_item_tag", $params)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ //カテゴリ削除
+ function deleteAlbum($multimedia_id, $album_id) {
+ $params = array(
+ "album_id" => $album_id
+ );
+
+ if (!$this->_db->deleteExecute("multimedia_comment", $params)) {
+ return false;
+ }
+
+ $sql = "SELECT item_id, upload_id, file_path ".
+ "FROM {multimedia_item} ".
+ "WHERE album_id = ?";
+ $items = $this->_db->execute($sql, $params);
+ if ($items === false) {
+ $this->_db->addError();
+ return false;
+ }
+ if (!$this->deleteItemFile($items)) {
+ return false;
+ }
+ if (!$this->_db->deleteExecute("multimedia_item", $params)) {
+ return false;
+ }
+
+ $sql = "SELECT album_sequence, upload_id ".
+ "FROM {multimedia_album} ".
+ "WHERE album_id = ?";
+ $albums = $this->_db->execute($sql, $params);
+ if ($albums === false) {
+ $this->_db->addError();
+ return false;
+ }
+
+ if (!$this->_db->deleteExecute("multimedia_album", $params)) {
+ return false;
+ }
+
+ if(!empty($albums[0]['upload_id'])) {
+ $container =& DIContainerFactory::getContainer();
+ $commonMain =& $container->getComponent("commonMain");
+ $uploads =& $commonMain->registerClass(WEBAPP_DIR.'/components/uploads/Action.class.php', "Uploads_Action", "uploadsAction");
+ if (!$uploads->delUploadsById($albums[0]['upload_id'])) {
+ return false;
+ }
+ }
+
+ $params = array(
+ "multimedia_id" => $multimedia_id
+ );
+ $sequenceParam = array(
+ "album_sequence" => $albums[0]['album_sequence']
+ );
+ if (!$this->_db->seqExecute("multimedia_album", $params, $sequenceParam)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ //動画削除
+ function deleteItem($item_id) {
+ $params = array(
+ "item_id" => $item_id
+ );
+
+ //コメント削除
+ if (!$this->_db->deleteExecute("multimedia_comment", $params)) {
+ return false;
+ }
+
+ //動画削除
+ $sql = "SELECT item_id, album_id, upload_id, file_path ".
+ "FROM {multimedia_item} ".
+ "WHERE item_id = ?";
+ $item = $this->_db->execute($sql, $params);
+ if ($item === false) {
+ $this->_db->addError();
+ return false;
+ }
+ if (!$this->deleteItemFile($item)) {
+ return false;
+ }
+ if (!$this->_db->deleteExecute("multimedia_item", $params)) {
+ return false;
+ }
+
+ if(!$this->setItemCount($item[0]['album_id'], -1)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ //アルバムの動画件数を計算
+ function setItemCount($album_id, $count) {
+ if(empty($album_id)) {
+ return false;
+ }
+
+ $params = array(
+ "album_id" => $album_id
+ );
+
+ $album = $this->_db->selectExecute("multimedia_album", $params);
+ if(empty($album) || !isset($album[0])) {
+ return false;
+ }
+
+ $sql = "UPDATE {multimedia_album} ".
+ "SET item_count = item_count + ".($count)." ".
+ "WHERE album_id = ?";
+ $result = $this->_db->execute($sql, $params);
+ if ($result === false) {
+ $this->_db->addError();
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * 動画タグデータを登録する
+ *
+ * @param string $item_id 対象の動画ID
+ * @return boolean true or false
+ * @access public
+ */
+ function setItemTag($item_id, $item_tag) {
+ if(empty($item_id)) {
+ return false;
+ }
+
+ $container =& DIContainerFactory::getContainer();
+
+ $tag_values = array();
+ if (!empty($item_tag)) {
+ $item_tag = str_replace(',', MULTIMEDIA_TAG_SEPARATOR, $item_tag);
+ $item_tag = str_replace('、', MULTIMEDIA_TAG_SEPARATOR, $item_tag);
+ $item_tag = str_replace('、', MULTIMEDIA_TAG_SEPARATOR, $item_tag);
+ $tag_values = split(MULTIMEDIA_TAG_SEPARATOR, $item_tag);
+ }
+
+ foreach ($tag_values as $key => $value) {
+ $value = preg_replace("/^[ ]+/u","",$value);
+ $value = preg_replace("/[ ]+$/u","",$value);
+ $tag_values[$key] = $value;
+ }
+
+ $tag_values = array_unique($tag_values);
+
+ $sql = "SELECT R.tag_id "
+ . "FROM {multimedia_item_tag} AS R "
+ . "INNER JOIN {multimedia_tag} AS T "
+ . "ON R.tag_id = T.tag_id "
+ . "WHERE R.item_id = ? ";
+ $params = array(
+ $item_id
+ );
+ $tag_id_string = $this->_db->execute($sql, $params, $limit = null, $offset = null, false, array($this, "_makeImplodeString"));
+
+ if ($tag_id_string === false) {
+ $this->_db->addError();
+ return false;
+ }
+ if (!empty($tag_id_string)) {
+ $sql = "DELETE FROM {multimedia_item_tag} "
+ . "WHERE item_id = ? "
+ . "AND tag_id IN (" . $tag_id_string . ") ";
+ $params = array(
+ $item_id
+ );
+ if ($this->_db->execute($sql, $params) === false) {
+ $this->_db->addError();
+ return false;
+ }
+ }
+
+ $sequence = 1;
+ $tag_ids = array();
+ foreach ($tag_values as $tag_value) {
+ if (empty($tag_value)) {
+ continue;
+ }
+ $sql = "SELECT tag_id "
+ . "FROM {multimedia_tag} "
+ . "WHERE tag_value = ? AND room_id = ? ";
+ $params = array(
+ $this->getSynonym($tag_value),
+ $this->_request->getParameter("room_id")
+ );
+ $item_tag_ids = $this->_db->execute($sql, $params);
+ if ($item_tag_ids === false) {
+ $this->_db->addError();
+ return false;
+ }
+ if (empty($item_tag_ids)) {
+ $params = array(
+ 'tag_value' => $this->getSynonym($tag_value),
+ 'used_number' => 1
+ );
+
+ $tag_id = $this->_db->insertExecute('multimedia_tag', $params, true, 'tag_id');
+ if (empty($tag_id)) {
+ return false;
+ }
+
+ } else {
+ $tag_id = $item_tag_ids[0]['tag_id'];
+ }
+ $tag_ids[] = $tag_id;
+
+ $item_tag = array(
+ 'item_id' => $item_id,
+ 'tag_id' => $tag_id,
+ 'tag_value' => $tag_value,
+ 'sequence' => $sequence
+ );
+ if (!$this->_db->insertExecute('multimedia_item_tag', $item_tag, true)){
+ return false;
+ }
+ $sequence++;
+ }
+
+ if (!empty($tag_id_string) && !empty($tag_ids)) {
+ $tag_id_string .= ',';
+ }
+ $tag_id_string .= implode(',', $tag_ids);
+
+ if (!$this->_tagReCount($tag_id_string)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * 動画タグの使用回数を再カウント。0件ならmultimedia_tagから削除。
+ *
+ * @param string $tagIDString 区切り文字
+ * @return boolean true or false
+ * @access private
+ */
+ function _tagReCount($tag_id_string) {
+ $counted_tag_ids = array();
+ if (!empty($tag_id_string)) {
+ $sql = "SELECT tag_id, "
+ . "COUNT(DISTINCT item_id) AS tag_count "
+ . "FROM {multimedia_item_tag} "
+ . "WHERE tag_id IN (" . $tag_id_string . ") "
+ . "GROUP BY tag_id;";
+ $tags = $this->_db->execute($sql);
+ if ($tags === false) {
+ $this->_db->addError();
+ return false;
+ }
+ if(!empty($tags)) {
+ foreach ($tags as $tag) {
+ $tag_used_number = array(
+ 'tag_id' => $tag['tag_id'],
+ 'used_number' => $tag['tag_count']
+ );
+ if (!$this->_db->updateExecute('multimedia_tag', $tag_used_number, 'tag_id', true)) {
+ return false;
+ }
+
+ $counted_tag_ids[] = $tag['tag_id'];
+ }
+ }
+ }
+
+ $tag_ids = explode(',', $tag_id_string);
+ $tag_ids = array_diff($tag_ids, $counted_tag_ids);
+ foreach ($tag_ids as $tag_id) {
+ $tag_used_number = array(
+ 'tag_id' => $tag_id
+ );
+ if (!$this->_db->deleteExecute('multimedia_tag', $tag_used_number)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * ADORecordSetの1カラム目を指定文字区切りの文字列にする
+ *
+ * @param array $recordSet ADORecordSet
+ * @param array $glue 区切り文字
+ * @return array 指定文字区切りの文字列
+ * @access private
+ */
+ function &_makeImplodeString(&$recordSet, $glue = ",") {
+ $string = "";
+ if ($recordSet->EOF) {
+ return $string;
+ }
+
+ while ($row = $recordSet->fetchRow()) {
+ $string .= $row[0] . $glue;
+ }
+ if (!empty($glue)) {
+ $string = substr($string, 0, strlen($glue) * -1);
+ }
+
+ return $string;
+ }
+
+ function getSynonym($str) {
+ //半角カナ(濁点付き)→全角カナに変換
+ $replace_of = array('ヴ', 'ガ', 'ギ', 'グ',
+ 'ゲ', 'ゴ', 'ザ', 'ジ',
+ 'ズ', 'ゼ', 'ゾ', 'ダ',
+ 'ヂ', 'ヅ', 'デ', 'ド',
+ 'バ', 'ビ', 'ブ', 'ベ',
+ 'ボ', 'パ', 'ピ', 'プ', 'ペ', 'ポ');
+
+ $replace_by = array('ヴ', 'ガ', 'ギ', 'グ',
+ 'ゲ', 'ゴ', 'ザ', 'ジ',
+ 'ズ', 'ゼ', 'ゾ', 'ダ',
+ 'ヂ', 'ヅ', 'デ', 'ド',
+ 'バ', 'ビ', 'ブ', 'ベ',
+ 'ボ', 'パ', 'ピ', 'プ', 'ペ', 'ポ');
+ $_result = str_replace($replace_of, $replace_by, $str);
+
+ //半角カナ→全角カナに変換
+ $replace_of = array('ア', 'イ', 'ウ', 'エ', 'オ',
+ 'カ', 'キ', 'ク', 'ケ', 'コ',
+ 'サ', 'シ', 'ス', 'セ', 'ソ',
+ 'タ', 'チ', 'ツ', 'テ', 'ト',
+ 'ナ', 'ニ', 'ヌ', 'ネ', 'ノ',
+ 'ハ', 'ヒ', 'フ', 'ヘ', 'ホ',
+ 'マ', 'ミ', 'ム', 'メ', 'モ',
+ 'ヤ', 'ユ', 'ヨ', 'ラ', 'リ',
+ 'ル', 'レ', 'ロ', 'ワ', 'ヲ',
+ 'ン', 'ァ', 'ィ', 'ゥ', 'ェ',
+ 'ォ', 'ヵ', 'ヶ', 'ャ', 'ュ',
+ 'ョ', 'ッ', '、', '。', 'ー',
+ '「', '」', '゙', '゚');
+
+ $replace_by = array('ア', 'イ', 'ウ', 'エ', 'オ',
+ 'カ', 'キ', 'ク', 'ケ', 'コ',
+ 'サ', 'シ', 'ス', 'セ', 'ソ',
+ 'タ', 'チ', 'ツ', 'テ', 'ト',
+ 'ナ', 'ニ', 'ヌ', 'ネ', 'ノ',
+ 'ハ', 'ヒ', 'フ', 'ヘ', 'ホ',
+ 'マ', 'ミ', 'ム', 'メ', 'モ',
+ 'ヤ', 'ユ', 'ヨ', 'ラ', 'リ',
+ 'ル', 'レ', 'ロ', 'ワ', 'ヲ',
+ 'ン', 'ァ', 'ィ', 'ゥ', 'ェ',
+ 'ォ', 'ヶ', 'ヶ', 'ャ', 'ュ',
+ 'ョ', 'ッ', '、', '。', 'ー',
+ '「', '」', '”', '');
+
+ $_result = str_replace($replace_of, $replace_by, $_result);
+
+ //全角数字→半角数字に変換
+ $replace_of = array('1', '2', '3', '4', '5',
+ '6', '7', '8', '9', '0');
+
+ $replace_by = array('1', '2', '3', '4', '5',
+ '6', '7', '8', '9', '0');
+
+ $_result = str_replace($replace_of, $replace_by, $_result);
+
+ //全角英字→半角英字に変換
+ $replace_of = array('A', 'B', 'C', 'D', 'E',
+ 'F', 'G', 'H', 'I', 'J',
+ 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y',
+ 'Z',
+ 'a', 'b', 'c', 'd', 'e',
+ 'f', 'g', 'h', 'i', 'j',
+ 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't',
+ 'u', 'v', 'w', 'x', 'y',
+ 'z');
+
+ $replace_by = array('A', 'B', 'C', 'D', 'E',
+ 'F', 'G', 'H', 'I', 'J',
+ 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y',
+ 'Z',
+ 'a', 'b', 'c', 'd', 'e',
+ 'f', 'g', 'h', 'i', 'j',
+ 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't',
+ 'u', 'v', 'w', 'x', 'y',
+ 'z');
+
+ $_result = str_replace($replace_of, $replace_by, $_result);
+
+/*
+ //小文字ひらがな→小文字カナに変換
+ $replace_of = array('ぁ', 'ぃ', 'ぅ', 'ぇ', 'ぉ',
+ 'ゃ', 'ゅ', 'ょ', 'っ');
+
+ $replace_by = array('ァ', 'ィ', 'ゥ', 'ェ', 'ォ',
+ 'ャ', 'ュ', 'ョ', 'ッ');
+
+ $_result = str_replace($replace_of, $replace_by, $_result);
+*/
+ //その他記号に変換
+ $replace_of = array('ー', '-', '-', '~', ',',
+ '、', ',', '・', '・', '=',
+ '=', ' ', ' ', '。', '.',
+ '.', '/', '/', '―', '‐',
+ '’', '′', '´', '‘', '゜',
+ '\'', '"', '〝', '″', '゛',
+ '“', '”', 'ッ', 'ュ', 'ィ',
+ 'ゅ', 'ぃ');
+
+ $replace_by = array('', '', '', '', '',
+ '', '', '', '', '',
+ '', '', '', '', '',
+ '', '', '', '', '',
+ '', '', '', '', '',
+ '', '', '', '', '',
+ '', '', '', '', '',
+ '', '');
+
+ $_result = str_replace($replace_of, $replace_by, $_result);
+
+/*
+ //小文字カナ→大文字カナに変換
+ $replace_of = array('ァ', 'ィ', 'ゥ', 'ェ', 'ォ',
+ 'ヶ', 'ヶ', 'ャ', 'ュ', 'ョ', 'ッ');
+
+ $replace_by = array('ア', 'イ', 'ウ', 'エ', 'オ',
+ 'ケ', 'ケ', 'ヤ', 'ユ', 'ヨ', 'ツ');
+
+ $_result = str_replace($replace_of, $replace_by, $_result);
+*/
+ return $_result;
+ }
+}
?>
\ No newline at end of file
diff --git a/multimedia/components/View.class.php b/multimedia/components/View.class.php
index 89c36c7..c65f307 100644
--- a/multimedia/components/View.class.php
+++ b/multimedia/components/View.class.php
@@ -1,966 +1,966 @@
-_db =& $container->getComponent("DbObject");
- $this->_request =& $container->getComponent("Request");
- $this->_session =& $container->getComponent("Session");
- }
-
- /**
- * 配置されている動画配信IDを取得する
- *
- * @return string 配置されている動画配信ID
- * @access public
- */
- function &getCurrentMultimediaId() {
- $params = array($this->_request->getParameter("block_id"));
- $sql = "SELECT multimedia_id ".
- "FROM {multimedia_block} ".
- "WHERE block_id = ?";
- $result = $this->_db->execute($sql, $params);
- if ($result === false) {
- $this->_db->addError();
- return $result;
- }
-
- return $result[0]["multimedia_id"];
- }
-
- /**
- * 現在登録されている動画配信IDを取得する
- *
- * @return string 配置されている動画配信ID
- * @access pblic
- */
- function &getFirstMultimediaId() {
- $params = array(
- $this->_request->getParameter('room_id')
- );
- $sql = "SELECT multimedia_id "
- . "FROM {multimedia} "
- . "WHERE room_id = ?";
- $result = $this->_db->execute($sql, $params, 1);
- if ($result === false) {
- $this->_db->addError();
- return $result;
- }
-
- return $result[0]['multimedia_id'];
- }
-
- /**
- * 動画配信が配置されているブロックデータを取得する
- *
- * @return string ブロックデータ
- * @access public
- */
- function &getBlock() {
- $params = array($this->_request->getParameter("multimedia_id"));
- $sql = "SELECT M.room_id, B.block_id ".
- "FROM {multimedia} M ".
- "INNER JOIN {multimedia_block} B ".
- "ON M.multimedia_id = B.multimedia_id ".
- "WHERE M.multimedia_id = ? ".
- "ORDER BY B.block_id";
- $result = $this->_db->execute($sql, $params, 1);
- if ($result === false) {
- $this->_db->addError();
- return $result;
- }
-
- return $result[0];
- }
-
- /**
- * 動画配信が存在するか判断する
- *
- * @return boolean true:存在する、false:存在しない
- * @access public
- */
- function multimediaExist() {
- $params = array(
- $this->_request->getParameter("multimedia_id"),
- $this->_request->getParameter("room_id")
- );
- $sql = "SELECT multimedia_id ".
- "FROM {multimedia} ".
- "WHERE multimedia_id = ? ".
- "AND room_id = ?";
- $result = $this->_db->execute($sql, $params);
- if ($result === false) {
- $this->_db->addError();
- return $result;
- }
-
- if (count($result) > 0) {
- return true;
- }
-
- return false;
- }
-
- function getMultimediaCount() {
- $params["room_id"] = $this->_request->getParameter("room_id");
- $count = $this->_db->countExecute("multimedia", $params);
- if($count === false) {
- $this->_db->addError();
- }
-
- return $count;
- }
-
- /**
- * 動画配信の設定データを取得する
- *
- * @return string 設定データ配列
- * @access public
- */
- function &getConfig() {
- $container =& DIContainerFactory::getContainer();
- $configView =& $container->getComponent("configView");
- $module_id = $this->_request->getParameter("module_id");
- $config = $configView->getConfig($module_id, false);
-
- return $config;
- }
-
- /**
- * 動画配信用デフォルトデータを取得する
- *
- * @return array 動画配信用デフォルトデータ配列
- * @access public
- */
- function &getDefaultMultimedia() {
- $config = $this->getConfig();
- if ($config === false) {
- return $config;
- }
-
- $multimedia = array(
- "album_authority" => constant($config['album_authority']['conf_value']),
- "vote_flag" => constant($config['vote_flag']['conf_value']),
- "comment_flag" => constant($config['comment_flag']['conf_value']),
- "confirm_flag" => constant($config['confirm_flag']['conf_value']),
- "display" => constant($config['display']['conf_value']),
- "autoplay_flag" => constant($config['autoplay_flag']['conf_value']),
- "buffer_time" => $config['buffer_time']['conf_value'],
- "album_visible_row" => $config['album_visible_row']['conf_value'],
- "new_period" => $config['new_period']['conf_value'],
- "album_jacket" => $config['album_jacket']['conf_value']
- );
-
- return $multimedia;
- }
-
- /**
- * 動画配信データを取得する
- *
- * @return array 動画配信データ
- * @access public
- */
- function &getCurrentMultimedia() {
- $params = array($this->_request->getParameter("block_id"));
- $sql = "SELECT B.block_id, B.multimedia_id, B.display, ".
- "B.autoplay_flag, B.buffer_time, ".
- "B.album_visible_row, B.new_period, ".
- "M.album_authority, M.vote_flag, M.comment_flag, M.confirm_flag ".
- "FROM {multimedia_block} B ".
- "INNER JOIN {multimedia} M ".
- "ON B.multimedia_id = M.multimedia_id ".
- "WHERE block_id = ?";
- $result = $this->_db->execute($sql, $params);
- if ($result === false) {
- $this->_db->addError();
- }
- if (empty($result)) {
- return $result;
- }
-
- $result[0]['album_authority'] = $this->_hasAlbumAuthority($result[0]);
- $result[0]['new_period_time'] = $this->_getNewPeriodTime($result[0]['new_period']);
-
- return $result[0];
- }
-
- /**
- * アルバム作成権限を取得する
- *
- * @param array $photoalbum フォトアルバムデータ配列
- * @return boolean true:権限有り、false:権限無し
- * @access public
- */
- function _hasAlbumAuthority($multimedia) {
- $auth_id = $this->_session->getParameter("_auth_id");
- if ($auth_id >= $multimedia['album_authority']) {
- return true;
- }
-
- return false;
- }
-
- function getMultimediaById($multimedia_id) {
- $params = array(
- "multimedia_id" => $multimedia_id
- );
-
- $result = $this->_db->selectExecute("multimedia", $params);
- if ($result === false) {
- $this->_db->addError();
- }
-
- if(!empty($result) && isset($result[0])) {
- return $result[0];
- }
-
- return $result;
- }
-
- /**
- * フォトアルバムデータを取得する
- *
- * @return array フォトアルバムデータ
- * @access public
- */
- function &getMultimedia() {
- $params = array($this->_request->getParameter("multimedia_id"));
- $sql = "SELECT multimedia_id, album_authority, vote_flag, comment_flag, confirm_flag ".
- "FROM {multimedia} ".
- "WHERE multimedia_id = ?";
- $result = $this->_db->execute($sql, $params);
- if ($result === false) {
- $this->_db->addError();
- return $result;
- }
-
- return $result[0];
- }
-
- /**
- * new記号表示期間から対象年月日を取得する
- *
- * @param string $new_period new記号表示期間
- * @return string new記号表示対象年月日(YmdHis)
- * @access public
- */
- function &_getNewPeriodTime($new_period) {
- if (empty($new_period)) {
- $new_period = -1;
- }
-
- $time = timezone_date();
- $time = mktime(0, 0, 0,
- intval(substr($time, 4, 2)),
- intval(substr($time, 6, 2)) - $new_period,
- intval(substr($time, 0, 4))
- );
- $time = date("YmdHis", $time);
-
- return $time;
- }
-
- /**
- * 動画配信のアルバムの計数を取得する
- *
- * @param string $new_period new記号表示期間
- * @return string new記号表示対象年月日(YmdHis)
- * @access public
- */
- function getAlbumCount($multimedia_id) {
- $params[] = $multimedia_id;
-
- $sql = "SELECT COUNT(*) as count ".
- "FROM {multimedia_album} A ";
- $sql .= $this->_getAuthorityFromSQL();
- $sql .= "WHERE A.multimedia_id = ? ";
- $sql .= $this->_getAuthorityWhereSQL($params);
- if(!empty($order_params)) {
- $sql .= $this->_db->getOrderSQL($order_params);
- }
- $result = $this->_db->execute($sql, $params);
- if ( $result === false ) {
- // エラーが発生した場合、エラーリストに追加
- $this->_db->addError();
- return $result;
- }
- return $result[0]['count'];
- }
-
- /**
- * アルバム一覧を取得する
- *
- * @return array アルバム一覧データ
- * @access public
- */
- function getAlbumList($multimedia_id, $order_params=null, $disp_cnt=null, $begin=null) {
- $params[] = $multimedia_id;
-
- $sql = "SELECT A.* ".
- "FROM {multimedia_album} A ";
- $sql .= $this->_getAuthorityFromSQL();
- $sql .= "WHERE A.multimedia_id = ? ";
- $sql .= $this->_getAuthorityWhereSQL($params);
- if(!empty($order_params)) {
- $sql .= $this->_db->getOrderSQL($order_params);
- }
- $result = $this->_db->execute($sql, $params, $disp_cnt, $begin, true, array($this, "_makeAlbumArray"));
- if ( $result === false ) {
- // エラーが発生した場合、エラーリストに追加
- $this->_db->addError();
- }
-
- return $result;
- }
-
- /**
- * アルバムデータ配列を生成する
- *
- * @param array $recordSet タスクADORecordSet
- * @return array タスクデータ配列
- * @access private
- */
- function &_makeAlbumArray(&$recordSet) {
- $multimedia = $this->_request->getParameter("multimedia_obj");
-
- $albums = array();
- while ($row = $recordSet->fetchRow()) {
- if (!empty($row["album_jacket"])) {
- $row["jacket_style"] = $this->getImageStyle($row["width"], $row["height"], MULTIMEDIA_JACKET_WIDTH, MULTIMEDIA_JACKET_HEIGHT);
- }
-
- $row["edit_authority"] = false;
- if ($multimedia["album_authority"]
- && $this->_hasEditAuthority($row["insert_user_id"])) {
- $row["edit_authority"] = true;
- }
-
- $albums[] = $row;
- }
-
- return $albums;
- }
-
- /**
- * アルバムのサムネイルのスタイル属性値を取得する
- *
- * @param string $width 幅
- * @param string $height 高さ
- * @param string $maxWidth 最大幅
- * @param string $maxHeight 最大高さ
- * @return array 画像のスタイル属性値
- * @access private
- */
- function &getImageStyle($width, $height, $maxWidth, $maxHeight) {
- $ratio = $height / $width;
-
- $widthRatio = $width / $maxWidth;
- $heightRatio = $height / $maxHeight;
-
- if ($widthRatio > $heightRatio) {
- $height = $maxHeight;
- $widht = intval($height / $ratio);
- $top = 0;
- $right = intval(($widht + $maxWidth) / 2);
- $bottom = $maxHeight;
- $left = intval(($widht - $maxWidth) / 2);
- $marginLeft = $left * -1;
- $marginTop = $top;
- } else {
- $widht = $maxWidth;
- $height = intval($widht * $ratio);
- $top = intval(($height - $maxHeight) / 2);
- $right = $maxWidth;
- $bottom = intval(($height + $maxHeight) / 2);
- $left = 0;
- $marginLeft = $left;
- $marginTop = $top * -1;
- }
-
- $style = sprintf(MULTIMEDIA_THUMBNAIL_STYLE, $widht, $height, $top, $right, $bottom, $left, $marginLeft, $marginTop);
-
- return $style;
- }
-
- /**
- * アルバムを取得する
- *
- * @return array アルバムデータ
- * @access public
- */
- function getAlbum($album_id) {
- $params = array(
- "album_id" => intval($album_id)
- );
-
- $result = $this->_db->selectExecute("multimedia_album", $params, null, null, null, array($this, "_makeAlbumArray"));
- if ($result === false) {
- $this->_db->addError();
- }
-
- if(!empty($result) && isset($result[0])) {
- return $result[0];
- }
-
- return $result;
- }
-
- /**
- * 動画を取得する
- *
- * @return array 動画データ
- * @access public
- */
- function getItem($item_id) {
- $params = array(
- "item_id" => intval($item_id)
- );
-
- $result = $this->_db->selectExecute("multimedia_item", $params, null, null, null, array($this, "_makeItemArray"));
- if ($result === false) {
- $this->_db->addError();
- }
-
- if(!empty($result) && isset($result[0])) {
- $result[0]['vote_authority'] = $this->_hasVoteAuthority($item_id);
- $result[0]['comment_authority'] = $this->_hasCommentAuthority();
- return $result[0];
- }
-
- return $result;
- }
-
- /**
- * 編集権限を取得する
- *
- * @param array $insertUserID 登録者ID
- * @return boolean true:権限有り、false:権限無し
- * @access public
- */
- function _hasEditAuthority(&$insertUserID) {
- $container =& DIContainerFactory::getContainer();
-
- $authID = $this->_session->getParameter("_auth_id");
- if ($authID >= _AUTH_CHIEF) {
- return true;
- }
-
- $userID = $this->_session->getParameter("_user_id");
- if ($insertUserID == $userID) {
- return true;
- }
-
- $hierarchy = $this->_session->getParameter("_hierarchy");
- $authCheck =& $container->getComponent("authCheck");
- $insetUserHierarchy = $authCheck->getPageHierarchy($insertUserID);
- if ($hierarchy > $insetUserHierarchy) {
- return true;
- }
-
- return false;
- }
-
- /**
- * 投票権限を取得する
- *
- * @param array $item 動画データ配列
- * @return boolean true:権限有り、false:権限無し
- * @access public
- */
- function _hasVoteAuthority($item_id) {
- $multimedia = $this->_request->getParameter("multimedia_obj");
- if ($multimedia['vote_flag'] != _ON) {
- return false;
- }
-
- $votes = $this->_session->getParameter("multimedia_votes");
- if (!empty($votes) && in_array($item_id, $votes)) {
- return false;
- }
-
- $user_id = $this->_session->getParameter("_user_id");
- if (empty($user_id)) {
- return true;
- }
-
- $params = array(
- $user_id,
- $item_id
- );
- $sql = "SELECT vote_flag ".
- "FROM {mutlimedia_user_item} ".
- "WHERE user_id = ? ".
- "AND item_id = ?";
- $vote_flags = $this->_db->execute($sql, $params, null, null, false);
- if ($vote_flags === false) {
- $this->_db->addError();
- return false;
- }
-
- if (empty($vote_flags) || $vote_flags[0][0] != _ON) {
- return true;
- }
-
- return false;
- }
-
- /**
- * コメント権限を取得する
- *
- * @return boolean true:権限有り、false:権限無し
- * @access public
- */
- function _hasCommentAuthority() {
- $multimedia = $this->_request->getParameter("multimedia_obj");
- if ($multimedia['comment_flag'] != _ON) {
- return false;
- }
-
- $auth_id = $this->_session->getParameter("_auth_id");
- if ($auth_id <= _AUTH_GUEST) {
- return false;
- }
-
- return true;
- }
-
- /**
- * 動画のコメントの計数を取得する
- *
- * @param string $item_id 動画id
- * @return string 動画のコメントの計数
- * @access public
- */
- function getCommentCount($item_id) {
- $params = array(
- "item_id" => intval($item_id)
- );
- $commentCount = $this->_db->countExecute("multimedia_comment", $params);
-
- if($commentCount === false) {
- $this->_db->addError();
- }
-
- return $commentCount;
- }
-
- /**
- * 動画のコメントを取得する
- *
- * @param string $item_id 動画id
- * @return string 動画のコメント
- * @access public
- */
- function getComments($item_id, $begin=null) {
- $comments = $this->_db->selectExecute("multimedia_comment", array("item_id" => intval($item_id)), array("insert_time" => "DESC"), MULTIMEDIA_VISIBLE_ITEM_COMMENT, $begin, array($this, "_makeCommentArray"));
- if($comments === false) {
- $this->_db->addError();
- }
-
- return $comments;
- }
-
- /**
- * コメントデータ配列を生成する
- *
- * @param array $recordSet タスクADORecordSet
- * @return array タスクデータ配列
- * @access private
- */
- function &_makeCommentArray(&$recordSet) {
- $comments = array();
- while ($row = $recordSet->fetchRow()) {
- $row["edit_authority"] = false;
- if ($this->_hasEditAuthority($row["insert_user_id"])) {
- $row["edit_authority"] = true;
- }
-
- $comments[] = $row;
- }
-
- return $comments;
- }
-
- /**
- * 画像の大きさを取得
- *
- * @return string 画像の大きさ
- * @access public
- */
- function &getImageSize($image) {
- if (is_numeric($image)) {
- $container =& DIContainerFactory::getContainer();
-
- $uploads =& $container->getComponent("uploadsView");
- $uploadFiles = $uploads->getUploadById($image);
- if (empty($uploadFiles)) {
- return false;
- }
-
- $imageSize = getimagesize(FILEUPLOADS_DIR. "multimedia/". $uploadFiles[0]["physical_file_name"]);
- } else {
- $imageSize = getimagesize(HTDOCS_DIR.MULTIMEDIA_SAMPLR_JACKET_PATH.MULTIMEDIA_SAMPLR_JACKET_DIR.$image);
- }
-
- return $imageSize;
- }
-
- /**
- * 権限判断用のSQL文FROM句を取得する
- *
- * @return string 権限判断用のSQL文FROM句
- * @access public
- */
- function &_getAuthorityFromSQL() {
- $auth_id = $this->_session->getParameter("_auth_id");
-
- $sql = "";
- if ($auth_id >= _AUTH_CHIEF) {
- return $sql;
- }
-
- $sql .= "LEFT JOIN {pages_users_link} PU ".
- "ON A.insert_user_id = PU.user_id ".
- "AND A.room_id = PU.room_id ";
- $sql .= "LEFT JOIN {authorities} AU ".
- "ON PU.role_authority_id = AU.role_authority_id ";
-
- return $sql;
- }
-
- /**
- * 権限判断用のSQL文WHERE句を取得する
- * パラメータ用配列に必要な値を追加する
- *
- * @param array $params パラメータ用配列
- * @return string 権限判断用のSQL文WHERE句
- * @access public
- */
- function &_getAuthorityWhereSQL(&$params) {
- $auth_id = $this->_session->getParameter("_auth_id");
-
- $sql = "";
- if ($auth_id >= _AUTH_CHIEF) {
- return $sql;
- }
-
- $sql .= " AND (A.public_flag = ? OR AU.hierarchy < ? OR A.insert_user_id = ? ";
-
- $default_entry = $this->_session->getParameter("_default_entry_flag");
- $hierarchy = $this->_session->getParameter("_hierarchy");
- if ($default_entry == _ON && $hierarchy > $this->_session->getParameter("_default_entry_hierarchy")) {
- $sql .= " OR AU.hierarchy IS NULL) ";
- } else {
- $sql .= ") ";
- }
-
- $params[] = _ON;
- $params[] = $hierarchy;
- $params[] = $this->_session->getParameter("_user_id");
-
- return $sql;
- }
-
- /**
- * 動画データ配列を生成する
- *
- * @param array $recordSet 動画ADORecordSet
- * @return array 動画データ配列
- * @access private
- */
- function &_makeItemArray(&$recordSet) {
- $items = array();
- while ($row = $recordSet->fetchRow()) {
- $row['edit_authority'] = false;
- if ($this->_hasEditAuthority($row['insert_user_id'])) {
- $row['edit_authority'] = true;
- }
- $tags = $this->getTags($row['item_id']);
- $row['item_tag'] = $this->_makeTagString($tags);
- $row['duration'] = floor($row['duration']/60).":".floor(($row['duration']-60*floor($row['duration']/60)));
- $items[] = $row;
- }
-
- return $items;
- }
-
- /**
- * 動画一覧共通のSQL
- *
- * @return array 動画件数データ
- * @access public
- */
- function _getItemListSQL(&$params, $where_params, $order_params=null, $count_flag=false) {
- $sql = "";
- if(empty($order_params)) {
- $order_params = array(
- "insert_time" => "DESC"
- );
- }
-
- if($count_flag) {
- $sql = "SELECT COUNT(T.item_id) as count FROM {multimedia_item} T ";
- }else {
- $sql = "SELECT T.* FROM {multimedia_item} T ";
- }
- $sql .= "LEFT JOIN {multimedia_album} A ON T.album_id=A.album_id ";
- $sql .= $this->_getAuthorityFromSQL();
- if(!empty($where_params)) {
- foreach($where_params as $key => $val) {
- if($val == "") {
- continue;
- }
- $where_params["T.".$key] = $val;
- unset($where_params[$key]);
- }
- $sql .= $this->_db->getWhereSQL($params, $where_params);
- }
- $sql .= $this->_getAuthorityWhereSQL($params);
- if(!$count_flag) {
- foreach($order_params as $key => $val) {
- $order_params["T.".$key] = $val;
- unset($order_params[$key]);
- }
- $sql .= $this->_db->getOrderSQL($order_params);
- }
-
- return $sql;
- }
-
- /**
- * 動画一覧件数を取得する
- *
- * @return array 動画件数データ
- * @access public
- */
- function getItemListCount($where_params) {
- if(empty($where_params)) {
- return false;
- }
-
- $sql = "";
- $params = array();
- $sql = $this->_getItemListSQL($params, $where_params, null, true);
- $result = $this->_db->execute($sql, $params);
- if ( $result === false ) {
- // エラーが発生した場合、エラーリストに追加
- $this->_db->addError();
- return $result;
- }
- return $result[0]['count'];
- }
-
- /**
- * 動画一覧を取得する
- *
- * @param int $multimedia_id ID
- * @return array 動画データ
- * @access public
- */
- function getItemList($where_params, $order_params, $begin=null) {
- if(empty($where_params)) {
- return false;
- }
-
- $sql = "";
- $params = array();
- $sql = $this->_getItemListSQL($params, $where_params, $order_params);
-
- $result = $this->_db->execute($sql, $params ,MULTIMEDIA_VISIBLE_ITEM_CNT, $begin, true, array($this, "_makeItemArray"));
- if ( $result === false ) {
- // エラーが発生した場合、エラーリストに追加
- $this->_db->addError();
- return $result;
- }
- return $result;
- }
-
- /**
- * 検索動画一覧を取得する
- *
- * @return array 動画データ
- * @access public
- */
- function getSearchItemList($sql, $where_params, $begin=null) {
- $result = $this->_db->execute($sql, $where_params ,MULTIMEDIA_SEARCH_VISIBLE_ITEM_CNT, $begin, true, array($this, "_makeItemArray"));
- if ( $result === false ) {
- // エラーが発生した場合、エラーリストに追加
- $this->_db->addError();
- }
- return $result;
- }
-
- /**
- * タグデータ配列を取得する
- *
- * @return array タグデータ配列
- * @access public
- */
- function getTags($item_id) {
- $sql = "SELECT R.tag_value, T.used_number, R.tag_id, R.item_id, R.sequence " .
- "FROM {multimedia_item_tag} AS R, {multimedia_tag} AS T " .
- "WHERE R.tag_id = T.tag_id " .
- "AND R.item_id = ? " .
- "ORDER BY R.sequence;";
-
- $params = array(
- $item_id
- );
- $tags = $this->_db->execute($sql, $params);
- if ($tags === false) {
- $this->_db->addError();
- return false;
- }
- return $tags;
- }
-
- /**
- * 関連動画配列を取得する
- *
- * @return array タグデータ配列
- * @access public
- */
- function getSimilarItems($item_id) {
- $tags = $this->getTags($item_id);
- if(empty($tags)) {
- return $tags;
- }
-
- $params = array();
- $where_sql = "";
- foreach($tags as $tag) {
- $params[] = $tag['tag_id'];
- $where_sql .= " G.tag_id=? OR";
- }
- $where_sql = " ( ".substr($where_sql, 0, -2)." ) ";
- $sql = "SELECT T.*,count(*) as count " .
- "FROM {multimedia_item_tag} AS G, {multimedia_item} AS T ";
- $sql .= "LEFT JOIN {multimedia_album} A ON T.album_id=A.album_id ";
- $sql .= $this->_getAuthorityFromSQL();
- $sql .= "WHERE G.item_id=T.item_id AND T.item_id <> ".$item_id." AND ".$where_sql;
- $sql .= $this->_getAuthorityWhereSQL($params);
- $sql .= " GROUP BY T.item_id ORDER BY count DESC";
- $items = $this->_db->execute($sql, $params, MULTIMEDIA_TAG_ITEMS_NUMBER, 0, true, array($this, "_makeItemArray"));
- if ($items === false) {
- $this->_db->addError();
- return false;
- }
- return $items;
- }
-
- /**
- * タグストリングを生成する
- */
- function &_makeTagString($tags) {
- $string = "";
- if(empty($tags)) {
- return $string;
- }
- $string = "";
- foreach($tags as $tag) {
- $string .= $tag['tag_value'].MULTIMEDIA_TAG_SEPARATOR;
- }
- $string = substr($string, 0, -1);
-
- return $string;
- }
-
- /**
- * ページに関する設定を行います
- *
- * @param int disp_cnt 1ページ当り表示件数
- * @param int now_page 現ページ
- */
- function setPageInfo(&$pager, $data_cnt, $disp_cnt, $now_page = NULL){
- $pager['data_cnt'] = 0;
- $pager['total_page'] = 0;
- $pager['next_link'] = FALSE;
- $pager['prev_link'] = FALSE;
- $pager['disp_begin'] = 0;
- $pager['disp_end'] = 0;
- $pager['link_array'] = NULL;
-
- if(empty($disp_cnt)) {
- return false;
- }
-
- $pager['data_cnt'] = $data_cnt;
- // now page
- $pager['now_page'] = (NULL == $now_page) ? 1 : $now_page;
- // total page
- $pager['total_page'] = ceil($pager['data_cnt'] / $disp_cnt);
- if($pager['total_page'] < $pager['now_page']) {
- $pager['now_page'] = 1;
- }
- // link array {{
- if(($pager['now_page'] - MULTIMEDIA_FRONT_AND_BEHIND_LINK_CNT) > 0){
- $start = $pager['now_page'] - MULTIMEDIA_FRONT_AND_BEHIND_LINK_CNT;
- }else{
- $start = 1;
- }
- if(($pager['now_page'] + MULTIMEDIA_FRONT_AND_BEHIND_LINK_CNT) >= $pager['total_page']){
- $end = $pager['total_page'];
- }else{
- $end = $pager['now_page'] + MULTIMEDIA_FRONT_AND_BEHIND_LINK_CNT;
- }
- $i = 0;
- for($i = $start; $i <= $end; $i++){
- $pager['link_array'][] = $i;
- }
- // next link
- if($disp_cnt < $pager['data_cnt']){
- if($pager['now_page'] < $pager['total_page']){
- $pager['next_link'] = TRUE;
- }
- }
- // prev link
- if(1 < $pager['now_page']){
- $pager['prev_link'] = TRUE;
- }
- // begin disp number
- $pager['disp_begin'] = ($pager['now_page'] - 1) * $disp_cnt;
- // end disp number
- $tmp_cnt = $pager['now_page'] * $disp_cnt;
- $pager['disp_end'] = ($pager['data_cnt'] < $tmp_cnt) ? $pager['data_cnt'] : $tmp_cnt;
- }
-}
+_db =& $container->getComponent("DbObject");
+ $this->_request =& $container->getComponent("Request");
+ $this->_session =& $container->getComponent("Session");
+ }
+
+ /**
+ * 配置されている動画配信IDを取得する
+ *
+ * @return string 配置されている動画配信ID
+ * @access public
+ */
+ function &getCurrentMultimediaId() {
+ $params = array($this->_request->getParameter("block_id"));
+ $sql = "SELECT multimedia_id ".
+ "FROM {multimedia_block} ".
+ "WHERE block_id = ?";
+ $result = $this->_db->execute($sql, $params);
+ if ($result === false) {
+ $this->_db->addError();
+ return $result;
+ }
+
+ return $result[0]["multimedia_id"];
+ }
+
+ /**
+ * 現在登録されている動画配信IDを取得する
+ *
+ * @return string 配置されている動画配信ID
+ * @access pblic
+ */
+ function &getFirstMultimediaId() {
+ $params = array(
+ $this->_request->getParameter('room_id')
+ );
+ $sql = "SELECT multimedia_id "
+ . "FROM {multimedia} "
+ . "WHERE room_id = ?";
+ $result = $this->_db->execute($sql, $params, 1);
+ if ($result === false) {
+ $this->_db->addError();
+ return $result;
+ }
+
+ return $result[0]['multimedia_id'];
+ }
+
+ /**
+ * 動画配信が配置されているブロックデータを取得する
+ *
+ * @return string ブロックデータ
+ * @access public
+ */
+ function &getBlock() {
+ $params = array($this->_request->getParameter("multimedia_id"));
+ $sql = "SELECT M.room_id, B.block_id ".
+ "FROM {multimedia} M ".
+ "INNER JOIN {multimedia_block} B ".
+ "ON M.multimedia_id = B.multimedia_id ".
+ "WHERE M.multimedia_id = ? ".
+ "ORDER BY B.block_id";
+ $result = $this->_db->execute($sql, $params, 1);
+ if ($result === false) {
+ $this->_db->addError();
+ return $result;
+ }
+
+ return $result[0];
+ }
+
+ /**
+ * 動画配信が存在するか判断する
+ *
+ * @return boolean true:存在する、false:存在しない
+ * @access public
+ */
+ function multimediaExist() {
+ $params = array(
+ $this->_request->getParameter("multimedia_id"),
+ $this->_request->getParameter("room_id")
+ );
+ $sql = "SELECT multimedia_id ".
+ "FROM {multimedia} ".
+ "WHERE multimedia_id = ? ".
+ "AND room_id = ?";
+ $result = $this->_db->execute($sql, $params);
+ if ($result === false) {
+ $this->_db->addError();
+ return $result;
+ }
+
+ if (count($result) > 0) {
+ return true;
+ }
+
+ return false;
+ }
+
+ function getMultimediaCount() {
+ $params["room_id"] = $this->_request->getParameter("room_id");
+ $count = $this->_db->countExecute("multimedia", $params);
+ if($count === false) {
+ $this->_db->addError();
+ }
+
+ return $count;
+ }
+
+ /**
+ * 動画配信の設定データを取得する
+ *
+ * @return string 設定データ配列
+ * @access public
+ */
+ function &getConfig() {
+ $container =& DIContainerFactory::getContainer();
+ $configView =& $container->getComponent("configView");
+ $module_id = $this->_request->getParameter("module_id");
+ $config = $configView->getConfig($module_id, false);
+
+ return $config;
+ }
+
+ /**
+ * 動画配信用デフォルトデータを取得する
+ *
+ * @return array 動画配信用デフォルトデータ配列
+ * @access public
+ */
+ function &getDefaultMultimedia() {
+ $config = $this->getConfig();
+ if ($config === false) {
+ return $config;
+ }
+
+ $multimedia = array(
+ "album_authority" => constant($config['album_authority']['conf_value']),
+ "vote_flag" => constant($config['vote_flag']['conf_value']),
+ "comment_flag" => constant($config['comment_flag']['conf_value']),
+ "confirm_flag" => constant($config['confirm_flag']['conf_value']),
+ "display" => constant($config['display']['conf_value']),
+ "autoplay_flag" => constant($config['autoplay_flag']['conf_value']),
+ "buffer_time" => $config['buffer_time']['conf_value'],
+ "album_visible_row" => $config['album_visible_row']['conf_value'],
+ "new_period" => $config['new_period']['conf_value'],
+ "album_jacket" => $config['album_jacket']['conf_value']
+ );
+
+ return $multimedia;
+ }
+
+ /**
+ * 動画配信データを取得する
+ *
+ * @return array 動画配信データ
+ * @access public
+ */
+ function &getCurrentMultimedia() {
+ $params = array($this->_request->getParameter("block_id"));
+ $sql = "SELECT B.block_id, B.multimedia_id, B.display, ".
+ "B.autoplay_flag, B.buffer_time, ".
+ "B.album_visible_row, B.new_period, ".
+ "M.album_authority, M.vote_flag, M.comment_flag, M.confirm_flag ".
+ "FROM {multimedia_block} B ".
+ "INNER JOIN {multimedia} M ".
+ "ON B.multimedia_id = M.multimedia_id ".
+ "WHERE block_id = ?";
+ $result = $this->_db->execute($sql, $params);
+ if ($result === false) {
+ $this->_db->addError();
+ }
+ if (empty($result)) {
+ return $result;
+ }
+
+ $result[0]['album_authority'] = $this->_hasAlbumAuthority($result[0]);
+ $result[0]['new_period_time'] = $this->_getNewPeriodTime($result[0]['new_period']);
+
+ return $result[0];
+ }
+
+ /**
+ * アルバム作成権限を取得する
+ *
+ * @param array $photoalbum フォトアルバムデータ配列
+ * @return boolean true:権限有り、false:権限無し
+ * @access public
+ */
+ function _hasAlbumAuthority($multimedia) {
+ $auth_id = $this->_session->getParameter("_auth_id");
+ if ($auth_id >= $multimedia['album_authority']) {
+ return true;
+ }
+
+ return false;
+ }
+
+ function getMultimediaById($multimedia_id) {
+ $params = array(
+ "multimedia_id" => $multimedia_id
+ );
+
+ $result = $this->_db->selectExecute("multimedia", $params);
+ if ($result === false) {
+ $this->_db->addError();
+ }
+
+ if(!empty($result) && isset($result[0])) {
+ return $result[0];
+ }
+
+ return $result;
+ }
+
+ /**
+ * フォトアルバムデータを取得する
+ *
+ * @return array フォトアルバムデータ
+ * @access public
+ */
+ function &getMultimedia() {
+ $params = array($this->_request->getParameter("multimedia_id"));
+ $sql = "SELECT multimedia_id, album_authority, vote_flag, comment_flag, confirm_flag ".
+ "FROM {multimedia} ".
+ "WHERE multimedia_id = ?";
+ $result = $this->_db->execute($sql, $params);
+ if ($result === false) {
+ $this->_db->addError();
+ return $result;
+ }
+
+ return $result[0];
+ }
+
+ /**
+ * new記号表示期間から対象年月日を取得する
+ *
+ * @param string $new_period new記号表示期間
+ * @return string new記号表示対象年月日(YmdHis)
+ * @access public
+ */
+ function &_getNewPeriodTime($new_period) {
+ if (empty($new_period)) {
+ $new_period = -1;
+ }
+
+ $time = timezone_date();
+ $time = mktime(0, 0, 0,
+ intval(substr($time, 4, 2)),
+ intval(substr($time, 6, 2)) - $new_period,
+ intval(substr($time, 0, 4))
+ );
+ $time = date("YmdHis", $time);
+
+ return $time;
+ }
+
+ /**
+ * 動画配信のアルバムの計数を取得する
+ *
+ * @param string $new_period new記号表示期間
+ * @return string new記号表示対象年月日(YmdHis)
+ * @access public
+ */
+ function getAlbumCount($multimedia_id) {
+ $params[] = $multimedia_id;
+
+ $sql = "SELECT COUNT(*) as count ".
+ "FROM {multimedia_album} A ";
+ $sql .= $this->_getAuthorityFromSQL();
+ $sql .= "WHERE A.multimedia_id = ? ";
+ $sql .= $this->_getAuthorityWhereSQL($params);
+ if(!empty($order_params)) {
+ $sql .= $this->_db->getOrderSQL($order_params);
+ }
+ $result = $this->_db->execute($sql, $params);
+ if ( $result === false ) {
+ // エラーが発生した場合、エラーリストに追加
+ $this->_db->addError();
+ return $result;
+ }
+ return $result[0]['count'];
+ }
+
+ /**
+ * アルバム一覧を取得する
+ *
+ * @return array アルバム一覧データ
+ * @access public
+ */
+ function getAlbumList($multimedia_id, $order_params=null, $disp_cnt=null, $begin=null) {
+ $params[] = $multimedia_id;
+
+ $sql = "SELECT A.* ".
+ "FROM {multimedia_album} A ";
+ $sql .= $this->_getAuthorityFromSQL();
+ $sql .= "WHERE A.multimedia_id = ? ";
+ $sql .= $this->_getAuthorityWhereSQL($params);
+ if(!empty($order_params)) {
+ $sql .= $this->_db->getOrderSQL($order_params);
+ }
+ $result = $this->_db->execute($sql, $params, $disp_cnt, $begin, true, array($this, "_makeAlbumArray"));
+ if ( $result === false ) {
+ // エラーが発生した場合、エラーリストに追加
+ $this->_db->addError();
+ }
+
+ return $result;
+ }
+
+ /**
+ * アルバムデータ配列を生成する
+ *
+ * @param array $recordSet タスクADORecordSet
+ * @return array タスクデータ配列
+ * @access private
+ */
+ function &_makeAlbumArray(&$recordSet) {
+ $multimedia = $this->_request->getParameter("multimedia_obj");
+
+ $albums = array();
+ while ($row = $recordSet->fetchRow()) {
+ if (!empty($row["album_jacket"])) {
+ $row["jacket_style"] = $this->getImageStyle($row["width"], $row["height"], MULTIMEDIA_JACKET_WIDTH, MULTIMEDIA_JACKET_HEIGHT);
+ }
+
+ $row["edit_authority"] = false;
+ if ($multimedia["album_authority"]
+ && $this->_hasEditAuthority($row["insert_user_id"])) {
+ $row["edit_authority"] = true;
+ }
+
+ $albums[] = $row;
+ }
+
+ return $albums;
+ }
+
+ /**
+ * アルバムのサムネイルのスタイル属性値を取得する
+ *
+ * @param string $width 幅
+ * @param string $height 高さ
+ * @param string $maxWidth 最大幅
+ * @param string $maxHeight 最大高さ
+ * @return array 画像のスタイル属性値
+ * @access private
+ */
+ function &getImageStyle($width, $height, $maxWidth, $maxHeight) {
+ $ratio = $height / $width;
+
+ $widthRatio = $width / $maxWidth;
+ $heightRatio = $height / $maxHeight;
+
+ if ($widthRatio > $heightRatio) {
+ $height = $maxHeight;
+ $widht = intval($height / $ratio);
+ $top = 0;
+ $right = intval(($widht + $maxWidth) / 2);
+ $bottom = $maxHeight;
+ $left = intval(($widht - $maxWidth) / 2);
+ $marginLeft = $left * -1;
+ $marginTop = $top;
+ } else {
+ $widht = $maxWidth;
+ $height = intval($widht * $ratio);
+ $top = intval(($height - $maxHeight) / 2);
+ $right = $maxWidth;
+ $bottom = intval(($height + $maxHeight) / 2);
+ $left = 0;
+ $marginLeft = $left;
+ $marginTop = $top * -1;
+ }
+
+ $style = sprintf(MULTIMEDIA_THUMBNAIL_STYLE, $widht, $height, $top, $right, $bottom, $left, $marginLeft, $marginTop);
+
+ return $style;
+ }
+
+ /**
+ * アルバムを取得する
+ *
+ * @return array アルバムデータ
+ * @access public
+ */
+ function getAlbum($album_id) {
+ $params = array(
+ "album_id" => intval($album_id)
+ );
+
+ $result = $this->_db->selectExecute("multimedia_album", $params, null, null, null, array($this, "_makeAlbumArray"));
+ if ($result === false) {
+ $this->_db->addError();
+ }
+
+ if(!empty($result) && isset($result[0])) {
+ return $result[0];
+ }
+
+ return $result;
+ }
+
+ /**
+ * 動画を取得する
+ *
+ * @return array 動画データ
+ * @access public
+ */
+ function getItem($item_id) {
+ $params = array(
+ "item_id" => intval($item_id)
+ );
+
+ $result = $this->_db->selectExecute("multimedia_item", $params, null, null, null, array($this, "_makeItemArray"));
+ if ($result === false) {
+ $this->_db->addError();
+ }
+
+ if(!empty($result) && isset($result[0])) {
+ $result[0]['vote_authority'] = $this->_hasVoteAuthority($item_id);
+ $result[0]['comment_authority'] = $this->_hasCommentAuthority();
+ return $result[0];
+ }
+
+ return $result;
+ }
+
+ /**
+ * 編集権限を取得する
+ *
+ * @param array $insertUserID 登録者ID
+ * @return boolean true:権限有り、false:権限無し
+ * @access public
+ */
+ function _hasEditAuthority(&$insertUserID) {
+ $container =& DIContainerFactory::getContainer();
+
+ $authID = $this->_session->getParameter("_auth_id");
+ if ($authID >= _AUTH_CHIEF) {
+ return true;
+ }
+
+ $userID = $this->_session->getParameter("_user_id");
+ if ($insertUserID == $userID) {
+ return true;
+ }
+
+ $hierarchy = $this->_session->getParameter("_hierarchy");
+ $authCheck =& $container->getComponent("authCheck");
+ $insetUserHierarchy = $authCheck->getPageHierarchy($insertUserID);
+ if ($hierarchy > $insetUserHierarchy) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * 投票権限を取得する
+ *
+ * @param array $item 動画データ配列
+ * @return boolean true:権限有り、false:権限無し
+ * @access public
+ */
+ function _hasVoteAuthority($item_id) {
+ $multimedia = $this->_request->getParameter("multimedia_obj");
+ if ($multimedia['vote_flag'] != _ON) {
+ return false;
+ }
+
+ $votes = $this->_session->getParameter("multimedia_votes");
+ if (!empty($votes) && in_array($item_id, $votes)) {
+ return false;
+ }
+
+ $user_id = $this->_session->getParameter("_user_id");
+ if (empty($user_id)) {
+ return true;
+ }
+
+ $params = array(
+ $user_id,
+ $item_id
+ );
+ $sql = "SELECT vote_flag ".
+ "FROM {mutlimedia_user_item} ".
+ "WHERE user_id = ? ".
+ "AND item_id = ?";
+ $vote_flags = $this->_db->execute($sql, $params, null, null, false);
+ if ($vote_flags === false) {
+ $this->_db->addError();
+ return false;
+ }
+
+ if (empty($vote_flags) || $vote_flags[0][0] != _ON) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * コメント権限を取得する
+ *
+ * @return boolean true:権限有り、false:権限無し
+ * @access public
+ */
+ function _hasCommentAuthority() {
+ $multimedia = $this->_request->getParameter("multimedia_obj");
+ if ($multimedia['comment_flag'] != _ON) {
+ return false;
+ }
+
+ $auth_id = $this->_session->getParameter("_auth_id");
+ if ($auth_id <= _AUTH_GUEST) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * 動画のコメントの計数を取得する
+ *
+ * @param string $item_id 動画id
+ * @return string 動画のコメントの計数
+ * @access public
+ */
+ function getCommentCount($item_id) {
+ $params = array(
+ "item_id" => intval($item_id)
+ );
+ $commentCount = $this->_db->countExecute("multimedia_comment", $params);
+
+ if($commentCount === false) {
+ $this->_db->addError();
+ }
+
+ return $commentCount;
+ }
+
+ /**
+ * 動画のコメントを取得する
+ *
+ * @param string $item_id 動画id
+ * @return string 動画のコメント
+ * @access public
+ */
+ function getComments($item_id, $begin=null) {
+ $comments = $this->_db->selectExecute("multimedia_comment", array("item_id" => intval($item_id)), array("insert_time" => "DESC"), MULTIMEDIA_VISIBLE_ITEM_COMMENT, $begin, array($this, "_makeCommentArray"));
+ if($comments === false) {
+ $this->_db->addError();
+ }
+
+ return $comments;
+ }
+
+ /**
+ * コメントデータ配列を生成する
+ *
+ * @param array $recordSet タスクADORecordSet
+ * @return array タスクデータ配列
+ * @access private
+ */
+ function &_makeCommentArray(&$recordSet) {
+ $comments = array();
+ while ($row = $recordSet->fetchRow()) {
+ $row["edit_authority"] = false;
+ if ($this->_hasEditAuthority($row["insert_user_id"])) {
+ $row["edit_authority"] = true;
+ }
+
+ $comments[] = $row;
+ }
+
+ return $comments;
+ }
+
+ /**
+ * 画像の大きさを取得
+ *
+ * @return string 画像の大きさ
+ * @access public
+ */
+ function &getImageSize($image) {
+ if (is_numeric($image)) {
+ $container =& DIContainerFactory::getContainer();
+
+ $uploads =& $container->getComponent("uploadsView");
+ $uploadFiles = $uploads->getUploadById($image);
+ if (empty($uploadFiles)) {
+ return false;
+ }
+
+ $imageSize = getimagesize(FILEUPLOADS_DIR. "multimedia/". $uploadFiles[0]["physical_file_name"]);
+ } else {
+ $imageSize = getimagesize(HTDOCS_DIR.MULTIMEDIA_SAMPLR_JACKET_PATH.MULTIMEDIA_SAMPLR_JACKET_DIR.$image);
+ }
+
+ return $imageSize;
+ }
+
+ /**
+ * 権限判断用のSQL文FROM句を取得する
+ *
+ * @return string 権限判断用のSQL文FROM句
+ * @access public
+ */
+ function &_getAuthorityFromSQL() {
+ $auth_id = $this->_session->getParameter("_auth_id");
+
+ $sql = "";
+ if ($auth_id >= _AUTH_CHIEF) {
+ return $sql;
+ }
+
+ $sql .= "LEFT JOIN {pages_users_link} PU ".
+ "ON A.insert_user_id = PU.user_id ".
+ "AND A.room_id = PU.room_id ";
+ $sql .= "LEFT JOIN {authorities} AU ".
+ "ON PU.role_authority_id = AU.role_authority_id ";
+
+ return $sql;
+ }
+
+ /**
+ * 権限判断用のSQL文WHERE句を取得する
+ * パラメータ用配列に必要な値を追加する
+ *
+ * @param array $params パラメータ用配列
+ * @return string 権限判断用のSQL文WHERE句
+ * @access public
+ */
+ function &_getAuthorityWhereSQL(&$params) {
+ $auth_id = $this->_session->getParameter("_auth_id");
+
+ $sql = "";
+ if ($auth_id >= _AUTH_CHIEF) {
+ return $sql;
+ }
+
+ $sql .= " AND (A.public_flag = ? OR AU.hierarchy < ? OR A.insert_user_id = ? ";
+
+ $default_entry = $this->_session->getParameter("_default_entry_flag");
+ $hierarchy = $this->_session->getParameter("_hierarchy");
+ if ($default_entry == _ON && $hierarchy > $this->_session->getParameter("_default_entry_hierarchy")) {
+ $sql .= " OR AU.hierarchy IS NULL) ";
+ } else {
+ $sql .= ") ";
+ }
+
+ $params[] = _ON;
+ $params[] = $hierarchy;
+ $params[] = $this->_session->getParameter("_user_id");
+
+ return $sql;
+ }
+
+ /**
+ * 動画データ配列を生成する
+ *
+ * @param array $recordSet 動画ADORecordSet
+ * @return array 動画データ配列
+ * @access private
+ */
+ function &_makeItemArray(&$recordSet) {
+ $items = array();
+ while ($row = $recordSet->fetchRow()) {
+ $row['edit_authority'] = false;
+ if ($this->_hasEditAuthority($row['insert_user_id'])) {
+ $row['edit_authority'] = true;
+ }
+ $tags = $this->getTags($row['item_id']);
+ $row['item_tag'] = $this->_makeTagString($tags);
+ $row['duration'] = floor($row['duration']/60).":".floor(($row['duration']-60*floor($row['duration']/60)));
+ $items[] = $row;
+ }
+
+ return $items;
+ }
+
+ /**
+ * 動画一覧共通のSQL
+ *
+ * @return array 動画件数データ
+ * @access public
+ */
+ function _getItemListSQL(&$params, $where_params, $order_params=null, $count_flag=false) {
+ $sql = "";
+ if(empty($order_params)) {
+ $order_params = array(
+ "insert_time" => "DESC"
+ );
+ }
+
+ if($count_flag) {
+ $sql = "SELECT COUNT(T.item_id) as count FROM {multimedia_item} T ";
+ }else {
+ $sql = "SELECT T.* FROM {multimedia_item} T ";
+ }
+ $sql .= "LEFT JOIN {multimedia_album} A ON T.album_id=A.album_id ";
+ $sql .= $this->_getAuthorityFromSQL();
+ if(!empty($where_params)) {
+ foreach($where_params as $key => $val) {
+ if($val == "") {
+ continue;
+ }
+ $where_params["T.".$key] = $val;
+ unset($where_params[$key]);
+ }
+ $sql .= $this->_db->getWhereSQL($params, $where_params);
+ }
+ $sql .= $this->_getAuthorityWhereSQL($params);
+ if(!$count_flag) {
+ foreach($order_params as $key => $val) {
+ $order_params["T.".$key] = $val;
+ unset($order_params[$key]);
+ }
+ $sql .= $this->_db->getOrderSQL($order_params);
+ }
+
+ return $sql;
+ }
+
+ /**
+ * 動画一覧件数を取得する
+ *
+ * @return array 動画件数データ
+ * @access public
+ */
+ function getItemListCount($where_params) {
+ if(empty($where_params)) {
+ return false;
+ }
+
+ $sql = "";
+ $params = array();
+ $sql = $this->_getItemListSQL($params, $where_params, null, true);
+ $result = $this->_db->execute($sql, $params);
+ if ( $result === false ) {
+ // エラーが発生した場合、エラーリストに追加
+ $this->_db->addError();
+ return $result;
+ }
+ return $result[0]['count'];
+ }
+
+ /**
+ * 動画一覧を取得する
+ *
+ * @param int $multimedia_id ID
+ * @return array 動画データ
+ * @access public
+ */
+ function getItemList($where_params, $order_params, $begin=null) {
+ if(empty($where_params)) {
+ return false;
+ }
+
+ $sql = "";
+ $params = array();
+ $sql = $this->_getItemListSQL($params, $where_params, $order_params);
+
+ $result = $this->_db->execute($sql, $params ,MULTIMEDIA_VISIBLE_ITEM_CNT, $begin, true, array($this, "_makeItemArray"));
+ if ( $result === false ) {
+ // エラーが発生した場合、エラーリストに追加
+ $this->_db->addError();
+ return $result;
+ }
+ return $result;
+ }
+
+ /**
+ * 検索動画一覧を取得する
+ *
+ * @return array 動画データ
+ * @access public
+ */
+ function getSearchItemList($sql, $where_params, $begin=null) {
+ $result = $this->_db->execute($sql, $where_params ,MULTIMEDIA_SEARCH_VISIBLE_ITEM_CNT, $begin, true, array($this, "_makeItemArray"));
+ if ( $result === false ) {
+ // エラーが発生した場合、エラーリストに追加
+ $this->_db->addError();
+ }
+ return $result;
+ }
+
+ /**
+ * タグデータ配列を取得する
+ *
+ * @return array タグデータ配列
+ * @access public
+ */
+ function getTags($item_id) {
+ $sql = "SELECT R.tag_value, T.used_number, R.tag_id, R.item_id, R.sequence " .
+ "FROM {multimedia_item_tag} AS R, {multimedia_tag} AS T " .
+ "WHERE R.tag_id = T.tag_id " .
+ "AND R.item_id = ? " .
+ "ORDER BY R.sequence;";
+
+ $params = array(
+ $item_id
+ );
+ $tags = $this->_db->execute($sql, $params);
+ if ($tags === false) {
+ $this->_db->addError();
+ return false;
+ }
+ return $tags;
+ }
+
+ /**
+ * 関連動画配列を取得する
+ *
+ * @return array タグデータ配列
+ * @access public
+ */
+ function getSimilarItems($item_id) {
+ $tags = $this->getTags($item_id);
+ if(empty($tags)) {
+ return $tags;
+ }
+
+ $params = array();
+ $where_sql = "";
+ foreach($tags as $tag) {
+ $params[] = $tag['tag_id'];
+ $where_sql .= " G.tag_id=? OR";
+ }
+ $where_sql = " ( ".substr($where_sql, 0, -2)." ) ";
+ $sql = "SELECT T.*,count(*) as count " .
+ "FROM {multimedia_item_tag} AS G, {multimedia_item} AS T ";
+ $sql .= "LEFT JOIN {multimedia_album} A ON T.album_id=A.album_id ";
+ $sql .= $this->_getAuthorityFromSQL();
+ $sql .= "WHERE G.item_id=T.item_id AND T.item_id <> ".$item_id." AND ".$where_sql;
+ $sql .= $this->_getAuthorityWhereSQL($params);
+ $sql .= " GROUP BY T.item_id ORDER BY count DESC";
+ $items = $this->_db->execute($sql, $params, MULTIMEDIA_TAG_ITEMS_NUMBER, 0, true, array($this, "_makeItemArray"));
+ if ($items === false) {
+ $this->_db->addError();
+ return false;
+ }
+ return $items;
+ }
+
+ /**
+ * タグストリングを生成する
+ */
+ function &_makeTagString($tags) {
+ $string = "";
+ if(empty($tags)) {
+ return $string;
+ }
+ $string = "";
+ foreach($tags as $tag) {
+ $string .= $tag['tag_value'].MULTIMEDIA_TAG_SEPARATOR;
+ }
+ $string = substr($string, 0, -1);
+
+ return $string;
+ }
+
+ /**
+ * ページに関する設定を行います
+ *
+ * @param int disp_cnt 1ページ当り表示件数
+ * @param int now_page 現ページ
+ */
+ function setPageInfo(&$pager, $data_cnt, $disp_cnt, $now_page = NULL){
+ $pager['data_cnt'] = 0;
+ $pager['total_page'] = 0;
+ $pager['next_link'] = FALSE;
+ $pager['prev_link'] = FALSE;
+ $pager['disp_begin'] = 0;
+ $pager['disp_end'] = 0;
+ $pager['link_array'] = NULL;
+
+ if(empty($disp_cnt)) {
+ return false;
+ }
+
+ $pager['data_cnt'] = $data_cnt;
+ // now page
+ $pager['now_page'] = (NULL == $now_page) ? 1 : $now_page;
+ // total page
+ $pager['total_page'] = ceil($pager['data_cnt'] / $disp_cnt);
+ if($pager['total_page'] < $pager['now_page']) {
+ $pager['now_page'] = 1;
+ }
+ // link array {{
+ if(($pager['now_page'] - MULTIMEDIA_FRONT_AND_BEHIND_LINK_CNT) > 0){
+ $start = $pager['now_page'] - MULTIMEDIA_FRONT_AND_BEHIND_LINK_CNT;
+ }else{
+ $start = 1;
+ }
+ if(($pager['now_page'] + MULTIMEDIA_FRONT_AND_BEHIND_LINK_CNT) >= $pager['total_page']){
+ $end = $pager['total_page'];
+ }else{
+ $end = $pager['now_page'] + MULTIMEDIA_FRONT_AND_BEHIND_LINK_CNT;
+ }
+ $i = 0;
+ for($i = $start; $i <= $end; $i++){
+ $pager['link_array'][] = $i;
+ }
+ // next link
+ if($disp_cnt < $pager['data_cnt']){
+ if($pager['now_page'] < $pager['total_page']){
+ $pager['next_link'] = TRUE;
+ }
+ }
+ // prev link
+ if(1 < $pager['now_page']){
+ $pager['prev_link'] = TRUE;
+ }
+ // begin disp number
+ $pager['disp_begin'] = ($pager['now_page'] - 1) * $disp_cnt;
+ // end disp number
+ $tmp_cnt = $pager['now_page'] * $disp_cnt;
+ $pager['disp_end'] = ($pager['data_cnt'] < $tmp_cnt) ? $pager['data_cnt'] : $tmp_cnt;
+ }
+}
?>
\ No newline at end of file
diff --git a/multimedia/config/main.ini b/multimedia/config/main.ini
index 6b4517e..65e8da9 100644
--- a/multimedia/config/main.ini
+++ b/multimedia/config/main.ini
@@ -16,6 +16,7 @@ define:MULTIMEDIA_EXTENSION = "ffmpeg"
define:MULTIMEDIA_MOVIE_THUMBNAIL_WIDTH = 120
define:MULTIMEDIA_MOVIE_THUMBNAIL_HEIGHT = 90
define:MULTIMEDIA_MOVIE_THUMBNAIL_NAME = "_thumbnail.jpg"
+define:MULTIMEDIA_MOVIE_CAPTUER_NAME = "_temp.jpg"
define:MULTIMEDIA_MOVIE_THUMBNAIL_ROW_NUMBER = 4
define:MULTIMEDIA_MOVIE_TYPE_NEW = "new"
define:MULTIMEDIA_MOVIE_TYPE_POP = "pop"
@@ -37,7 +38,14 @@ define:MULTIMEDIA_TAG_SEPARATOR = ","
define:MULTIMEDIA_TAG_ITEMS_NUMBER = 6
define:MULTIMEDIA_MOVIE_PLAYER_WIDTH = 504
define:MULTIMEDIA_MOVIE_PLAYER_HEIGHT = 290
+define:MULTIMEDIA_MOVIE_PLAYER_CONTROLLER_HEIGHT = 24 ;sv
+define:MULTIMEDIA_MOVIE_PLAYER_EMBEDED_WIDTH = 400
+define:MULTIMEDIA_MOVIE_PLAYER_EMBEDED_HEIGHT = 300
define:MULTIMEDIA_GET_FLASH_LINK = "http://www.adobe.com/go/getflashplayer"
define:MULTIMEDIA_GET_FLASH_ICON = "http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif"
define:MULTIMEDIA_VISIBLE_ITEM_COMMENT = 5
-define:MULTIMEDIA_SEARCH_VISIBLE_ITEM_CNT = 5
\ No newline at end of file
+define:MULTIMEDIA_SEARCH_VISIBLE_ITEM_CNT = 5
+define:MULTIMEDIA_FFMPEG_PATH = "/usr/bin/ffmpeg"
+define:MULTIMEDIA_FFMPEG_OPTION = "-acodec libfaac -ar 44100 -vcodec libx264 -vpre medium -r 30 -b 500k"
+define:MULTIMEDIA_MP4BOX_PATH = "/usr/local/bin/MP4Box"
+define:MULTIMEDIA_THUMBNAIL_SECONDS = 10
diff --git a/multimedia/files/css/default/style.css b/multimedia/files/css/default/style.css
index 2e7a62e..bd2b71c 100644
--- a/multimedia/files/css/default/style.css
+++ b/multimedia/files/css/default/style.css
@@ -589,4 +589,537 @@ div.multimedia_search_title {
}
.multimedia_upload_table_td{
width:260px;
-}
\ No newline at end of file
+}
+.multimedia_player_background{
+ border:1px solid #bbb;
+}
+.multimedia_player_thumbnail{
+ width:100%;
+ height:100%;
+}
+.multimedia_player_error_block{
+ position:absolute;
+ margin-top:-27px;
+ height:26px;
+ background-color:#000;
+ border-top:1px solid #bbb;
+}
+.multimedia_player_error_detail{
+ margin:5px;
+ font-size:13px;
+ color:#fff;
+}
+
+/* 以下、動画プレイヤー用 */
+div.jp-video {
+ font-size:1.25em; /* 1.25em for testing in site pages */ /* No parent CSS that can effect the size in the demos ZIP */
+ font-family:Verdana, Arial, sans-serif;
+ line-height:1.6;
+ color: #000;
+ background-color:#eee;
+}
+
+div.jp-video-embeded {
+ width:400px; /* 幅を変更する場合はここを修正 */
+}
+div.jp-video-normal {
+ width:504px; /* 幅を変更する場合はここを修正 */
+}
+div.jp-video-full {
+ position:static !important; position:relative
+}
+
+div.jp-video-full div div {
+ z-index:1000;
+}
+
+div.jp-video-full div.jp-jplayer {
+ top: 0;
+ left: 0;
+ position: fixed !important; position: relative;
+ overflow: hidden;
+}
+
+div.jp-video-full div.jp-gui {
+ position: fixed !important; position: static;
+ top: 0;
+ left: 0;
+ width:100%;
+ height:100%;
+ z-index:1001;
+}
+
+div.jp-video-full div.jp-interface {
+ position: absolute !important; position: relative;
+ bottom: 0;
+ left: 0;
+}
+
+div.jp-gui div.jp-interface {
+ position: relative;
+ background-color:#eee;
+ width:100%;
+ margin-top: -21px;
+}
+
+div.jp-video div.jp-interface {
+}
+
+/* @group CONTROLS */
+
+div.jp-controls-holder {
+ clear: both;
+ margin:0 auto;
+ position: relative;
+ overflow:hidden;
+ height:18px;
+ background: url("<{$smarty.const.CORE_BASE_URL}>/images/multimedia/jplayer/jplayer.netcommons.jpg") 0 -101px repeat-x;
+ border-left: 1px solid #bbb;
+ border-right: 1px solid #bbb;
+}
+
+div.jp-interface ul.jp-controls {
+ list-style-type:none;
+ margin:0;
+ padding: 0;
+ overflow:hidden;
+}
+
+div.jp-interface ul.jp-controls-left {
+ list-style-type:none;
+ margin:0;
+ padding: 0;
+ overflow:hidden;
+ margin-top: 1px;
+}
+
+div.jp-interface ul.jp-controls-right {
+ list-style-type:none;
+ margin:0;
+ padding: 0;
+ overflow:hidden;
+ margin-top: 1px;
+}
+
+div.jp-video div.jp-type-single ul.jp-controls {
+ width: 78px;
+ margin-left: 200px;
+}
+
+div.jp-video div.jp-type-single ul.jp-controls-left {
+}
+
+div.jp-video div.jp-type-single ul.jp-controls-right {
+}
+
+div.jp-video ul.jp-controls,
+div.jp-interface ul.jp-controls li {
+ display:inline;
+ float: left;
+}
+
+div.jp-video ul.jp-controls-left,
+div.jp-interface ul.jp-controls-left li {
+ display:inline;
+ float: left;
+}
+
+div.jp-video ul.jp-controls-right,
+div.jp-interface ul.jp-controls-right li {
+ display:inline;
+ float: right;
+}
+
+div.jp-interface ul.jp-controls a {
+ display:block;
+ overflow:hidden;
+ text-indent:-9999px;
+}
+
+div.jp-interface ul.jp-controls-left a {
+ display:block;
+ overflow:hidden;
+ text-indent:-9999px;
+}
+
+div.jp-interface ul.jp-controls-right a {
+ display:block;
+ overflow:hidden;
+ text-indent:-9999px;
+}
+
+a.jp-play,
+a.jp-pause {
+ width: 15px;
+ height: 15px;
+}
+
+a.jp-play {
+ background: url("<{$smarty.const.CORE_BASE_URL}>/images/multimedia/jplayer/jplayer.netcommons.jpg") 0 0 no-repeat;
+ margin-left: 6px;
+}
+a.jp-play:hover {
+ background: url("<{$smarty.const.CORE_BASE_URL}>/images/multimedia/jplayer/jplayer.netcommons.jpg") -17px 0 no-repeat;
+}
+a.jp-pause {
+ background: url("<{$smarty.const.CORE_BASE_URL}>/images/multimedia/jplayer/jplayer.netcommons.jpg") 0 -16px no-repeat;
+ margin-left: 6px;
+ display: none;
+}
+a.jp-pause:hover {
+ background: url("<{$smarty.const.CORE_BASE_URL}>/images/multimedia/jplayer/jplayer.netcommons.jpg") -17px -16px no-repeat;
+}
+
+a.jp-stop {
+ display: none;
+}
+
+/* @group progress bar */
+
+div.jp-progress {
+ overflow:hidden;
+ background-color: #ddd;
+}
+
+div.jp-video div.jp-progress {
+ top:0px;
+ left:0px;
+ width:100%;
+ height:3px;
+}
+div.jp-seek-bar {
+ background: url("<{$smarty.const.CORE_BASE_URL}>/images/multimedia/jplayer/jplayer.netcommons.jpg") 0 -81px repeat-x;
+ width:0px;
+ height:100%;
+ cursor: pointer;
+}
+div.jp-play-bar {
+ background: url("<{$smarty.const.CORE_BASE_URL}>/images/multimedia/jplayer/jplayer.netcommons.jpg") 0 -85px repeat-x ;
+ width:0px;
+ height:100%;
+}
+
+div.jp-seeking-bg {
+ background: url("jplayer/jplayer.blue.monday.seeking.gif");
+}
+
+/* @group volume controls */
+
+a.jp-mute,
+a.jp-unmute,
+a.jp-volume-max {
+ width:16px;
+ height:15px;
+ margin-left: 3px;
+}
+
+div.jp-video a.jp-mute,
+div.jp-video a.jp-unmute,
+div.jp-video a.jp-volume-max {
+}
+
+div.jp-video a.jp-mute,
+div.jp-video a.jp-unmute {
+ left: 50px;
+}
+
+div.jp-video a.jp-volume-max {
+ left: 134px;
+}
+
+a.jp-mute {
+ background: url("<{$smarty.const.CORE_BASE_URL}>/images/multimedia/jplayer/jplayer.netcommons.jpg") 0 -48px no-repeat;
+}
+a.jp-mute:hover {
+ background: url("<{$smarty.const.CORE_BASE_URL}>/images/multimedia/jplayer/jplayer.netcommons.jpg") -17px -48px no-repeat;
+}
+a.jp-unmute {
+ background: url("<{$smarty.const.CORE_BASE_URL}>/images/multimedia/jplayer/jplayer.netcommons.jpg") 0 -32px no-repeat;
+ display: none;
+}
+a.jp-unmute:hover {
+ background: url("<{$smarty.const.CORE_BASE_URL}>/images/multimedia/jplayer/jplayer.netcommons.jpg") -17px -32px no-repeat;
+}
+
+a.jp-volume-max {
+ background: url("<{$smarty.const.CORE_BASE_URL}>/images/multimedia/jplayer/jplayer.netcommons.jpg") 0 -32px no-repeat;
+}
+a.jp-volume-max:hover {
+ background: url("<{$smarty.const.CORE_BASE_URL}>/images/multimedia/jplayer/jplayer.netcommons.jpg") -17px -32px no-repeat;
+}
+
+div.jp-volume-bar {
+ overflow:hidden;
+ background: url("<{$smarty.const.CORE_BASE_URL}>/images/multimedia/jplayer/jplayer.netcommons.jpg") 0 -89px repeat-x;
+ width:100px;
+ height:5px;
+ cursor: pointer;
+ margin-top: 5px;
+ margin-left:3px;
+}
+
+div.jp-video div.jp-volume-bar {
+}
+div.jp-volume-bar-value {
+ background: url("<{$smarty.const.CORE_BASE_URL}>/images/multimedia/jplayer/jplayer.netcommons.jpg") 0 -95px repeat-x;
+ width:0px;
+ height:5px;
+}
+
+/* @group current time and duration */
+
+div.jp-audio div.jp-time-holder {
+ position:absolute;
+ top:50px;
+}
+div.jp-audio div.jp-type-single div.jp-time-holder {
+ left:110px;
+ width:186px;
+}
+div.jp-audio div.jp-type-playlist div.jp-time-holder {
+ left:166px;
+ width:130px;
+}
+
+div.jp-current-time,
+div.jp-duration {
+ font-size: 9px;
+}
+div.jp-current-time {
+}
+div.jp-duration {
+}
+
+div.jp-video div.jp-current-time {
+ margin-left: 5px;
+}
+div.jp-video div.jp-duration {
+ margin-left: 5px;
+}
+
+/* @group playlist */
+
+div.jp-title {
+ font-weight:bold;
+ text-align:center;
+}
+
+div.jp-title,
+div.jp-playlist {
+ width:100%;
+ background-color:#ccc;
+ border-top:1px solid #009be3;
+}
+div.jp-type-single div.jp-title,
+div.jp-type-playlist div.jp-title,
+div.jp-type-single div.jp-playlist {
+ border-top:none;
+}
+div.jp-title ul,
+div.jp-playlist ul {
+ list-style-type:none;
+ margin:0;
+ padding:0 20px;
+ font-size:.72em;
+}
+
+div.jp-title li {
+ padding:5px 0;
+ font-weight:bold;
+}
+div.jp-playlist li {
+ padding:5px 0 4px 20px;
+ border-bottom:1px solid #eee;
+}
+
+div.jp-playlist li div {
+ display:inline;
+}
+
+div.jp-type-playlist div.jp-playlist li:last-child {
+ padding:5px 0 5px 20px;
+ border-bottom:none;
+}
+div.jp-type-playlist div.jp-playlist li.jp-playlist-current {
+ list-style-type:square;
+ list-style-position:inside;
+ padding-left:7px;
+}
+div.jp-type-playlist div.jp-playlist a {
+ color: #333;
+ text-decoration: none;
+}
+div.jp-type-playlist div.jp-playlist a:hover {
+ color:#0d88c1;
+}
+div.jp-type-playlist div.jp-playlist a.jp-playlist-current {
+ color:#0d88c1;
+}
+
+div.jp-type-playlist div.jp-playlist a.jp-playlist-item-remove {
+ float:right;
+ display:inline;
+ text-align:right;
+ margin-right:10px;
+ font-weight:bold;
+ color:#666;
+}
+div.jp-type-playlist div.jp-playlist a.jp-playlist-item-remove:hover {
+ color:#0d88c1;
+}
+div.jp-type-playlist div.jp-playlist span.jp-free-media {
+ float:right;
+ display:inline;
+ text-align:right;
+ margin-right:10px;
+}
+div.jp-type-playlist div.jp-playlist span.jp-free-media a{
+ color:#666;
+}
+div.jp-type-playlist div.jp-playlist span.jp-free-media a:hover{
+ color:#0d88c1;
+}
+span.jp-artist {
+ font-size:.8em;
+ color:#666;
+}
+
+/* @end */
+
+div.jp-video-play {
+ width:100%;
+ overflow:hidden;
+ cursor:pointer;
+ background-color:rgba(0,0,0,0);
+}
+div.jp-video-embeded div.jp-video-play {
+ /* 高さを変更する場合はここを修正 */
+ margin-top:-300px;
+ height:300px;
+}
+div.jp-video-normal div.jp-video-play {
+ /* 高さを変更する場合はここを修正 */
+ margin-top:-290px;
+ height:290px;
+}
+div.jp-video-full div.jp-video-play {
+ height:100%;
+}
+a.jp-video-play-icon {
+ position:relative;
+ display:block;
+ width: 80px;
+ height: 80px;
+ margin-left:-40px;
+ margin-top:-40px;
+ left:50%;
+ top:50%;
+ background: url("jplayer/jplayer.netcommons.video.play.png") 0 0 no-repeat;
+ text-indent:-9999px;
+}
+
+div.jp-video-full a.jp-video-play-icon {
+ position:absolute;
+ z-index:1002;
+}
+
+div.jp-jplayer {
+ width:0px;
+ height:0px;
+}
+
+div.jp-jplayer {
+ background-color: #000000;
+ border:1px solid #bbb;
+}
+
+/* @group TOGGLES */
+
+ul.jp-toggles {
+ list-style-type:none;
+ padding:0;
+ margin:0 auto;
+ overflow:hidden;
+}
+
+div.jp-video ul.jp-toggles {
+ margin-top:10px;
+ width:100px;
+}
+
+ul.jp-toggles li {
+ display:block;
+ float:right;
+}
+
+ul.jp-toggles li a {
+ display:block;
+ width:25px;
+ height:18px;
+ text-indent:-9999px;
+ line-height:100%;
+}
+
+a.jp-full-screen {
+ background: url("<{$smarty.const.CORE_BASE_URL}>/images/multimedia/jplayer/jplayer.netcommons.jpg") 0 -64px no-repeat;
+ width: 16px;
+ height: 15px;
+ margin-left: 5px;
+ margin-right: 5px;
+}
+
+a.jp-full-screen:hover {
+ background: url("<{$smarty.const.CORE_BASE_URL}>/images/multimedia/jplayer/jplayer.netcommons.jpg") -17px -64px no-repeat;
+}
+
+a.jp-restore-screen {
+ background: url("<{$smarty.const.CORE_BASE_URL}>/images/multimedia/jplayer/jplayer.netcommons.jpg") 0 -64px no-repeat;
+ width: 16px;
+ height: 15px;
+ margin-left: 5px;
+ margin-right: 5px;
+}
+
+a.jp-restore-screen:hover {
+ background: url("<{$smarty.const.CORE_BASE_URL}>/images/multimedia/jplayer/jplayer.netcommons.jpg") -17px -64px no-repeat;
+}
+
+a.jp-repeat {
+ display: none;
+}
+
+a.jp-repeat-off {
+ display: none;
+}
+
+a.jp-shuffle {
+ display: none;
+}
+
+a.jp-shuffle-off {
+ display: none;
+}
+
+/* @group NO SOLUTION error feedback */
+
+.jp-no-solution {
+ padding:5px;
+ font-size:.8em;
+ background-color:#eee;
+ border:2px solid #009be3;
+ color:#000;
+ display:none;
+}
+
+.jp-no-solution a {
+ color:#000;
+}
+
+.jp-no-solution span {
+ font-size:1em;
+ display:block;
+ text-align:center;
+ font-weight:bold;
+}
+
+/* @end */
diff --git a/multimedia/files/images/Jplayer.swf b/multimedia/files/images/Jplayer.swf
new file mode 100644
index 0000000000000000000000000000000000000000..aca11a5a77693bc51ddae1dfd4f95445050724b8
GIT binary patch
literal 13674
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ℓpX&2OkYc~q){sjB{nnsLClUxPCB9KZn;AG
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
IKL9atIeJ-FWdHyG
literal 0
HcmV?d00001
diff --git a/multimedia/files/images/jplayer/jplayer.blue.monday.jpg b/multimedia/files/images/jplayer/jplayer.blue.monday.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..adab53ff7b6ea893972ce1f2c24323d319b8e5ea
GIT binary patch
literal 23189
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