diff --git a/app/Models/SearchBox.php b/app/Models/SearchBox.php index 57aa575e..5a5ddff7 100644 --- a/app/Models/SearchBox.php +++ b/app/Models/SearchBox.php @@ -2,6 +2,8 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Casts\Attribute; + class SearchBox extends NexusModel { protected $table = 'searchbox'; @@ -33,6 +35,21 @@ class SearchBox extends NexusModel return $result; } + public function getCustomFieldsAttribute($value): array + { + if (!is_array($value)) { + return explode(',', $value); + } + } + + public function setCustomFieldsAttribute($value) + { + if (is_array($value)) { + $this->attributes['custom_fields'] = implode(',', $value); + } + } + + public function categories(): \Illuminate\Database\Eloquent\Relations\HasMany { return $this->hasMany(Category::class, 'mode'); diff --git a/app/Models/TorrentCustomField.php b/app/Models/TorrentCustomField.php new file mode 100644 index 00000000..98068da2 --- /dev/null +++ b/app/Models/TorrentCustomField.php @@ -0,0 +1,15 @@ +privacy == "strong" || ($torrent && $torrent->anonymous == 'yes' && $user->id == $torrent->owner)) { //用户强私密,或者种子作者匿名而当前项作者刚好为种子作者 + $anonymousText = nexus_trans('label.anonymous'); if($authenticator->class >= $canViewAnonymousClass || $user->id == $authenticator->id) { //但当前用户权限可以查看匿名者,或当前用户查看自己的数据,显示个匿名,后边加真实用户名 - return sprintf('匿名(%s)', $username); + return sprintf('%s(%s)', $anonymousText, $username); } else { - return '匿名'; + return $anonymousText; } } else { return $username; diff --git a/database/migrations/2022_09_19_043749_add_display_to_torrents_custom_fields_table.php b/database/migrations/2022_09_19_043749_add_display_to_torrents_custom_fields_table.php new file mode 100644 index 00000000..315d4abe --- /dev/null +++ b/database/migrations/2022_09_19_043749_add_display_to_torrents_custom_fields_table.php @@ -0,0 +1,33 @@ +text('display')->nullable(true)->after('help'); + $table->integer('priority')->default(0)->after('display'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('torrents_custom_fields', function (Blueprint $table) { + $table->dropColumn('display', 'priority'); + }); + } +}; diff --git a/include/constants.php b/include/constants.php index 77346b6d..b83eced9 100644 --- a/include/constants.php +++ b/include/constants.php @@ -1,6 +1,6 @@ '横向多选', 'field_type_select' => '下拉单选', 'field_type_image' => '图片', + 'col_display' => '自定义展示', -]; \ No newline at end of file +]; diff --git a/lang/cht/lang_fields.php b/lang/cht/lang_fields.php index 8e3eea26..096544b9 100644 --- a/lang/cht/lang_fields.php +++ b/lang/cht/lang_fields.php @@ -25,5 +25,6 @@ $lang_fields = [ 'field_type_radio' => '橫向單選', 'field_type_checkbox' => '橫向多選', 'field_type_select' => '下拉單選', + 'col_display' => '自定義展示', -]; \ No newline at end of file +]; diff --git a/lang/en/lang_fields.php b/lang/en/lang_fields.php index d3bddc60..f0829af1 100644 --- a/lang/en/lang_fields.php +++ b/lang/en/lang_fields.php @@ -26,5 +26,6 @@ $lang_fields = [ 'field_type_checkbox' => 'Horizontal multiple select', 'field_type_select' => 'Vertical single select', 'field_type_image' => 'Image', + 'col_display' => 'Custom display', -]; \ No newline at end of file +]; diff --git a/nexus/Field/Field.php b/nexus/Field/Field.php index a467dc3b..8ca7cc18 100644 --- a/nexus/Field/Field.php +++ b/nexus/Field/Field.php @@ -2,6 +2,10 @@ namespace Nexus\Field; +use App\Models\SearchBox; +use App\Models\TorrentCustomField; +use App\Models\TorrentCustomFieldValue; +use Elasticsearch\Endpoints\Search; use Nexus\Database\NexusDB; class Field @@ -86,7 +90,7 @@ class Field function buildFieldForm(array $row = []) { - global $lang_fields, $lang_functions; + global $lang_fields, $lang_functions, $lang_catmanage; $trName = tr($lang_fields['col_name'] . '*', '  ' . $lang_fields['col_name_help'], 1, '', true); $trLabel = tr($lang_fields['col_label'] . '*', '', 1, '', true); $trType = tr($lang_fields['col_type'] . '*', $this->radio('type', $this->getTypeRadioOptions(), $row['type'] ?? null), 1, '', true); @@ -94,6 +98,9 @@ class Field $trHelp = tr($lang_fields['col_help'], '', 1, '', true); $trOptions = tr($lang_fields['col_options'], '
' . $lang_fields['col_options_help'], 1, '', true); $trIsSingleRow = tr($lang_fields['col_is_single_row'] . '*', $this->radio('is_single_row', ['0' => $lang_functions['text_no'], '1' => $lang_functions['text_yes']], $row['is_single_row'] ?? null), 1, '', true); + $trPriority = tr(nexus_trans('label.priority') . '*', '', 1, '', true); + $trDisplay = tr($lang_fields['col_display'], '
' . $lang_catmanage['row_custom_field_display_help'], 1, '', true); + $id = $row['id'] ?? 0; $form = << @@ -109,6 +116,8 @@ class Field {$trHelp} {$trOptions} {$trIsSingleRow} + {$trPriority} + {$trDisplay}
@@ -126,7 +135,7 @@ HTML; $perPage = 10; $total = get_row_count('torrents_custom_fields'); list($paginationTop, $paginationBottom, $limit) = pager($perPage, $total, "?"); - $sql = "select * from torrents_custom_fields order by id asc $limit"; + $sql = "select * from torrents_custom_fields order by priority desc $limit"; $res = sql_query($sql); $header = [ 'id' => $lang_fields['col_id'], @@ -135,6 +144,7 @@ HTML; 'type_text' => $lang_fields['col_type'], 'required_text' => $lang_fields['col_required'], 'is_single_row_text' => $lang_fields['col_is_single_row'], + 'priority' => nexus_trans('label.priority'), 'action' => $lang_fields['col_action'], ]; $rows = []; @@ -203,6 +213,8 @@ HEAD; $attributes['help'] = $data['help'] ?? ''; $attributes['options'] = trim($data['options'] ?? ''); + $attributes['display'] = trim($data['display'] ?? ''); + $attributes['priority'] = trim($data['priority'] ?? '0'); $now = date('Y-m-d H:i:s'); $attributes['updated_at'] = $now; $table = 'torrents_custom_fields'; @@ -252,24 +264,29 @@ HEAD; } - public function renderOnUploadPage($torrentId = 0) + public function renderOnUploadPage($torrentId = 0, $searchBoxId) { - global $browsecatmode; - $searchBox = NexusDB::getOne('searchbox', "id = $browsecatmode"); + $searchBox = NexusDB::getOne('searchbox', "id = $searchBoxId"); if (empty($searchBox)) { - throw new \RuntimeException("Invalid search box: $browsecatmode"); + throw new \RuntimeException("Invalid search box: $searchBoxId"); } - $customValues = $this->listTorrentCustomField($torrentId); - $sql = sprintf('select * from torrents_custom_fields where id in (%s)', $searchBox['custom_fields'] ?: 0); + $customValues = $this->listTorrentCustomField($torrentId, $searchBoxId); + $sql = sprintf('select * from torrents_custom_fields where id in (%s) order by priority desc', $searchBox['custom_fields'] ?: 0); $res = sql_query($sql); $html = ''; while ($row = mysql_fetch_assoc($res)) { - $name = "custom_fields[{$row['id']}]"; + $name = "custom_fields[$searchBoxId][{$row['id']}]"; $currentValue = $customValues[$row['id']]['custom_field_value'] ?? ''; + $requireText = ''; + if ($row['required']) { + $requireText = "*"; + } + $trLabel = $row['label'] . $requireText; + $trRelation = "mode_$searchBoxId"; if ($row['type'] == self::TYPE_TEXT) { - $html .= tr($row['label'], sprintf('', $name, $currentValue, '99%'), 1); + $html .= tr($trLabel, sprintf('', $name, $currentValue, '99%'), 1, $trRelation); } elseif ($row['type'] == self::TYPE_TEXTAREA) { - $html .= tr($row['label'], sprintf('', $name, '99%', $currentValue), 1); + $html .= tr($trLabel, sprintf('', $name, '99%', $currentValue), 1, $trRelation); } elseif ($row['type'] == self::TYPE_RADIO || $row['type'] == self::TYPE_CHECKBOX) { if ($row['type'] == self::TYPE_CHECKBOX) { $name .= '[]'; @@ -293,7 +310,7 @@ HEAD; $row['type'], $name, $value, $checked, $label ); } - $html .= tr($row['label'], $part, 1); + $html .= tr($trLabel, $part, 1, $trRelation); } elseif ($row['type'] == self::TYPE_SELECT) { $part = ''; - $html .= tr($row['label'], $part, 1); + $html .= tr($trLabel, $part, 1, $trRelation); } elseif ($row['type'] == self::TYPE_IMAGE) { $callbackFunc = "preview_custom_field_image_" . $row['id']; $iframeId = "iframe_$callbackFunc"; @@ -351,18 +368,14 @@ HEAD; } JS; - $html .= tr($row['label'], $y, 1); + $html .= tr($trLabel, $y, 1, $trRelation, true); } } return $html; } - public function listTorrentCustomField($torrentId, $searchBoxId = 0) + public function listTorrentCustomField($torrentId, $searchBoxId) { - global $browsecatmode; - if ($searchBoxId <= 0) { - $searchBoxId = $browsecatmode; - } //suppose torrentId is array $isArray = true; $torrentIdArr = $torrentId; @@ -371,7 +384,7 @@ JS; $torrentIdArr = [$torrentId]; } $torrentIdStr = implode(',', $torrentIdArr); - $res = sql_query("select f.*, v.custom_field_value, v.torrent_id from torrents_custom_field_values v inner join torrents_custom_fields f on v.custom_field_id = f.id inner join searchbox box on box.id = $searchBoxId and find_in_set(f.id, box.custom_fields) where torrent_id in ($torrentIdStr)"); + $res = sql_query("select f.*, v.custom_field_value, v.torrent_id from torrents_custom_field_values v inner join torrents_custom_fields f on v.custom_field_id = f.id inner join searchbox box on box.id = $searchBoxId and find_in_set(f.id, box.custom_fields) where torrent_id in ($torrentIdStr) order by f.priority desc"); $values = []; $result = []; while ($row = mysql_fetch_assoc($res)) { @@ -402,12 +415,11 @@ JS; return $isArray ? $result : ($result[$torrentId] ?? []); } - public function renderOnTorrentDetailsPage($torrentId) + public function renderOnTorrentDetailsPage($torrentId, $searchBoxId) { - global $browsecatmode; - $displayName = get_searchbox_value($browsecatmode, 'custom_fields_display_name'); - $customFields = $this->listTorrentCustomField($torrentId); - $mixedRowContent = get_searchbox_value($browsecatmode, 'custom_fields_display'); + $displayName = get_searchbox_value($searchBoxId, 'custom_fields_display_name'); + $customFields = $this->listTorrentCustomField($torrentId, $searchBoxId); + $mixedRowContent = get_searchbox_value($searchBoxId, 'custom_fields_display'); $rowByRowHtml = ''; $shouldRenderMixRow = false; foreach ($customFields as $field) { @@ -422,8 +434,15 @@ JS; $mixedRowContent = str_replace("<%{$field['name']}.label%>", $field['label'], $mixedRowContent); $mixedRowContent = str_replace("<%{$field['name']}.value%>", $contentNotFormatted, $mixedRowContent); if ($field['is_single_row']) { - $contentFormatted = $this->formatCustomFieldValue($field, true); - $rowByRowHtml .= tr($field['label'], $contentFormatted, 1); + if (!empty($field['display'])) { + $customFieldDisplay = $field['display']; + $customFieldDisplay = str_replace("<%{$field['name']}.label%>", $field['label'], $customFieldDisplay); + $customFieldDisplay = str_replace("<%{$field['name']}.value%>", $contentNotFormatted, $customFieldDisplay); + $rowByRowHtml .= tr($field['label'], format_comment($customFieldDisplay, false), 1); + } else { + $contentFormatted = $this->formatCustomFieldValue($field, true); + $rowByRowHtml .= tr($field['label'], $contentFormatted, 1); + } } } @@ -443,13 +462,13 @@ JS; switch ($customFieldWithValue['type']) { case self::TYPE_TEXT: case self::TYPE_TEXTAREA: - $result .= $doFormatComment ? format_comment($fieldValue) : $fieldValue; + $result .= $doFormatComment ? format_comment($fieldValue, false) : $fieldValue; break; case self::TYPE_IMAGE: if (substr($fieldValue, 0, 4) == 'http') { $result .= $doFormatComment ? formatImg($fieldValue, true, 700, 0, "attach{$customFieldWithValue['id']}") : $fieldValue; } else { - $result .= $doFormatComment ? format_comment($fieldValue) : $fieldValue; + $result .= $doFormatComment ? format_comment($fieldValue, false) : $fieldValue; } break; case self::TYPE_RADIO: @@ -492,6 +511,32 @@ JS; } + public function saveFieldValues($searchBoxId, $torrentId, array $data) + { + $searchBox = SearchBox::query()->findOrFail($searchBoxId); + $enabledFields = TorrentCustomField::query()->find($searchBox->custom_fields); + $insert = []; + $now = now(); + foreach ($enabledFields as $field) { + if (empty($data[$field->id])) { + if ($field->required) { +// throw new \InvalidArgumentException(nexus_trans("nexus.require_argument", ['argument' => $field->label])); + do_log("Field: {$field->label} required, but empty"); + } + continue; + } + $insert[] = [ + 'torrent_id' => $torrentId, + 'custom_field_id' => $field->id, + 'custom_field_value' => $data[$field->id], + 'created_at' => $now, + 'updated_at' => $now, + ]; + } + TorrentCustomFieldValue::query()->where('torrent_id', $torrentId)->delete(); + TorrentCustomFieldValue::query()->insert($insert); + } + } diff --git a/public/details.php b/public/details.php index e1ca5a2a..5ed0672c 100644 --- a/public/details.php +++ b/public/details.php @@ -278,7 +278,7 @@ JS; do_action('torrent_detail_before_desc', $row['id'], $CURUSER['id']); /**************start custom fields****************/ - echo $customField->renderOnTorrentDetailsPage($id); + echo $customField->renderOnTorrentDetailsPage($id, $row['search_box_id']); /**************end custom fields****************/ diff --git a/public/edit.php b/public/edit.php index f490bd8a..a2a64a57 100644 --- a/public/edit.php +++ b/public/edit.php @@ -67,8 +67,6 @@ else { echo $ptGen->renderUploadPageFormInput($row['pt_gen']); } - $customField->renderOnUploadPage($id); - if ($enablenfo_main=='yes') tr($lang_edit['row_nfo_file'], "".$lang_edit['radio_keep_current']. "".$lang_edit['radio_remove']. @@ -81,7 +79,7 @@ else { tr($lang_functions['text_technical_info'], '
' . $lang_functions['text_technical_info_help_text'], 1); } - $s = ""; $cats = genrelist($sectionmode); foreach ($cats as $subrow) { @@ -93,7 +91,7 @@ else { $s .= "\n"; if ($allowmove){ - $s2 = "\n"; $cats2 = genrelist($othermode); foreach ($cats2 as $subrow) { $s2 .= "