Changeset 3712148
- Timestamp:
- 09/24/2026 11:06:29 PM (4 weeks ago)
- Location:
- servantly-ask-qa-spam-protection
- Files:
-
- 6 added
- 24 edited
- 1 copied
-
tags/2.1.5 (copied) (copied from servantly-ask-qa-spam-protection/trunk )
-
tags/2.1.5/admin/views/question-detail.php (modified) (3 diffs)
-
tags/2.1.5/assets/css/servantly-ask-frontend.css (modified) (1 diff)
-
tags/2.1.5/assets/js/servantly-ask-frontend.js (modified) (3 diffs)
-
tags/2.1.5/includes/class-servantly-ask-archive.php (modified) (5 diffs)
-
tags/2.1.5/includes/class-servantly-ask-moderation-queue.php (modified) (3 diffs)
-
tags/2.1.5/includes/class-servantly-ask-post-type.php (modified) (3 diffs)
-
tags/2.1.5/includes/class-servantly-ask-public-question.php (added)
-
tags/2.1.5/includes/class-servantly-ask-script-config.php (modified) (1 diff)
-
tags/2.1.5/includes/class-servantly-ask-settings.php (modified) (1 diff)
-
tags/2.1.5/public/class-servantly-ask-shortcodes.php (modified) (1 diff)
-
tags/2.1.5/public/views/public-archive.php (modified) (6 diffs)
-
tags/2.1.5/public/views/single-question.php (added)
-
tags/2.1.5/public/views/topic-archive.php (added)
-
tags/2.1.5/readme.txt (modified) (1 diff)
-
tags/2.1.5/servantly-ask-qa-spam-protection.php (modified) (5 diffs)
-
trunk/admin/views/question-detail.php (modified) (3 diffs)
-
trunk/assets/css/servantly-ask-frontend.css (modified) (1 diff)
-
trunk/assets/js/servantly-ask-frontend.js (modified) (3 diffs)
-
trunk/includes/class-servantly-ask-archive.php (modified) (5 diffs)
-
trunk/includes/class-servantly-ask-moderation-queue.php (modified) (3 diffs)
-
trunk/includes/class-servantly-ask-post-type.php (modified) (3 diffs)
-
trunk/includes/class-servantly-ask-public-question.php (added)
-
trunk/includes/class-servantly-ask-script-config.php (modified) (1 diff)
-
trunk/includes/class-servantly-ask-settings.php (modified) (1 diff)
-
trunk/public/class-servantly-ask-shortcodes.php (modified) (1 diff)
-
trunk/public/views/public-archive.php (modified) (6 diffs)
-
trunk/public/views/single-question.php (added)
-
trunk/public/views/topic-archive.php (added)
-
trunk/readme.txt (modified) (1 diff)
-
trunk/servantly-ask-qa-spam-protection.php (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
servantly-ask-qa-spam-protection/tags/2.1.5/admin/views/question-detail.php
r3641266 r3712148 20 20 $servantly_ask_submitter_name = get_post_meta( $servantly_ask_question_id, 'servantly_ask_submitter_name', true ); 21 21 $servantly_ask_submitter_email = get_post_meta( $servantly_ask_question_id, 'servantly_ask_submitter_email', true ); 22 $servantly_ask_answer_text = get_post_meta( $servantly_ask_question_id, 'servantly_ask_answer_text', true );23 22 $servantly_ask_internal_notes = get_post_meta( $servantly_ask_question_id, 'servantly_ask_internal_notes', true ); 24 $servantly_ask_is_public = Servantly_Ask_Archive::is_public( $servantly_ask_question_id );25 $servantly_ask_can_publish = Servantly_Ask_Settings::can_publish_to_archive( $servantly_ask_question_post );26 23 $servantly_ask_terms = get_the_terms( $servantly_ask_question_id, Servantly_Ask_Post_Type::TAXONOMY ); 27 24 $servantly_ask_category_label = ( ! empty( $servantly_ask_terms ) && ! is_wp_error( $servantly_ask_terms ) ) ? implode( ', ', wp_list_pluck( $servantly_ask_terms, 'name' ) ) : ''; … … 122 119 <tr> 123 120 <th scope="row"> 124 <label for="servantly_ask_answer_text"><?php esc_html_e( 'Answer', 'servantly-ask-qa-spam-protection' ); ?></label> 125 </th> 126 <td> 127 <textarea name="servantly_ask_answer_text" id="servantly_ask_answer_text" rows="6" class="large-text"><?php echo esc_textarea( $servantly_ask_answer_text ); ?></textarea> 121 <label for="servantly_ask_short_title"><?php esc_html_e( 'Short title', 'servantly-ask-qa-spam-protection' ); ?></label> 122 </th> 123 <td> 124 <?php $servantly_ask_short_title = Servantly_Ask_Public_Question::short_title( $servantly_ask_question_id ); ?> 125 <input type="text" class="large-text" name="servantly_ask_short_title" id="servantly_ask_short_title" value="<?php echo esc_attr( $servantly_ask_short_title ); ?>" /> 126 <?php if ( Servantly_Ask_Archive::is_public( $servantly_ask_question_id ) ) : ?> 128 127 <p class="description"> 129 <?php esc_html_e( 'Shown publicly on the archive underneath this question once published. Leave blank to show the question without an answer.', 'servantly-ask-qa-spam-protection' ); ?> 130 </p> 128 <?php esc_html_e( 'This is the heading. The link stays the same unless you edit the link below.', 'servantly-ask-qa-spam-protection' ); ?> 129 </p> 130 <?php $servantly_ask_page_url = get_permalink( $servantly_ask_question_id ); ?> 131 <p> 132 <a href="<?php echo esc_url( $servantly_ask_page_url ); ?>"><?php esc_html_e( 'View page', 'servantly-ask-qa-spam-protection' ); ?></a> 133 <code><?php echo esc_html( $servantly_ask_page_url ); ?></code> 134 </p> 135 <p> 136 <label for="servantly_ask_link_slug"><?php esc_html_e( 'Edit link', 'servantly-ask-qa-spam-protection' ); ?></label><br /> 137 <input type="text" class="regular-text" name="servantly_ask_link_slug" id="servantly_ask_link_slug" value="<?php echo esc_attr( $servantly_ask_question_post->post_name ); ?>" /> 138 </p> 139 <?php else : ?> 140 <p class="description"> 141 <?php esc_html_e( 'The page is created when you set the status to Published to Archive and save.', 'servantly-ask-qa-spam-protection' ); ?> 142 </p> 143 <?php endif; ?> 144 </td> 145 </tr> 146 <tr> 147 <th scope="row"><?php esc_html_e( 'Asker name', 'servantly-ask-qa-spam-protection' ); ?></th> 148 <td> 149 <label> 150 <input type="checkbox" name="servantly_ask_hide_name" value="1" <?php checked( 'yes', get_post_meta( $servantly_ask_question_id, Servantly_Ask_Public_Question::META_HIDE_NAME, true ) ); ?> /> 151 <?php esc_html_e( 'Hide the asker’s name on the public archive and the question page', 'servantly-ask-qa-spam-protection' ); ?> 152 </label> 153 </td> 154 </tr> 155 <tr> 156 <th scope="row"> 157 <label for="servantly_ask_date_answered"><?php esc_html_e( 'Date answered', 'servantly-ask-qa-spam-protection' ); ?></label> 158 </th> 159 <td> 160 <input type="date" name="servantly_ask_date_answered" id="servantly_ask_date_answered" value="<?php echo esc_attr( (string) get_post_meta( $servantly_ask_question_id, Servantly_Ask_Public_Question::META_DATE_ANSWERED, true ) ); ?>" /> 161 </td> 162 </tr> 163 <tr> 164 <th scope="row"><?php esc_html_e( 'Answers', 'servantly-ask-qa-spam-protection' ); ?></th> 165 <td> 166 <?php 167 $servantly_ask_answer_rows = Servantly_Ask_Public_Question::get_answers( $servantly_ask_question_id ); 168 $servantly_ask_answer_rows[] = array( 169 'pastor' => 'other', 170 'custom' => '', 171 'text' => '', 172 ); 173 ?> 174 <?php foreach ( $servantly_ask_answer_rows as $servantly_ask_answer_row ) : ?> 175 <p> 176 <select name="servantly_ask_answer_pastor[]"> 177 <?php foreach ( Servantly_Ask_Public_Question::author_names() as $servantly_ask_author_name ) : ?> 178 <option value="<?php echo esc_attr( sanitize_key( $servantly_ask_author_name ) ); ?>" <?php selected( $servantly_ask_answer_row['pastor'], sanitize_key( $servantly_ask_author_name ) ); ?>> 179 <?php echo esc_html( $servantly_ask_author_name ); ?> 180 </option> 181 <?php endforeach; ?> 182 <option value="other" <?php selected( $servantly_ask_answer_row['pastor'], 'other' ); ?>><?php esc_html_e( 'Other', 'servantly-ask-qa-spam-protection' ); ?></option> 183 </select> 184 <input type="text" name="servantly_ask_answer_custom[]" value="<?php echo esc_attr( $servantly_ask_answer_row['custom'] ); ?>" placeholder="<?php esc_attr_e( 'Name if Other', 'servantly-ask-qa-spam-protection' ); ?>" /> 185 </p> 186 <textarea name="servantly_ask_answer_text_row[]" rows="5" class="large-text"><?php echo esc_textarea( $servantly_ask_answer_row['text'] ); ?></textarea> 187 <?php endforeach; ?> 188 <p class="description"> 189 <?php esc_html_e( 'One block per pastor, in the order they should appear. The original combined answer is kept in sync from these fields.', 'servantly-ask-qa-spam-protection' ); ?> 190 </p> 191 </td> 192 </tr> 193 <tr> 194 <th scope="row"><?php esc_html_e( 'Topics', 'servantly-ask-qa-spam-protection' ); ?></th> 195 <td> 196 <?php 197 $servantly_ask_all_topics = get_terms( 198 array( 199 'taxonomy' => Servantly_Ask_Public_Question::TAXONOMY, 200 'hide_empty' => false, 201 ) 202 ); 203 $servantly_ask_set_topics = wp_get_post_terms( $servantly_ask_question_id, Servantly_Ask_Public_Question::TAXONOMY, array( 'fields' => 'ids' ) ); 204 if ( is_wp_error( $servantly_ask_set_topics ) ) { 205 $servantly_ask_set_topics = array(); 206 } 207 if ( is_array( $servantly_ask_all_topics ) && $servantly_ask_all_topics ) : 208 foreach ( $servantly_ask_all_topics as $servantly_ask_topic_term ) : 209 ?> 210 <label style="display:block;margin:0 0 0.25em;"> 211 <input type="checkbox" name="servantly_ask_topics[]" value="<?php echo esc_attr( (string) $servantly_ask_topic_term->term_id ); ?>" <?php checked( in_array( $servantly_ask_topic_term->term_id, $servantly_ask_set_topics, true ) ); ?> /> 212 <?php echo esc_html( $servantly_ask_topic_term->name ); ?> 213 </label> 214 <?php 215 endforeach; 216 else : 217 ?> 218 <p class="description"><?php esc_html_e( 'No topics yet.', 'servantly-ask-qa-spam-protection' ); ?></p> 219 <?php 220 endif; 221 ?> 222 <p> 223 <label for="servantly_ask_new_topic"><?php esc_html_e( 'Add a topic', 'servantly-ask-qa-spam-protection' ); ?></label> 224 <input type="text" name="servantly_ask_new_topic" id="servantly_ask_new_topic" class="regular-text" /> 225 </p> 226 </td> 227 </tr> 228 <tr> 229 <th scope="row"> 230 <label for="servantly_ask_video_url"><?php esc_html_e( 'Video URL', 'servantly-ask-qa-spam-protection' ); ?></label> 231 </th> 232 <td> 233 <input type="url" class="large-text" name="servantly_ask_video_url" id="servantly_ask_video_url" value="<?php echo esc_attr( (string) get_post_meta( $servantly_ask_question_id, Servantly_Ask_Public_Question::META_VIDEO_URL, true ) ); ?>" /> 234 <p> 235 <label for="servantly_ask_video_start"><?php esc_html_e( 'Start time (seconds or mm:ss)', 'servantly-ask-qa-spam-protection' ); ?></label> 236 <input type="text" name="servantly_ask_video_start" id="servantly_ask_video_start" value="<?php echo esc_attr( (string) get_post_meta( $servantly_ask_question_id, Servantly_Ask_Public_Question::META_VIDEO_START, true ) ); ?>" /> 237 </p> 238 </td> 239 </tr> 240 <tr> 241 <th scope="row"> 242 <label for="servantly_ask_scripture"><?php esc_html_e( 'Scripture references', 'servantly-ask-qa-spam-protection' ); ?></label> 243 </th> 244 <td> 245 <input type="text" class="large-text" name="servantly_ask_scripture" id="servantly_ask_scripture" value="<?php echo esc_attr( (string) get_post_meta( $servantly_ask_question_id, Servantly_Ask_Public_Question::META_SCRIPTURE, true ) ); ?>" placeholder="<?php esc_attr_e( '1 Corinthians 8; Luke 9:23', 'servantly-ask-qa-spam-protection' ); ?>" /> 246 </td> 247 </tr> 248 <tr> 249 <th scope="row"> 250 <label for="servantly_ask_related_sermons"><?php esc_html_e( 'Related sermon IDs', 'servantly-ask-qa-spam-protection' ); ?></label> 251 </th> 252 <td> 253 <?php 254 $servantly_ask_related_ids = get_post_meta( $servantly_ask_question_id, Servantly_Ask_Public_Question::META_RELATED, true ); 255 $servantly_ask_related_ids = is_array( $servantly_ask_related_ids ) ? implode( ', ', $servantly_ask_related_ids ) : ''; 256 ?> 257 <input type="text" class="large-text" name="servantly_ask_related_sermons" id="servantly_ask_related_sermons" value="<?php echo esc_attr( $servantly_ask_related_ids ); ?>" /> 258 </td> 259 </tr> 260 <tr> 261 <th scope="row"> 262 <label for="servantly_ask_meta_description"><?php esc_html_e( 'Meta description', 'servantly-ask-qa-spam-protection' ); ?></label> 263 </th> 264 <td> 265 <textarea name="servantly_ask_meta_description" id="servantly_ask_meta_description" rows="3" class="large-text" maxlength="160"><?php echo esc_textarea( (string) get_post_meta( $servantly_ask_question_id, Servantly_Ask_Public_Question::META_DESCRIPTION, true ) ); ?></textarea> 266 <p class="description"><?php esc_html_e( 'Optional. Leave blank to use the start of the first answer.', 'servantly-ask-qa-spam-protection' ); ?></p> 131 267 </td> 132 268 </tr> … … 140 276 </tr> 141 277 </table> 142 143 <?php if ( $servantly_ask_is_public ) : ?>144 <p>145 <strong><?php esc_html_e( 'Public archive:', 'servantly-ask-qa-spam-protection' ); ?></strong>146 <?php esc_html_e( 'This question is published on the public archive.', 'servantly-ask-qa-spam-protection' ); ?>147 </p>148 <?php submit_button( __( 'Remove from Public Archive', 'servantly-ask-qa-spam-protection' ), 'secondary', 'servantly_ask_unpublish_archive', false ); ?>149 <?php elseif ( $servantly_ask_can_publish ) : ?>150 <?php submit_button( __( 'Publish to Public Archive', 'servantly-ask-qa-spam-protection' ), 'secondary', 'servantly_ask_publish_archive', false ); ?>151 <?php else : ?>152 <p class="description">153 <?php esc_html_e( 'Approve this question (or clear spam checks in Auto-clear mode) before publishing to the public archive.', 'servantly-ask-qa-spam-protection' ); ?>154 </p>155 <?php endif; ?>156 278 157 279 <?php submit_button( __( 'Save Question', 'servantly-ask-qa-spam-protection' ), 'primary', 'servantly_ask_save_question' ); ?> -
servantly-ask-qa-spam-protection/tags/2.1.5/assets/css/servantly-ask-frontend.css
r3641266 r3712148 287 287 font-style: italic; 288 288 } 289 290 .servantly-ask-topic-filters, 291 .servantly-ask-archive-card-meta, 292 .servantly-ask-share, 293 .servantly-ask-scripture { 294 display: flex; 295 flex-wrap: wrap; 296 gap: 0.5rem; 297 align-items: center; 298 } 299 300 .servantly-ask-topic-filter, 301 .servantly-ask-topic-tag, 302 .servantly-ask-watch, 303 .servantly-ask-share a, 304 .servantly-ask-share button { 305 display: inline-block; 306 border: 1px solid var(--servantly-ask-border); 307 border-radius: 999px; 308 padding: 0.35em 0.8em; 309 background: #fff; 310 color: var(--servantly-ask-text); 311 text-decoration: none; 312 font: inherit; 313 cursor: pointer; 314 } 315 316 body.servantly-ask-public-page .servantly-ask-share a, 317 body.servantly-ask-public-page .servantly-ask-share button { 318 border-radius: 999px !important; 319 box-shadow: none !important; 320 color: #226053; 321 line-height: 1.4; 322 } 323 324 .servantly-ask-topic-filter.is-active, 325 .servantly-ask-watch { 326 background: var(--servantly-ask-archive-accent, var(--servantly-ask-accent)); 327 border-color: var(--servantly-ask-archive-accent, var(--servantly-ask-accent)); 328 color: #fff; 329 } 330 331 .servantly-ask-archive-card-title { 332 margin: 0 0 0.35em; 333 font-size: 1.25rem; 334 } 335 336 .servantly-ask-archive-card-title a { 337 color: inherit; 338 text-decoration: none; 339 } 340 341 .servantly-ask-archive-card-excerpt { 342 margin: 0 0 0.5em; 343 } 344 345 .servantly-ask-archive-pages { 346 display: flex; 347 justify-content: space-between; 348 gap: 1rem; 349 margin-top: 1.5rem; 350 } 351 352 .servantly-ask-archive.is-searching .servantly-ask-archive-pages, 353 .servantly-ask-archive.is-searching .servantly-ask-topic-filters { 354 display: none; 355 } 356 357 body.servantly-ask-public-page #ajax-content-wrap > .container-wrap { 358 background-color: #ffffff !important; 359 } 360 361 .servantly-ask-single, 362 .servantly-ask-single-wrap { 363 max-width: 42rem; 364 margin: 2rem auto; 365 color: #1a1a1a; 366 } 367 368 body.servantly-ask-public-page .servantly-ask-single h1, 369 body.servantly-ask-public-page .servantly-ask-single h2, 370 body.servantly-ask-public-page .servantly-ask-single-wrap h1, 371 body.servantly-ask-public-page .servantly-ask-single-wrap h2 { 372 color: #1a2744; 373 } 374 375 body.servantly-ask-public-page .servantly-ask-single a, 376 body.servantly-ask-public-page .servantly-ask-single-wrap a { 377 color: #226053; 378 } 379 380 .servantly-ask-breadcrumb { 381 color: var(--servantly-ask-muted); 382 font-size: 0.95rem; 383 } 384 385 .servantly-ask-single-question, 386 .servantly-ask-single-answer { 387 margin: 1.25rem 0; 388 } 389 390 .servantly-ask-single-cta { 391 margin-top: 2rem; 392 font-weight: 700; 393 } -
servantly-ask-qa-spam-protection/tags/2.1.5/assets/js/servantly-ask-frontend.js
r3641266 r3712148 149 149 function restoreOriginalList() { 150 150 setStatus( '' ); 151 var archive = list.closest( '.servantly-ask-archive' ); 152 if ( archive ) { 153 archive.classList.remove( 'is-searching' ); 154 } 151 155 list.innerHTML = originalHtml; 152 156 initArchiveVoting( list ); … … 176 180 activeController = controller; 177 181 182 var archive = list.closest( '.servantly-ask-archive' ); 183 if ( archive ) { 184 archive.classList.add( 'is-searching' ); 185 } 178 186 setStatus( searchI18n( 'searching', 'Searching…' ) ); 179 187 … … 237 245 li.setAttribute( 'data-question-id', String( row.id ) ); 238 246 247 if ( row.url && row.title ) { 248 var heading = document.createElement( 'h2' ); 249 heading.className = 'servantly-ask-archive-card-title'; 250 var titleLink = document.createElement( 'a' ); 251 titleLink.href = row.url; 252 titleLink.textContent = row.title; 253 heading.appendChild( titleLink ); 254 li.appendChild( heading ); 255 256 if ( row.excerpt ) { 257 var excerpt = document.createElement( 'p' ); 258 excerpt.className = 'servantly-ask-archive-card-excerpt'; 259 appendHighlighted( excerpt, row.excerpt, term ); 260 li.appendChild( excerpt ); 261 } 262 263 var meta = document.createElement( 'p' ); 264 meta.className = 'servantly-ask-archive-card-meta'; 265 if ( row.dateLabel ) { 266 var date = document.createElement( 'span' ); 267 date.textContent = row.dateLabel; 268 meta.appendChild( date ); 269 } 270 ( row.topics || [] ).forEach( function ( topic ) { 271 var tag = document.createElement( 'a' ); 272 tag.className = 'servantly-ask-topic-tag'; 273 tag.href = topic.url; 274 tag.textContent = topic.name; 275 meta.appendChild( tag ); 276 } ); 277 if ( meta.childNodes.length ) { 278 li.appendChild( meta ); 279 } 280 281 var more = document.createElement( 'p' ); 282 more.className = 'servantly-ask-archive-card-more'; 283 var moreLink = document.createElement( 'a' ); 284 moreLink.href = row.url; 285 moreLink.textContent = searchI18n( 'readMore', 'Read full answer →' ); 286 more.appendChild( moreLink ); 287 li.appendChild( more ); 288 289 if ( config.voting && config.voting.enabled ) { 290 li.appendChild( buildVoteMarkup( row ) ); 291 } 292 return li; 293 } 294 239 295 var questionBlock = document.createElement( 'div' ); 240 296 questionBlock.className = 'servantly-ask-archive-block servantly-ask-archive-question-block'; -
servantly-ask-qa-spam-protection/tags/2.1.5/includes/class-servantly-ask-archive.php
r3641266 r3712148 63 63 * Publish a question to the public archive (`publish` status per spec). 64 64 * 65 * @param int $post_id Post ID. 65 * @param int $post_id Post ID. 66 * @param bool $force When true, publish from whatever status the question 67 * is in. The question detail dropdown uses this so 68 * choosing Published to Archive and saving always 69 * publishes. The separate button still requires an 70 * eligible status. 66 71 * @return bool 67 72 */ 68 public static function publish_to_archive( $post_id ) {73 public static function publish_to_archive( $post_id, $force = false ) { 69 74 $post_id = absint( $post_id ); 70 75 $post = get_post( $post_id ); … … 78 83 } 79 84 80 if ( ! Servantly_Ask_Settings::can_publish_to_archive( $post ) ) {85 if ( ! $force && ! Servantly_Ask_Settings::can_publish_to_archive( $post ) ) { 81 86 return false; 82 87 } … … 193 198 */ 194 199 public static function get_public_questions( $search = '' ) { 195 $args = array( 200 $result = self::query_public_questions( 201 array( 202 'search' => $search, 203 'posts_per_page' => 500, 204 'paged' => 1, 205 ) 206 ); 207 return $result['posts']; 208 } 209 210 /** 211 * Paginated public-archive query. Search matches the question, the 212 * short title, and the answer text, not only the current page. 213 * 214 * @param array<string, mixed> $args search, paged, posts_per_page, topic. 215 * @return array{posts: WP_Post[], found: int, max_pages: int} 216 */ 217 public static function query_public_questions( $args = array() ) { 218 $args = wp_parse_args( 219 $args, 220 array( 221 'search' => '', 222 'paged' => 1, 223 'posts_per_page' => Servantly_Ask_Public_Question::PER_PAGE, 224 'topic' => '', 225 ) 226 ); 227 228 $query_args = array( 196 229 'post_type' => Servantly_Ask_Post_Type::POST_TYPE, 197 230 'post_status' => 'publish', 198 'posts_per_page' => 100, 231 'posts_per_page' => max( 1, (int) $args['posts_per_page'] ), 232 'paged' => max( 1, (int) $args['paged'] ), 199 233 'ignore_sticky_posts' => true, 200 'no_found_rows' => true,201 234 'update_post_meta_cache' => true, 202 235 'meta_query' => array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query … … 208 241 ); 209 242 210 $search = trim( (string) $search ); 243 $topic = sanitize_title( (string) $args['topic'] ); 244 if ( '' !== $topic ) { 245 $query_args['tax_query'] = array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query 246 array( 247 'taxonomy' => Servantly_Ask_Public_Question::TAXONOMY, 248 'field' => 'slug', 249 'terms' => $topic, 250 ), 251 ); 252 } 253 254 $search = trim( (string) $args['search'] ); 211 255 if ( '' !== $search ) { 212 $args['s'] = $search; 256 $query_args['servantly_ask_archive_search'] = $search; 257 add_filter( 'posts_where', array( __CLASS__, 'search_where' ), 10, 2 ); 213 258 } 214 259 215 260 if ( Servantly_Ask_Settings::is_voting_enabled() && 'votes' === Servantly_Ask_Settings::get_archive_sort_by() ) { 216 $ args['meta_key'] = Servantly_Ask_Voting::META_VOTE_COUNT; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key217 $ args['orderby'] = 'meta_value_num';218 $ args['order'] = 'DESC';261 $query_args['meta_key'] = Servantly_Ask_Voting::META_VOTE_COUNT; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key 262 $query_args['orderby'] = 'meta_value_num'; 263 $query_args['order'] = 'DESC'; 219 264 } else { 220 $args['orderby'] = 'date'; 221 $args['order'] = 'DESC'; 222 } 223 224 $query = new WP_Query( $args ); 225 return $query->posts; 265 $query_args['orderby'] = 'date'; 266 $query_args['order'] = 'DESC'; 267 } 268 269 $query = new WP_Query( $query_args ); 270 271 if ( '' !== $search ) { 272 remove_filter( 'posts_where', array( __CLASS__, 'search_where' ), 10 ); 273 } 274 275 return array( 276 'posts' => $query->posts, 277 'found' => (int) $query->found_posts, 278 'max_pages' => (int) $query->max_num_pages, 279 ); 280 } 281 282 /** 283 * Match question text, short title, and answer text. 284 * 285 * @param string $where SQL WHERE. 286 * @param WP_Query $query Query. 287 * @return string 288 */ 289 public static function search_where( $where, $query ) { 290 $term = $query->get( 'servantly_ask_archive_search' ); 291 if ( ! is_string( $term ) || '' === $term ) { 292 return $where; 293 } 294 global $wpdb; 295 $like = '%' . $wpdb->esc_like( $term ) . '%'; 296 $where .= $wpdb->prepare( 297 " AND ( {$wpdb->posts}.post_title LIKE %s OR {$wpdb->posts}.post_content LIKE %s OR EXISTS ( SELECT 1 FROM {$wpdb->postmeta} sa_pm WHERE sa_pm.post_id = {$wpdb->posts}.ID AND sa_pm.meta_key IN ('servantly_ask_answer_text','servantly_ask_short_title') AND sa_pm.meta_value LIKE %s ) )", 298 $like, 299 $like, 300 $like 301 ); 302 return $where; 226 303 } 227 304 … … 234 311 */ 235 312 private static function format_row_for_json( WP_Post $post ) { 313 $indexable = Servantly_Ask_Public_Question::is_indexable( $post ); 314 $name = Servantly_Ask_Public_Question::public_asker_name( $post->ID ); 315 $topics = array(); 316 $terms = get_the_terms( $post->ID, Servantly_Ask_Public_Question::TAXONOMY ); 317 if ( is_array( $terms ) ) { 318 foreach ( $terms as $term ) { 319 $topics[] = array( 320 'name' => $term->name, 321 'url' => Servantly_Ask_Public_Question::topic_url( $term->slug ), 322 ); 323 } 324 } 236 325 return array( 237 326 'id' => $post->ID, 238 327 'text' => wp_strip_all_tags( $post->post_content ), 239 'submitterName' => (string) get_post_meta( $post->ID, 'servantly_ask_submitter_name', true ),328 'submitterName' => $name, 240 329 'answerText' => wp_strip_all_tags( (string) get_post_meta( $post->ID, 'servantly_ask_answer_text', true ) ), 241 330 'voteCount' => Servantly_Ask_Voting::get_vote_count( $post->ID ), 331 'indexable' => $indexable, 332 'title' => $indexable ? Servantly_Ask_Public_Question::short_title( $post->ID ) : '', 333 'url' => $indexable ? get_permalink( $post->ID ) : '', 334 'excerpt' => Servantly_Ask_Public_Question::excerpt_from_first_answer( $post->ID, 180 ), 335 'dateLabel' => Servantly_Ask_Public_Question::answered_label( $post->ID ), 336 'topics' => $topics, 242 337 ); 243 338 } -
servantly-ask-qa-spam-protection/tags/2.1.5/includes/class-servantly-ask-moderation-queue.php
r3641266 r3712148 216 216 } 217 217 218 self::update_question_status( $post_id, $new_status ); 219 220 $answer_text = isset( $_POST['servantly_ask_answer_text'] ) 221 ? sanitize_textarea_field( wp_unslash( $_POST['servantly_ask_answer_text'] ) ) 222 : ''; 223 update_post_meta( $post_id, 'servantly_ask_answer_text', $answer_text ); 218 self::apply_status_from_detail_save( $post, $new_status ); 219 220 if ( ! isset( $_POST['servantly_ask_answer_pastor'] ) ) { 221 $answer_text = isset( $_POST['servantly_ask_answer_text'] ) 222 ? sanitize_textarea_field( wp_unslash( $_POST['servantly_ask_answer_text'] ) ) 223 : ''; 224 update_post_meta( $post_id, 'servantly_ask_answer_text', $answer_text ); 225 } 224 226 225 227 $internal_notes = isset( $_POST['servantly_ask_internal_notes'] ) … … 228 230 update_post_meta( $post_id, 'servantly_ask_internal_notes', $internal_notes ); 229 231 232 if ( class_exists( 'Servantly_Ask_Public_Question' ) ) { 233 Servantly_Ask_Public_Question::save_detail_fields( $post_id ); 234 } 235 230 236 $redirect = Servantly_Ask_Admin_Menu::get_question_detail_url( $post_id ); 231 237 $redirect = add_query_arg( 'servantly_ask_saved', '1', $redirect ); … … 233 239 wp_safe_redirect( $redirect ); 234 240 exit; 241 } 242 243 /** 244 * Apply the detail-screen status dropdown. 245 * 246 * Published to Archive sets the public flag and the status together. 247 * Any other status takes the question off the public archive. Notes and 248 * the other fields are saved by the caller either way. 249 * 250 * @param WP_Post $post Question before this save. 251 * @param string $new_status Requested status slug. 252 * @return void 253 */ 254 private static function apply_status_from_detail_save( WP_Post $post, $new_status ) { 255 $post_id = (int) $post->ID; 256 $was_public = Servantly_Ask_Archive::is_public( $post_id ); 257 258 if ( 'publish' === $new_status ) { 259 if ( ! $was_public ) { 260 Servantly_Ask_Archive::publish_to_archive( $post_id, true ); 261 } 262 return; 263 } 264 265 if ( $was_public ) { 266 Servantly_Ask_Archive::unpublish_from_archive( $post_id ); 267 } 268 269 $current = get_post_status( $post_id ); 270 if ( $current !== $new_status ) { 271 self::update_question_status( $post_id, $new_status ); 272 } 235 273 } 236 274 -
servantly-ask-qa-spam-protection/tags/2.1.5/includes/class-servantly-ask-post-type.php
r3641266 r3712148 52 52 * Register the `servantly_ask_q` custom post type. 53 53 * 54 * The post type is intentionally non-public: questions are private 55 * submissions, never directly browsable/queryable on the front end. 54 * Questions stay out of the admin UI and out of site search. Published 55 * archive answers are publicly queryable so each one can have its own 56 * URL. Anything that is not on the public archive, or whose short title 57 * is still awaiting review, is 404'd in Servantly_Ask_Public_Question. 56 58 * `show_ui` is false: questions are managed only via the Servantly Ask 57 59 * moderation queue (guest submission is the only intended entry path). … … 82 84 'description' => __( 'A question submitted through the Servantly Ask submission form.', 'servantly-ask-qa-spam-protection' ), 83 85 'public' => false, 84 'publicly_queryable' => false,86 'publicly_queryable' => true, 85 87 'exclude_from_search' => true, 86 88 'show_ui' => false, … … 89 91 'show_in_admin_bar' => false, 90 92 'show_in_rest' => false, 91 'query_var' => false,93 'query_var' => true, 92 94 'rewrite' => false, 93 95 'has_archive' => false, -
servantly-ask-qa-spam-protection/tags/2.1.5/includes/class-servantly-ask-script-config.php
r3641266 r3712148 197 197 'questionBadge' => __( 'Question', 'servantly-ask-qa-spam-protection' ), 198 198 'answerBadge' => __( 'Answer', 'servantly-ask-qa-spam-protection' ), 199 'readMore' => __( 'Read full answer →', 'servantly-ask-qa-spam-protection' ), 199 200 ), 200 201 ); -
servantly-ask-qa-spam-protection/tags/2.1.5/includes/class-servantly-ask-settings.php
r3699296 r3712148 1238 1238 } 1239 1239 1240 return in_array( $post->post_status, array( 'sa_approved', 'sa_displayed', 'sa_answered' ), true ); 1240 if ( in_array( $post->post_status, array( 'sa_approved', 'sa_displayed', 'sa_answered' ), true ) ) { 1241 return true; 1242 } 1243 1244 // Status was set to publish without the public flag (dropdown save 1245 // used to do this). Treat it as not yet on the archive so the 1246 // publish button and a second save can finish the job. 1247 return 'publish' === $post->post_status && ! Servantly_Ask_Archive::is_public( $post->ID ); 1241 1248 } 1242 1249 -
servantly-ask-qa-spam-protection/tags/2.1.5/public/class-servantly-ask-shortcodes.php
r3699296 r3712148 185 185 self::enqueue_archive_accent_style(); 186 186 187 $questions = Servantly_Ask_Archive::get_public_questions(); 187 $servantly_ask_topic = isset( $_GET['servantly_ask_topic'] ) ? sanitize_title( wp_unslash( $_GET['servantly_ask_topic'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended 188 if ( '' === $servantly_ask_topic ) { 189 $queried = get_query_var( 'servantly_ask_topic' ); 190 $servantly_ask_topic = is_string( $queried ) ? sanitize_title( $queried ) : ''; 191 } 192 $servantly_ask_paged = Servantly_Ask_Public_Question::hub_page_number(); 193 $servantly_ask_result = Servantly_Ask_Archive::query_public_questions( 194 array( 195 'paged' => $servantly_ask_paged, 196 'topic' => $servantly_ask_topic, 197 ) 198 ); 199 $questions = $servantly_ask_result['posts']; 200 $servantly_ask_found = $servantly_ask_result['found']; 201 $servantly_ask_max_pages = $servantly_ask_result['max_pages']; 202 $servantly_ask_topic_terms = get_terms( 203 array( 204 'taxonomy' => Servantly_Ask_Public_Question::TAXONOMY, 205 'hide_empty' => true, 206 ) 207 ); 208 if ( is_wp_error( $servantly_ask_topic_terms ) ) { 209 $servantly_ask_topic_terms = array(); 210 } 188 211 189 212 ob_start(); -
servantly-ask-qa-spam-protection/tags/2.1.5/public/views/public-archive.php
r3641266 r3712148 6 6 * 7 7 * @var WP_Post[] $questions Published archive questions. 8 * @var int $servantly_ask_found Number of matching questions. 9 * @var int $servantly_ask_max_pages Page count. 10 * @var int $servantly_ask_paged Current page. 11 * @var string $servantly_ask_topic Active topic slug. 12 * @var WP_Term[] $servantly_ask_topic_terms Topic terms. 8 13 */ 9 14 … … 21 26 </p> 22 27 <?php else : ?> 28 <?php if ( ! empty( $servantly_ask_topic_terms ) ) : ?> 29 <nav class="servantly-ask-topic-filters" aria-label="<?php esc_attr_e( 'Topics', 'servantly-ask-qa-spam-protection' ); ?>"> 30 <a class="servantly-ask-topic-filter<?php echo '' === $servantly_ask_topic ? ' is-active' : ''; ?>" href="<?php echo esc_url( Servantly_Ask_Public_Question::archive_url() ); ?>"> 31 <?php esc_html_e( 'All', 'servantly-ask-qa-spam-protection' ); ?> 32 </a> 33 <?php foreach ( $servantly_ask_topic_terms as $servantly_ask_topic_term ) : ?> 34 <a class="servantly-ask-topic-filter<?php echo $servantly_ask_topic === $servantly_ask_topic_term->slug ? ' is-active' : ''; ?>" href="<?php echo esc_url( Servantly_Ask_Public_Question::topic_url( $servantly_ask_topic_term->slug ) ); ?>"> 35 <?php echo esc_html( $servantly_ask_topic_term->name ); ?> 36 </a> 37 <?php endforeach; ?> 38 </nav> 39 <?php endif; ?> 23 40 <?php if ( $servantly_ask_search_enabled ) : ?> 24 41 <div class="servantly-ask-archive-search"> … … 45 62 ?> 46 63 <li class="servantly-ask-archive-item" data-question-id="<?php echo esc_attr( (string) $servantly_ask_archive_question_id ); ?>"> 64 <?php if ( Servantly_Ask_Public_Question::is_indexable( $servantly_ask_question_post ) ) : ?> 65 <?php 66 $servantly_ask_card_url = get_permalink( $servantly_ask_question_post ); 67 $servantly_ask_card_title = Servantly_Ask_Public_Question::short_title( $servantly_ask_archive_question_id ); 68 $servantly_ask_card_date = Servantly_Ask_Public_Question::answered_label( $servantly_ask_archive_question_id ); 69 $servantly_ask_card_terms = get_the_terms( $servantly_ask_archive_question_id, Servantly_Ask_Public_Question::TAXONOMY ); 70 ?> 71 <h2 class="servantly-ask-archive-card-title"> 72 <a href="<?php echo esc_url( $servantly_ask_card_url ); ?>"><?php echo esc_html( $servantly_ask_card_title ); ?></a> 73 </h2> 74 <p class="servantly-ask-archive-card-excerpt"><?php echo esc_html( Servantly_Ask_Public_Question::excerpt_from_first_answer( $servantly_ask_archive_question_id, 180 ) ); ?></p> 75 <p class="servantly-ask-archive-card-meta"> 76 <?php if ( $servantly_ask_card_date ) : ?> 77 <span><?php echo esc_html( $servantly_ask_card_date ); ?></span> 78 <?php endif; ?> 79 <?php if ( is_array( $servantly_ask_card_terms ) ) : ?> 80 <?php foreach ( $servantly_ask_card_terms as $servantly_ask_card_term ) : ?> 81 <a class="servantly-ask-topic-tag" href="<?php echo esc_url( Servantly_Ask_Public_Question::topic_url( $servantly_ask_card_term->slug ) ); ?>"><?php echo esc_html( $servantly_ask_card_term->name ); ?></a> 82 <?php endforeach; ?> 83 <?php endif; ?> 84 </p> 85 <p class="servantly-ask-archive-card-more"> 86 <a href="<?php echo esc_url( $servantly_ask_card_url ); ?>"><?php esc_html_e( 'Read full answer →', 'servantly-ask-qa-spam-protection' ); ?></a> 87 </p> 88 <?php else : ?> 47 89 <div class="servantly-ask-archive-block servantly-ask-archive-question-block"> 48 90 <span class="servantly-ask-archive-badge servantly-ask-archive-badge-question"> … … 52 94 <?php echo esc_html( $servantly_ask_question_post->post_content ); ?> 53 95 </div> 54 <?php if ( $servantly_ask_submitter_name ) : ?>96 <?php if ( $servantly_ask_submitter_name && '' !== Servantly_Ask_Public_Question::public_asker_name( $servantly_ask_archive_question_id ) ) : ?> 55 97 <p class="servantly-ask-archive-meta"> 56 98 <?php … … 76 118 </div> 77 119 <?php endif; ?> 120 <?php endif; ?> 78 121 <?php if ( $servantly_ask_voting_enabled ) : ?> 79 122 <div class="servantly-ask-vote-wrap"> … … 93 136 <?php endforeach; ?> 94 137 </ul> 138 <?php if ( $servantly_ask_max_pages > 1 ) : ?> 139 <nav class="servantly-ask-archive-pages" aria-label="<?php esc_attr_e( 'Archive pages', 'servantly-ask-qa-spam-protection' ); ?>"> 140 <?php 141 $servantly_ask_page_url = static function ( $page ) use ( $servantly_ask_topic ) { 142 $page = max( 1, (int) $page ); 143 if ( '' !== $servantly_ask_topic ) { 144 $base = Servantly_Ask_Public_Question::topic_url( $servantly_ask_topic ); 145 return 1 === $page ? $base : trailingslashit( $base ) . 'page/' . $page . '/'; 146 } 147 return Servantly_Ask_Public_Question::hub_page_url( $page ); 148 }; 149 ?> 150 <?php if ( $servantly_ask_paged > 1 ) : ?> 151 <a href="<?php echo esc_url( $servantly_ask_page_url( $servantly_ask_paged - 1 ) ); ?>"><?php esc_html_e( '← Newer', 'servantly-ask-qa-spam-protection' ); ?></a> 152 <?php endif; ?> 153 <span> 154 <?php 155 echo esc_html( 156 sprintf( 157 /* translators: 1: current page, 2: total pages */ 158 __( 'Page %1$d of %2$d', 'servantly-ask-qa-spam-protection' ), 159 $servantly_ask_paged, 160 $servantly_ask_max_pages 161 ) 162 ); 163 ?> 164 </span> 165 <?php if ( $servantly_ask_paged < $servantly_ask_max_pages ) : ?> 166 <a href="<?php echo esc_url( $servantly_ask_page_url( $servantly_ask_paged + 1 ) ); ?>"><?php esc_html_e( 'Older →', 'servantly-ask-qa-spam-protection' ); ?></a> 167 <?php endif; ?> 168 </nav> 169 <?php endif; ?> 95 170 <?php endif; ?> 96 171 </div> -
servantly-ask-qa-spam-protection/tags/2.1.5/readme.txt
r3699296 r3712148 5 5 Tested up to: 7.1 6 6 Requires PHP: 7.4 7 Stable tag: 2. 0.27 Stable tag: 2.1.5 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html -
servantly-ask-qa-spam-protection/tags/2.1.5/servantly-ask-qa-spam-protection.php
r3699296 r3712148 4 4 * Plugin URI: https://servantly.org/ 5 5 * Description: Collect questions from your community through a guest-friendly, spam-resistant submission form, review them in a private moderation queue, and optionally run a live Q&A projector display. 6 * Version: 2. 0.26 * Version: 2.1.5 7 7 * Requires at least: 6.0 8 8 * Requires PHP: 7.4 … … 21 21 } 22 22 23 define( 'SERVANTLY_ASK_VERSION', '2. 0.2' );23 define( 'SERVANTLY_ASK_VERSION', '2.1.5' ); 24 24 define( 'SERVANTLY_ASK_PLUGIN_FILE', __FILE__ ); 25 25 define( 'SERVANTLY_ASK_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); … … 50 50 require_once SERVANTLY_ASK_PLUGIN_DIR . 'includes/class-servantly-ask-presenter-kit.php'; 51 51 require_once SERVANTLY_ASK_PLUGIN_DIR . 'includes/class-servantly-ask-archive.php'; 52 require_once SERVANTLY_ASK_PLUGIN_DIR . 'includes/class-servantly-ask-public-question.php'; 52 53 require_once SERVANTLY_ASK_PLUGIN_DIR . 'includes/class-servantly-ask-voting.php'; 53 54 require_once SERVANTLY_ASK_PLUGIN_DIR . 'includes/class-servantly-ask-live-display.php'; … … 77 78 Servantly_Ask_Script_Config::init(); 78 79 Servantly_Ask_Archive::init(); 80 Servantly_Ask_Public_Question::init(); 79 81 Servantly_Ask_Voting::init(); 80 82 Servantly_Ask_Live_Display::init(); … … 101 103 Servantly_Ask_Post_Type::register_post_type(); 102 104 Servantly_Ask_Post_Type::register_taxonomy(); 105 Servantly_Ask_Public_Question::register_taxonomy(); 106 Servantly_Ask_Public_Question::register_rewrites(); 103 107 Servantly_Ask_Roles::activate(); 104 108 Servantly_Ask_Settings::seed_defaults(); -
servantly-ask-qa-spam-protection/trunk/admin/views/question-detail.php
r3641266 r3712148 20 20 $servantly_ask_submitter_name = get_post_meta( $servantly_ask_question_id, 'servantly_ask_submitter_name', true ); 21 21 $servantly_ask_submitter_email = get_post_meta( $servantly_ask_question_id, 'servantly_ask_submitter_email', true ); 22 $servantly_ask_answer_text = get_post_meta( $servantly_ask_question_id, 'servantly_ask_answer_text', true );23 22 $servantly_ask_internal_notes = get_post_meta( $servantly_ask_question_id, 'servantly_ask_internal_notes', true ); 24 $servantly_ask_is_public = Servantly_Ask_Archive::is_public( $servantly_ask_question_id );25 $servantly_ask_can_publish = Servantly_Ask_Settings::can_publish_to_archive( $servantly_ask_question_post );26 23 $servantly_ask_terms = get_the_terms( $servantly_ask_question_id, Servantly_Ask_Post_Type::TAXONOMY ); 27 24 $servantly_ask_category_label = ( ! empty( $servantly_ask_terms ) && ! is_wp_error( $servantly_ask_terms ) ) ? implode( ', ', wp_list_pluck( $servantly_ask_terms, 'name' ) ) : ''; … … 122 119 <tr> 123 120 <th scope="row"> 124 <label for="servantly_ask_answer_text"><?php esc_html_e( 'Answer', 'servantly-ask-qa-spam-protection' ); ?></label> 125 </th> 126 <td> 127 <textarea name="servantly_ask_answer_text" id="servantly_ask_answer_text" rows="6" class="large-text"><?php echo esc_textarea( $servantly_ask_answer_text ); ?></textarea> 121 <label for="servantly_ask_short_title"><?php esc_html_e( 'Short title', 'servantly-ask-qa-spam-protection' ); ?></label> 122 </th> 123 <td> 124 <?php $servantly_ask_short_title = Servantly_Ask_Public_Question::short_title( $servantly_ask_question_id ); ?> 125 <input type="text" class="large-text" name="servantly_ask_short_title" id="servantly_ask_short_title" value="<?php echo esc_attr( $servantly_ask_short_title ); ?>" /> 126 <?php if ( Servantly_Ask_Archive::is_public( $servantly_ask_question_id ) ) : ?> 128 127 <p class="description"> 129 <?php esc_html_e( 'Shown publicly on the archive underneath this question once published. Leave blank to show the question without an answer.', 'servantly-ask-qa-spam-protection' ); ?> 130 </p> 128 <?php esc_html_e( 'This is the heading. The link stays the same unless you edit the link below.', 'servantly-ask-qa-spam-protection' ); ?> 129 </p> 130 <?php $servantly_ask_page_url = get_permalink( $servantly_ask_question_id ); ?> 131 <p> 132 <a href="<?php echo esc_url( $servantly_ask_page_url ); ?>"><?php esc_html_e( 'View page', 'servantly-ask-qa-spam-protection' ); ?></a> 133 <code><?php echo esc_html( $servantly_ask_page_url ); ?></code> 134 </p> 135 <p> 136 <label for="servantly_ask_link_slug"><?php esc_html_e( 'Edit link', 'servantly-ask-qa-spam-protection' ); ?></label><br /> 137 <input type="text" class="regular-text" name="servantly_ask_link_slug" id="servantly_ask_link_slug" value="<?php echo esc_attr( $servantly_ask_question_post->post_name ); ?>" /> 138 </p> 139 <?php else : ?> 140 <p class="description"> 141 <?php esc_html_e( 'The page is created when you set the status to Published to Archive and save.', 'servantly-ask-qa-spam-protection' ); ?> 142 </p> 143 <?php endif; ?> 144 </td> 145 </tr> 146 <tr> 147 <th scope="row"><?php esc_html_e( 'Asker name', 'servantly-ask-qa-spam-protection' ); ?></th> 148 <td> 149 <label> 150 <input type="checkbox" name="servantly_ask_hide_name" value="1" <?php checked( 'yes', get_post_meta( $servantly_ask_question_id, Servantly_Ask_Public_Question::META_HIDE_NAME, true ) ); ?> /> 151 <?php esc_html_e( 'Hide the asker’s name on the public archive and the question page', 'servantly-ask-qa-spam-protection' ); ?> 152 </label> 153 </td> 154 </tr> 155 <tr> 156 <th scope="row"> 157 <label for="servantly_ask_date_answered"><?php esc_html_e( 'Date answered', 'servantly-ask-qa-spam-protection' ); ?></label> 158 </th> 159 <td> 160 <input type="date" name="servantly_ask_date_answered" id="servantly_ask_date_answered" value="<?php echo esc_attr( (string) get_post_meta( $servantly_ask_question_id, Servantly_Ask_Public_Question::META_DATE_ANSWERED, true ) ); ?>" /> 161 </td> 162 </tr> 163 <tr> 164 <th scope="row"><?php esc_html_e( 'Answers', 'servantly-ask-qa-spam-protection' ); ?></th> 165 <td> 166 <?php 167 $servantly_ask_answer_rows = Servantly_Ask_Public_Question::get_answers( $servantly_ask_question_id ); 168 $servantly_ask_answer_rows[] = array( 169 'pastor' => 'other', 170 'custom' => '', 171 'text' => '', 172 ); 173 ?> 174 <?php foreach ( $servantly_ask_answer_rows as $servantly_ask_answer_row ) : ?> 175 <p> 176 <select name="servantly_ask_answer_pastor[]"> 177 <?php foreach ( Servantly_Ask_Public_Question::author_names() as $servantly_ask_author_name ) : ?> 178 <option value="<?php echo esc_attr( sanitize_key( $servantly_ask_author_name ) ); ?>" <?php selected( $servantly_ask_answer_row['pastor'], sanitize_key( $servantly_ask_author_name ) ); ?>> 179 <?php echo esc_html( $servantly_ask_author_name ); ?> 180 </option> 181 <?php endforeach; ?> 182 <option value="other" <?php selected( $servantly_ask_answer_row['pastor'], 'other' ); ?>><?php esc_html_e( 'Other', 'servantly-ask-qa-spam-protection' ); ?></option> 183 </select> 184 <input type="text" name="servantly_ask_answer_custom[]" value="<?php echo esc_attr( $servantly_ask_answer_row['custom'] ); ?>" placeholder="<?php esc_attr_e( 'Name if Other', 'servantly-ask-qa-spam-protection' ); ?>" /> 185 </p> 186 <textarea name="servantly_ask_answer_text_row[]" rows="5" class="large-text"><?php echo esc_textarea( $servantly_ask_answer_row['text'] ); ?></textarea> 187 <?php endforeach; ?> 188 <p class="description"> 189 <?php esc_html_e( 'One block per pastor, in the order they should appear. The original combined answer is kept in sync from these fields.', 'servantly-ask-qa-spam-protection' ); ?> 190 </p> 191 </td> 192 </tr> 193 <tr> 194 <th scope="row"><?php esc_html_e( 'Topics', 'servantly-ask-qa-spam-protection' ); ?></th> 195 <td> 196 <?php 197 $servantly_ask_all_topics = get_terms( 198 array( 199 'taxonomy' => Servantly_Ask_Public_Question::TAXONOMY, 200 'hide_empty' => false, 201 ) 202 ); 203 $servantly_ask_set_topics = wp_get_post_terms( $servantly_ask_question_id, Servantly_Ask_Public_Question::TAXONOMY, array( 'fields' => 'ids' ) ); 204 if ( is_wp_error( $servantly_ask_set_topics ) ) { 205 $servantly_ask_set_topics = array(); 206 } 207 if ( is_array( $servantly_ask_all_topics ) && $servantly_ask_all_topics ) : 208 foreach ( $servantly_ask_all_topics as $servantly_ask_topic_term ) : 209 ?> 210 <label style="display:block;margin:0 0 0.25em;"> 211 <input type="checkbox" name="servantly_ask_topics[]" value="<?php echo esc_attr( (string) $servantly_ask_topic_term->term_id ); ?>" <?php checked( in_array( $servantly_ask_topic_term->term_id, $servantly_ask_set_topics, true ) ); ?> /> 212 <?php echo esc_html( $servantly_ask_topic_term->name ); ?> 213 </label> 214 <?php 215 endforeach; 216 else : 217 ?> 218 <p class="description"><?php esc_html_e( 'No topics yet.', 'servantly-ask-qa-spam-protection' ); ?></p> 219 <?php 220 endif; 221 ?> 222 <p> 223 <label for="servantly_ask_new_topic"><?php esc_html_e( 'Add a topic', 'servantly-ask-qa-spam-protection' ); ?></label> 224 <input type="text" name="servantly_ask_new_topic" id="servantly_ask_new_topic" class="regular-text" /> 225 </p> 226 </td> 227 </tr> 228 <tr> 229 <th scope="row"> 230 <label for="servantly_ask_video_url"><?php esc_html_e( 'Video URL', 'servantly-ask-qa-spam-protection' ); ?></label> 231 </th> 232 <td> 233 <input type="url" class="large-text" name="servantly_ask_video_url" id="servantly_ask_video_url" value="<?php echo esc_attr( (string) get_post_meta( $servantly_ask_question_id, Servantly_Ask_Public_Question::META_VIDEO_URL, true ) ); ?>" /> 234 <p> 235 <label for="servantly_ask_video_start"><?php esc_html_e( 'Start time (seconds or mm:ss)', 'servantly-ask-qa-spam-protection' ); ?></label> 236 <input type="text" name="servantly_ask_video_start" id="servantly_ask_video_start" value="<?php echo esc_attr( (string) get_post_meta( $servantly_ask_question_id, Servantly_Ask_Public_Question::META_VIDEO_START, true ) ); ?>" /> 237 </p> 238 </td> 239 </tr> 240 <tr> 241 <th scope="row"> 242 <label for="servantly_ask_scripture"><?php esc_html_e( 'Scripture references', 'servantly-ask-qa-spam-protection' ); ?></label> 243 </th> 244 <td> 245 <input type="text" class="large-text" name="servantly_ask_scripture" id="servantly_ask_scripture" value="<?php echo esc_attr( (string) get_post_meta( $servantly_ask_question_id, Servantly_Ask_Public_Question::META_SCRIPTURE, true ) ); ?>" placeholder="<?php esc_attr_e( '1 Corinthians 8; Luke 9:23', 'servantly-ask-qa-spam-protection' ); ?>" /> 246 </td> 247 </tr> 248 <tr> 249 <th scope="row"> 250 <label for="servantly_ask_related_sermons"><?php esc_html_e( 'Related sermon IDs', 'servantly-ask-qa-spam-protection' ); ?></label> 251 </th> 252 <td> 253 <?php 254 $servantly_ask_related_ids = get_post_meta( $servantly_ask_question_id, Servantly_Ask_Public_Question::META_RELATED, true ); 255 $servantly_ask_related_ids = is_array( $servantly_ask_related_ids ) ? implode( ', ', $servantly_ask_related_ids ) : ''; 256 ?> 257 <input type="text" class="large-text" name="servantly_ask_related_sermons" id="servantly_ask_related_sermons" value="<?php echo esc_attr( $servantly_ask_related_ids ); ?>" /> 258 </td> 259 </tr> 260 <tr> 261 <th scope="row"> 262 <label for="servantly_ask_meta_description"><?php esc_html_e( 'Meta description', 'servantly-ask-qa-spam-protection' ); ?></label> 263 </th> 264 <td> 265 <textarea name="servantly_ask_meta_description" id="servantly_ask_meta_description" rows="3" class="large-text" maxlength="160"><?php echo esc_textarea( (string) get_post_meta( $servantly_ask_question_id, Servantly_Ask_Public_Question::META_DESCRIPTION, true ) ); ?></textarea> 266 <p class="description"><?php esc_html_e( 'Optional. Leave blank to use the start of the first answer.', 'servantly-ask-qa-spam-protection' ); ?></p> 131 267 </td> 132 268 </tr> … … 140 276 </tr> 141 277 </table> 142 143 <?php if ( $servantly_ask_is_public ) : ?>144 <p>145 <strong><?php esc_html_e( 'Public archive:', 'servantly-ask-qa-spam-protection' ); ?></strong>146 <?php esc_html_e( 'This question is published on the public archive.', 'servantly-ask-qa-spam-protection' ); ?>147 </p>148 <?php submit_button( __( 'Remove from Public Archive', 'servantly-ask-qa-spam-protection' ), 'secondary', 'servantly_ask_unpublish_archive', false ); ?>149 <?php elseif ( $servantly_ask_can_publish ) : ?>150 <?php submit_button( __( 'Publish to Public Archive', 'servantly-ask-qa-spam-protection' ), 'secondary', 'servantly_ask_publish_archive', false ); ?>151 <?php else : ?>152 <p class="description">153 <?php esc_html_e( 'Approve this question (or clear spam checks in Auto-clear mode) before publishing to the public archive.', 'servantly-ask-qa-spam-protection' ); ?>154 </p>155 <?php endif; ?>156 278 157 279 <?php submit_button( __( 'Save Question', 'servantly-ask-qa-spam-protection' ), 'primary', 'servantly_ask_save_question' ); ?> -
servantly-ask-qa-spam-protection/trunk/assets/css/servantly-ask-frontend.css
r3641266 r3712148 287 287 font-style: italic; 288 288 } 289 290 .servantly-ask-topic-filters, 291 .servantly-ask-archive-card-meta, 292 .servantly-ask-share, 293 .servantly-ask-scripture { 294 display: flex; 295 flex-wrap: wrap; 296 gap: 0.5rem; 297 align-items: center; 298 } 299 300 .servantly-ask-topic-filter, 301 .servantly-ask-topic-tag, 302 .servantly-ask-watch, 303 .servantly-ask-share a, 304 .servantly-ask-share button { 305 display: inline-block; 306 border: 1px solid var(--servantly-ask-border); 307 border-radius: 999px; 308 padding: 0.35em 0.8em; 309 background: #fff; 310 color: var(--servantly-ask-text); 311 text-decoration: none; 312 font: inherit; 313 cursor: pointer; 314 } 315 316 body.servantly-ask-public-page .servantly-ask-share a, 317 body.servantly-ask-public-page .servantly-ask-share button { 318 border-radius: 999px !important; 319 box-shadow: none !important; 320 color: #226053; 321 line-height: 1.4; 322 } 323 324 .servantly-ask-topic-filter.is-active, 325 .servantly-ask-watch { 326 background: var(--servantly-ask-archive-accent, var(--servantly-ask-accent)); 327 border-color: var(--servantly-ask-archive-accent, var(--servantly-ask-accent)); 328 color: #fff; 329 } 330 331 .servantly-ask-archive-card-title { 332 margin: 0 0 0.35em; 333 font-size: 1.25rem; 334 } 335 336 .servantly-ask-archive-card-title a { 337 color: inherit; 338 text-decoration: none; 339 } 340 341 .servantly-ask-archive-card-excerpt { 342 margin: 0 0 0.5em; 343 } 344 345 .servantly-ask-archive-pages { 346 display: flex; 347 justify-content: space-between; 348 gap: 1rem; 349 margin-top: 1.5rem; 350 } 351 352 .servantly-ask-archive.is-searching .servantly-ask-archive-pages, 353 .servantly-ask-archive.is-searching .servantly-ask-topic-filters { 354 display: none; 355 } 356 357 body.servantly-ask-public-page #ajax-content-wrap > .container-wrap { 358 background-color: #ffffff !important; 359 } 360 361 .servantly-ask-single, 362 .servantly-ask-single-wrap { 363 max-width: 42rem; 364 margin: 2rem auto; 365 color: #1a1a1a; 366 } 367 368 body.servantly-ask-public-page .servantly-ask-single h1, 369 body.servantly-ask-public-page .servantly-ask-single h2, 370 body.servantly-ask-public-page .servantly-ask-single-wrap h1, 371 body.servantly-ask-public-page .servantly-ask-single-wrap h2 { 372 color: #1a2744; 373 } 374 375 body.servantly-ask-public-page .servantly-ask-single a, 376 body.servantly-ask-public-page .servantly-ask-single-wrap a { 377 color: #226053; 378 } 379 380 .servantly-ask-breadcrumb { 381 color: var(--servantly-ask-muted); 382 font-size: 0.95rem; 383 } 384 385 .servantly-ask-single-question, 386 .servantly-ask-single-answer { 387 margin: 1.25rem 0; 388 } 389 390 .servantly-ask-single-cta { 391 margin-top: 2rem; 392 font-weight: 700; 393 } -
servantly-ask-qa-spam-protection/trunk/assets/js/servantly-ask-frontend.js
r3641266 r3712148 149 149 function restoreOriginalList() { 150 150 setStatus( '' ); 151 var archive = list.closest( '.servantly-ask-archive' ); 152 if ( archive ) { 153 archive.classList.remove( 'is-searching' ); 154 } 151 155 list.innerHTML = originalHtml; 152 156 initArchiveVoting( list ); … … 176 180 activeController = controller; 177 181 182 var archive = list.closest( '.servantly-ask-archive' ); 183 if ( archive ) { 184 archive.classList.add( 'is-searching' ); 185 } 178 186 setStatus( searchI18n( 'searching', 'Searching…' ) ); 179 187 … … 237 245 li.setAttribute( 'data-question-id', String( row.id ) ); 238 246 247 if ( row.url && row.title ) { 248 var heading = document.createElement( 'h2' ); 249 heading.className = 'servantly-ask-archive-card-title'; 250 var titleLink = document.createElement( 'a' ); 251 titleLink.href = row.url; 252 titleLink.textContent = row.title; 253 heading.appendChild( titleLink ); 254 li.appendChild( heading ); 255 256 if ( row.excerpt ) { 257 var excerpt = document.createElement( 'p' ); 258 excerpt.className = 'servantly-ask-archive-card-excerpt'; 259 appendHighlighted( excerpt, row.excerpt, term ); 260 li.appendChild( excerpt ); 261 } 262 263 var meta = document.createElement( 'p' ); 264 meta.className = 'servantly-ask-archive-card-meta'; 265 if ( row.dateLabel ) { 266 var date = document.createElement( 'span' ); 267 date.textContent = row.dateLabel; 268 meta.appendChild( date ); 269 } 270 ( row.topics || [] ).forEach( function ( topic ) { 271 var tag = document.createElement( 'a' ); 272 tag.className = 'servantly-ask-topic-tag'; 273 tag.href = topic.url; 274 tag.textContent = topic.name; 275 meta.appendChild( tag ); 276 } ); 277 if ( meta.childNodes.length ) { 278 li.appendChild( meta ); 279 } 280 281 var more = document.createElement( 'p' ); 282 more.className = 'servantly-ask-archive-card-more'; 283 var moreLink = document.createElement( 'a' ); 284 moreLink.href = row.url; 285 moreLink.textContent = searchI18n( 'readMore', 'Read full answer →' ); 286 more.appendChild( moreLink ); 287 li.appendChild( more ); 288 289 if ( config.voting && config.voting.enabled ) { 290 li.appendChild( buildVoteMarkup( row ) ); 291 } 292 return li; 293 } 294 239 295 var questionBlock = document.createElement( 'div' ); 240 296 questionBlock.className = 'servantly-ask-archive-block servantly-ask-archive-question-block'; -
servantly-ask-qa-spam-protection/trunk/includes/class-servantly-ask-archive.php
r3641266 r3712148 63 63 * Publish a question to the public archive (`publish` status per spec). 64 64 * 65 * @param int $post_id Post ID. 65 * @param int $post_id Post ID. 66 * @param bool $force When true, publish from whatever status the question 67 * is in. The question detail dropdown uses this so 68 * choosing Published to Archive and saving always 69 * publishes. The separate button still requires an 70 * eligible status. 66 71 * @return bool 67 72 */ 68 public static function publish_to_archive( $post_id ) {73 public static function publish_to_archive( $post_id, $force = false ) { 69 74 $post_id = absint( $post_id ); 70 75 $post = get_post( $post_id ); … … 78 83 } 79 84 80 if ( ! Servantly_Ask_Settings::can_publish_to_archive( $post ) ) {85 if ( ! $force && ! Servantly_Ask_Settings::can_publish_to_archive( $post ) ) { 81 86 return false; 82 87 } … … 193 198 */ 194 199 public static function get_public_questions( $search = '' ) { 195 $args = array( 200 $result = self::query_public_questions( 201 array( 202 'search' => $search, 203 'posts_per_page' => 500, 204 'paged' => 1, 205 ) 206 ); 207 return $result['posts']; 208 } 209 210 /** 211 * Paginated public-archive query. Search matches the question, the 212 * short title, and the answer text, not only the current page. 213 * 214 * @param array<string, mixed> $args search, paged, posts_per_page, topic. 215 * @return array{posts: WP_Post[], found: int, max_pages: int} 216 */ 217 public static function query_public_questions( $args = array() ) { 218 $args = wp_parse_args( 219 $args, 220 array( 221 'search' => '', 222 'paged' => 1, 223 'posts_per_page' => Servantly_Ask_Public_Question::PER_PAGE, 224 'topic' => '', 225 ) 226 ); 227 228 $query_args = array( 196 229 'post_type' => Servantly_Ask_Post_Type::POST_TYPE, 197 230 'post_status' => 'publish', 198 'posts_per_page' => 100, 231 'posts_per_page' => max( 1, (int) $args['posts_per_page'] ), 232 'paged' => max( 1, (int) $args['paged'] ), 199 233 'ignore_sticky_posts' => true, 200 'no_found_rows' => true,201 234 'update_post_meta_cache' => true, 202 235 'meta_query' => array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query … … 208 241 ); 209 242 210 $search = trim( (string) $search ); 243 $topic = sanitize_title( (string) $args['topic'] ); 244 if ( '' !== $topic ) { 245 $query_args['tax_query'] = array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query 246 array( 247 'taxonomy' => Servantly_Ask_Public_Question::TAXONOMY, 248 'field' => 'slug', 249 'terms' => $topic, 250 ), 251 ); 252 } 253 254 $search = trim( (string) $args['search'] ); 211 255 if ( '' !== $search ) { 212 $args['s'] = $search; 256 $query_args['servantly_ask_archive_search'] = $search; 257 add_filter( 'posts_where', array( __CLASS__, 'search_where' ), 10, 2 ); 213 258 } 214 259 215 260 if ( Servantly_Ask_Settings::is_voting_enabled() && 'votes' === Servantly_Ask_Settings::get_archive_sort_by() ) { 216 $ args['meta_key'] = Servantly_Ask_Voting::META_VOTE_COUNT; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key217 $ args['orderby'] = 'meta_value_num';218 $ args['order'] = 'DESC';261 $query_args['meta_key'] = Servantly_Ask_Voting::META_VOTE_COUNT; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key 262 $query_args['orderby'] = 'meta_value_num'; 263 $query_args['order'] = 'DESC'; 219 264 } else { 220 $args['orderby'] = 'date'; 221 $args['order'] = 'DESC'; 222 } 223 224 $query = new WP_Query( $args ); 225 return $query->posts; 265 $query_args['orderby'] = 'date'; 266 $query_args['order'] = 'DESC'; 267 } 268 269 $query = new WP_Query( $query_args ); 270 271 if ( '' !== $search ) { 272 remove_filter( 'posts_where', array( __CLASS__, 'search_where' ), 10 ); 273 } 274 275 return array( 276 'posts' => $query->posts, 277 'found' => (int) $query->found_posts, 278 'max_pages' => (int) $query->max_num_pages, 279 ); 280 } 281 282 /** 283 * Match question text, short title, and answer text. 284 * 285 * @param string $where SQL WHERE. 286 * @param WP_Query $query Query. 287 * @return string 288 */ 289 public static function search_where( $where, $query ) { 290 $term = $query->get( 'servantly_ask_archive_search' ); 291 if ( ! is_string( $term ) || '' === $term ) { 292 return $where; 293 } 294 global $wpdb; 295 $like = '%' . $wpdb->esc_like( $term ) . '%'; 296 $where .= $wpdb->prepare( 297 " AND ( {$wpdb->posts}.post_title LIKE %s OR {$wpdb->posts}.post_content LIKE %s OR EXISTS ( SELECT 1 FROM {$wpdb->postmeta} sa_pm WHERE sa_pm.post_id = {$wpdb->posts}.ID AND sa_pm.meta_key IN ('servantly_ask_answer_text','servantly_ask_short_title') AND sa_pm.meta_value LIKE %s ) )", 298 $like, 299 $like, 300 $like 301 ); 302 return $where; 226 303 } 227 304 … … 234 311 */ 235 312 private static function format_row_for_json( WP_Post $post ) { 313 $indexable = Servantly_Ask_Public_Question::is_indexable( $post ); 314 $name = Servantly_Ask_Public_Question::public_asker_name( $post->ID ); 315 $topics = array(); 316 $terms = get_the_terms( $post->ID, Servantly_Ask_Public_Question::TAXONOMY ); 317 if ( is_array( $terms ) ) { 318 foreach ( $terms as $term ) { 319 $topics[] = array( 320 'name' => $term->name, 321 'url' => Servantly_Ask_Public_Question::topic_url( $term->slug ), 322 ); 323 } 324 } 236 325 return array( 237 326 'id' => $post->ID, 238 327 'text' => wp_strip_all_tags( $post->post_content ), 239 'submitterName' => (string) get_post_meta( $post->ID, 'servantly_ask_submitter_name', true ),328 'submitterName' => $name, 240 329 'answerText' => wp_strip_all_tags( (string) get_post_meta( $post->ID, 'servantly_ask_answer_text', true ) ), 241 330 'voteCount' => Servantly_Ask_Voting::get_vote_count( $post->ID ), 331 'indexable' => $indexable, 332 'title' => $indexable ? Servantly_Ask_Public_Question::short_title( $post->ID ) : '', 333 'url' => $indexable ? get_permalink( $post->ID ) : '', 334 'excerpt' => Servantly_Ask_Public_Question::excerpt_from_first_answer( $post->ID, 180 ), 335 'dateLabel' => Servantly_Ask_Public_Question::answered_label( $post->ID ), 336 'topics' => $topics, 242 337 ); 243 338 } -
servantly-ask-qa-spam-protection/trunk/includes/class-servantly-ask-moderation-queue.php
r3641266 r3712148 216 216 } 217 217 218 self::update_question_status( $post_id, $new_status ); 219 220 $answer_text = isset( $_POST['servantly_ask_answer_text'] ) 221 ? sanitize_textarea_field( wp_unslash( $_POST['servantly_ask_answer_text'] ) ) 222 : ''; 223 update_post_meta( $post_id, 'servantly_ask_answer_text', $answer_text ); 218 self::apply_status_from_detail_save( $post, $new_status ); 219 220 if ( ! isset( $_POST['servantly_ask_answer_pastor'] ) ) { 221 $answer_text = isset( $_POST['servantly_ask_answer_text'] ) 222 ? sanitize_textarea_field( wp_unslash( $_POST['servantly_ask_answer_text'] ) ) 223 : ''; 224 update_post_meta( $post_id, 'servantly_ask_answer_text', $answer_text ); 225 } 224 226 225 227 $internal_notes = isset( $_POST['servantly_ask_internal_notes'] ) … … 228 230 update_post_meta( $post_id, 'servantly_ask_internal_notes', $internal_notes ); 229 231 232 if ( class_exists( 'Servantly_Ask_Public_Question' ) ) { 233 Servantly_Ask_Public_Question::save_detail_fields( $post_id ); 234 } 235 230 236 $redirect = Servantly_Ask_Admin_Menu::get_question_detail_url( $post_id ); 231 237 $redirect = add_query_arg( 'servantly_ask_saved', '1', $redirect ); … … 233 239 wp_safe_redirect( $redirect ); 234 240 exit; 241 } 242 243 /** 244 * Apply the detail-screen status dropdown. 245 * 246 * Published to Archive sets the public flag and the status together. 247 * Any other status takes the question off the public archive. Notes and 248 * the other fields are saved by the caller either way. 249 * 250 * @param WP_Post $post Question before this save. 251 * @param string $new_status Requested status slug. 252 * @return void 253 */ 254 private static function apply_status_from_detail_save( WP_Post $post, $new_status ) { 255 $post_id = (int) $post->ID; 256 $was_public = Servantly_Ask_Archive::is_public( $post_id ); 257 258 if ( 'publish' === $new_status ) { 259 if ( ! $was_public ) { 260 Servantly_Ask_Archive::publish_to_archive( $post_id, true ); 261 } 262 return; 263 } 264 265 if ( $was_public ) { 266 Servantly_Ask_Archive::unpublish_from_archive( $post_id ); 267 } 268 269 $current = get_post_status( $post_id ); 270 if ( $current !== $new_status ) { 271 self::update_question_status( $post_id, $new_status ); 272 } 235 273 } 236 274 -
servantly-ask-qa-spam-protection/trunk/includes/class-servantly-ask-post-type.php
r3641266 r3712148 52 52 * Register the `servantly_ask_q` custom post type. 53 53 * 54 * The post type is intentionally non-public: questions are private 55 * submissions, never directly browsable/queryable on the front end. 54 * Questions stay out of the admin UI and out of site search. Published 55 * archive answers are publicly queryable so each one can have its own 56 * URL. Anything that is not on the public archive, or whose short title 57 * is still awaiting review, is 404'd in Servantly_Ask_Public_Question. 56 58 * `show_ui` is false: questions are managed only via the Servantly Ask 57 59 * moderation queue (guest submission is the only intended entry path). … … 82 84 'description' => __( 'A question submitted through the Servantly Ask submission form.', 'servantly-ask-qa-spam-protection' ), 83 85 'public' => false, 84 'publicly_queryable' => false,86 'publicly_queryable' => true, 85 87 'exclude_from_search' => true, 86 88 'show_ui' => false, … … 89 91 'show_in_admin_bar' => false, 90 92 'show_in_rest' => false, 91 'query_var' => false,93 'query_var' => true, 92 94 'rewrite' => false, 93 95 'has_archive' => false, -
servantly-ask-qa-spam-protection/trunk/includes/class-servantly-ask-script-config.php
r3641266 r3712148 197 197 'questionBadge' => __( 'Question', 'servantly-ask-qa-spam-protection' ), 198 198 'answerBadge' => __( 'Answer', 'servantly-ask-qa-spam-protection' ), 199 'readMore' => __( 'Read full answer →', 'servantly-ask-qa-spam-protection' ), 199 200 ), 200 201 ); -
servantly-ask-qa-spam-protection/trunk/includes/class-servantly-ask-settings.php
r3699296 r3712148 1238 1238 } 1239 1239 1240 return in_array( $post->post_status, array( 'sa_approved', 'sa_displayed', 'sa_answered' ), true ); 1240 if ( in_array( $post->post_status, array( 'sa_approved', 'sa_displayed', 'sa_answered' ), true ) ) { 1241 return true; 1242 } 1243 1244 // Status was set to publish without the public flag (dropdown save 1245 // used to do this). Treat it as not yet on the archive so the 1246 // publish button and a second save can finish the job. 1247 return 'publish' === $post->post_status && ! Servantly_Ask_Archive::is_public( $post->ID ); 1241 1248 } 1242 1249 -
servantly-ask-qa-spam-protection/trunk/public/class-servantly-ask-shortcodes.php
r3699296 r3712148 185 185 self::enqueue_archive_accent_style(); 186 186 187 $questions = Servantly_Ask_Archive::get_public_questions(); 187 $servantly_ask_topic = isset( $_GET['servantly_ask_topic'] ) ? sanitize_title( wp_unslash( $_GET['servantly_ask_topic'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended 188 if ( '' === $servantly_ask_topic ) { 189 $queried = get_query_var( 'servantly_ask_topic' ); 190 $servantly_ask_topic = is_string( $queried ) ? sanitize_title( $queried ) : ''; 191 } 192 $servantly_ask_paged = Servantly_Ask_Public_Question::hub_page_number(); 193 $servantly_ask_result = Servantly_Ask_Archive::query_public_questions( 194 array( 195 'paged' => $servantly_ask_paged, 196 'topic' => $servantly_ask_topic, 197 ) 198 ); 199 $questions = $servantly_ask_result['posts']; 200 $servantly_ask_found = $servantly_ask_result['found']; 201 $servantly_ask_max_pages = $servantly_ask_result['max_pages']; 202 $servantly_ask_topic_terms = get_terms( 203 array( 204 'taxonomy' => Servantly_Ask_Public_Question::TAXONOMY, 205 'hide_empty' => true, 206 ) 207 ); 208 if ( is_wp_error( $servantly_ask_topic_terms ) ) { 209 $servantly_ask_topic_terms = array(); 210 } 188 211 189 212 ob_start(); -
servantly-ask-qa-spam-protection/trunk/public/views/public-archive.php
r3641266 r3712148 6 6 * 7 7 * @var WP_Post[] $questions Published archive questions. 8 * @var int $servantly_ask_found Number of matching questions. 9 * @var int $servantly_ask_max_pages Page count. 10 * @var int $servantly_ask_paged Current page. 11 * @var string $servantly_ask_topic Active topic slug. 12 * @var WP_Term[] $servantly_ask_topic_terms Topic terms. 8 13 */ 9 14 … … 21 26 </p> 22 27 <?php else : ?> 28 <?php if ( ! empty( $servantly_ask_topic_terms ) ) : ?> 29 <nav class="servantly-ask-topic-filters" aria-label="<?php esc_attr_e( 'Topics', 'servantly-ask-qa-spam-protection' ); ?>"> 30 <a class="servantly-ask-topic-filter<?php echo '' === $servantly_ask_topic ? ' is-active' : ''; ?>" href="<?php echo esc_url( Servantly_Ask_Public_Question::archive_url() ); ?>"> 31 <?php esc_html_e( 'All', 'servantly-ask-qa-spam-protection' ); ?> 32 </a> 33 <?php foreach ( $servantly_ask_topic_terms as $servantly_ask_topic_term ) : ?> 34 <a class="servantly-ask-topic-filter<?php echo $servantly_ask_topic === $servantly_ask_topic_term->slug ? ' is-active' : ''; ?>" href="<?php echo esc_url( Servantly_Ask_Public_Question::topic_url( $servantly_ask_topic_term->slug ) ); ?>"> 35 <?php echo esc_html( $servantly_ask_topic_term->name ); ?> 36 </a> 37 <?php endforeach; ?> 38 </nav> 39 <?php endif; ?> 23 40 <?php if ( $servantly_ask_search_enabled ) : ?> 24 41 <div class="servantly-ask-archive-search"> … … 45 62 ?> 46 63 <li class="servantly-ask-archive-item" data-question-id="<?php echo esc_attr( (string) $servantly_ask_archive_question_id ); ?>"> 64 <?php if ( Servantly_Ask_Public_Question::is_indexable( $servantly_ask_question_post ) ) : ?> 65 <?php 66 $servantly_ask_card_url = get_permalink( $servantly_ask_question_post ); 67 $servantly_ask_card_title = Servantly_Ask_Public_Question::short_title( $servantly_ask_archive_question_id ); 68 $servantly_ask_card_date = Servantly_Ask_Public_Question::answered_label( $servantly_ask_archive_question_id ); 69 $servantly_ask_card_terms = get_the_terms( $servantly_ask_archive_question_id, Servantly_Ask_Public_Question::TAXONOMY ); 70 ?> 71 <h2 class="servantly-ask-archive-card-title"> 72 <a href="<?php echo esc_url( $servantly_ask_card_url ); ?>"><?php echo esc_html( $servantly_ask_card_title ); ?></a> 73 </h2> 74 <p class="servantly-ask-archive-card-excerpt"><?php echo esc_html( Servantly_Ask_Public_Question::excerpt_from_first_answer( $servantly_ask_archive_question_id, 180 ) ); ?></p> 75 <p class="servantly-ask-archive-card-meta"> 76 <?php if ( $servantly_ask_card_date ) : ?> 77 <span><?php echo esc_html( $servantly_ask_card_date ); ?></span> 78 <?php endif; ?> 79 <?php if ( is_array( $servantly_ask_card_terms ) ) : ?> 80 <?php foreach ( $servantly_ask_card_terms as $servantly_ask_card_term ) : ?> 81 <a class="servantly-ask-topic-tag" href="<?php echo esc_url( Servantly_Ask_Public_Question::topic_url( $servantly_ask_card_term->slug ) ); ?>"><?php echo esc_html( $servantly_ask_card_term->name ); ?></a> 82 <?php endforeach; ?> 83 <?php endif; ?> 84 </p> 85 <p class="servantly-ask-archive-card-more"> 86 <a href="<?php echo esc_url( $servantly_ask_card_url ); ?>"><?php esc_html_e( 'Read full answer →', 'servantly-ask-qa-spam-protection' ); ?></a> 87 </p> 88 <?php else : ?> 47 89 <div class="servantly-ask-archive-block servantly-ask-archive-question-block"> 48 90 <span class="servantly-ask-archive-badge servantly-ask-archive-badge-question"> … … 52 94 <?php echo esc_html( $servantly_ask_question_post->post_content ); ?> 53 95 </div> 54 <?php if ( $servantly_ask_submitter_name ) : ?>96 <?php if ( $servantly_ask_submitter_name && '' !== Servantly_Ask_Public_Question::public_asker_name( $servantly_ask_archive_question_id ) ) : ?> 55 97 <p class="servantly-ask-archive-meta"> 56 98 <?php … … 76 118 </div> 77 119 <?php endif; ?> 120 <?php endif; ?> 78 121 <?php if ( $servantly_ask_voting_enabled ) : ?> 79 122 <div class="servantly-ask-vote-wrap"> … … 93 136 <?php endforeach; ?> 94 137 </ul> 138 <?php if ( $servantly_ask_max_pages > 1 ) : ?> 139 <nav class="servantly-ask-archive-pages" aria-label="<?php esc_attr_e( 'Archive pages', 'servantly-ask-qa-spam-protection' ); ?>"> 140 <?php 141 $servantly_ask_page_url = static function ( $page ) use ( $servantly_ask_topic ) { 142 $page = max( 1, (int) $page ); 143 if ( '' !== $servantly_ask_topic ) { 144 $base = Servantly_Ask_Public_Question::topic_url( $servantly_ask_topic ); 145 return 1 === $page ? $base : trailingslashit( $base ) . 'page/' . $page . '/'; 146 } 147 return Servantly_Ask_Public_Question::hub_page_url( $page ); 148 }; 149 ?> 150 <?php if ( $servantly_ask_paged > 1 ) : ?> 151 <a href="<?php echo esc_url( $servantly_ask_page_url( $servantly_ask_paged - 1 ) ); ?>"><?php esc_html_e( '← Newer', 'servantly-ask-qa-spam-protection' ); ?></a> 152 <?php endif; ?> 153 <span> 154 <?php 155 echo esc_html( 156 sprintf( 157 /* translators: 1: current page, 2: total pages */ 158 __( 'Page %1$d of %2$d', 'servantly-ask-qa-spam-protection' ), 159 $servantly_ask_paged, 160 $servantly_ask_max_pages 161 ) 162 ); 163 ?> 164 </span> 165 <?php if ( $servantly_ask_paged < $servantly_ask_max_pages ) : ?> 166 <a href="<?php echo esc_url( $servantly_ask_page_url( $servantly_ask_paged + 1 ) ); ?>"><?php esc_html_e( 'Older →', 'servantly-ask-qa-spam-protection' ); ?></a> 167 <?php endif; ?> 168 </nav> 169 <?php endif; ?> 95 170 <?php endif; ?> 96 171 </div> -
servantly-ask-qa-spam-protection/trunk/readme.txt
r3699296 r3712148 5 5 Tested up to: 7.1 6 6 Requires PHP: 7.4 7 Stable tag: 2. 0.27 Stable tag: 2.1.5 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html -
servantly-ask-qa-spam-protection/trunk/servantly-ask-qa-spam-protection.php
r3699296 r3712148 4 4 * Plugin URI: https://servantly.org/ 5 5 * Description: Collect questions from your community through a guest-friendly, spam-resistant submission form, review them in a private moderation queue, and optionally run a live Q&A projector display. 6 * Version: 2. 0.26 * Version: 2.1.5 7 7 * Requires at least: 6.0 8 8 * Requires PHP: 7.4 … … 21 21 } 22 22 23 define( 'SERVANTLY_ASK_VERSION', '2. 0.2' );23 define( 'SERVANTLY_ASK_VERSION', '2.1.5' ); 24 24 define( 'SERVANTLY_ASK_PLUGIN_FILE', __FILE__ ); 25 25 define( 'SERVANTLY_ASK_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); … … 50 50 require_once SERVANTLY_ASK_PLUGIN_DIR . 'includes/class-servantly-ask-presenter-kit.php'; 51 51 require_once SERVANTLY_ASK_PLUGIN_DIR . 'includes/class-servantly-ask-archive.php'; 52 require_once SERVANTLY_ASK_PLUGIN_DIR . 'includes/class-servantly-ask-public-question.php'; 52 53 require_once SERVANTLY_ASK_PLUGIN_DIR . 'includes/class-servantly-ask-voting.php'; 53 54 require_once SERVANTLY_ASK_PLUGIN_DIR . 'includes/class-servantly-ask-live-display.php'; … … 77 78 Servantly_Ask_Script_Config::init(); 78 79 Servantly_Ask_Archive::init(); 80 Servantly_Ask_Public_Question::init(); 79 81 Servantly_Ask_Voting::init(); 80 82 Servantly_Ask_Live_Display::init(); … … 101 103 Servantly_Ask_Post_Type::register_post_type(); 102 104 Servantly_Ask_Post_Type::register_taxonomy(); 105 Servantly_Ask_Public_Question::register_taxonomy(); 106 Servantly_Ask_Public_Question::register_rewrites(); 103 107 Servantly_Ask_Roles::activate(); 104 108 Servantly_Ask_Settings::seed_defaults();
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)