Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.circleci/config.yml
bin/install-wp-tests.sh
.phpcs.xml.dist
100 changes: 100 additions & 0 deletions assets/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
.rtc-contributors-box {
margin-top: 30px;
padding: 20px;
border: 1px solid #e0e0e0;
background-color: #f9f9f9;
border-radius: 4px;
clear: both; /* Ensure it clears floats if any */
overflow: hidden; /* Contain floats */
}

.rtc-contributors-box h3 {
margin-top: 0;
margin-bottom: 15px;
font-size: 1.2em;
border-bottom: 1px solid #e0e0e0;
padding-bottom: 10px;
}

.rtc-contributors-box ul {
list-style: none;
padding: 0;
margin: 0;
}

.rtc-contributors-box li {
margin-bottom: 15px;
padding-bottom: 15px;
border-bottom: 1px dotted #ccc;
display: flex; /* Use flexbox for layout */
align-items: center; /* Vertically align items */
flex-wrap: wrap; /* Allow wrapping on small screens */
}

.rtc-contributors-box li:last-child {
margin-bottom: 0;
padding-bottom: 0;
border-bottom: none;
}

.rtc-contributors-box .contributor-avatar {
margin-right: 15px;
flex-shrink: 0; /* Prevent avatar from shrinking */
}

.rtc-contributors-box .contributor-avatar img {
border-radius: 50%; /* Make avatar circular */
display: block;
}

.rtc-contributors-box .contributor-info {
flex-grow: 1; /* Allow info section to take remaining space */
}

.rtc-contributors-box .contributor-name {
font-weight: bold;
text-decoration: none;
color: #333;
display: block; /* Ensure link takes full width if needed */
margin-bottom: 5px; /* Space below name */
}

.rtc-contributors-box .contributor-name:hover {
text-decoration: underline;
color: #0073aa; /* WordPress blue */
}

/* Responsive Adjustments */
@media (max-width: 600px) {
.rtc-contributors-box {
padding: 15px;
}

.rtc-contributors-box li {
/* Stack avatar and info vertically on small screens */
/* flex-direction: column;
align-items: flex-start; */ /* Optional: align left if stacking */
}

.rtc-contributors-box .contributor-avatar {
/* margin-right: 0;
margin-bottom: 10px; */ /* Adjust spacing if stacking */
}
}

/* Admin Metabox list basic style (optional, relies mostly on core styles) */
.rtc-contributors-list ul {
margin: 0;
padding: 0;
}

.rtc-contributors-list li {
margin: 0 0 5px 0;
padding: 0;
list-style: none;
}

.rtc-contributors-list label {
display: block; /* Ensure labels take full width for easier clicking */
padding: 2px 0;
}
104 changes: 104 additions & 0 deletions class-author-archive.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?php
/**
* File for handling the author archives in author page .
*
* @created 2025-04-12
* @author atiqsu <atiqur.su@gmail.com>
* @package rtCamp
*/

namespace rtCamp;

use rtCamp\Metabox;

/**
* Contributor class
*/
class Author_Archive {

/**
* Initializes the actual actions
*/
public function init() {

add_action( 'pre_get_posts', array( $this, 'modify_author_archive_query' ) );
}

/**
* Show all the posts for the author listed in contributors.
*
* @param string $query The query that fetches the posts for author.
*/
public function modify_author_archive_query( $query ) {

if ( is_admin() || ! $query->is_main_query() || ! $query->is_author() ) {

return;
}

$author_id = get_queried_object_id();

$all_post_ids = $this->get_all_post_ids_from_pm( $author_id );

$query->set( 'author', '' );
$query->set( 'author_name', '' );

$query->set( 'post__in', $all_post_ids );
}

/**
* Get all the posts for the author.
*
* @param int $author_id author id to fetch the posts for.
*/
public function get_all_post_ids_from_pm( $author_id ) {

global $wpdb;

$author_id = (int) $author_id;

$cache_key = 'cache_contributors_for_author_' . $author_id;
$matched_post_ids = wp_cache_get( $cache_key, 'cached_contributors' );

if ( false === $matched_post_ids ) {
$like = '%' . $author_id . '%';

$meta_rows = $wpdb->get_results( // phpcs:ignore
$wpdb->prepare(
'SELECT post_id, meta_value FROM ' . $wpdb->postmeta . ' WHERE meta_key = %s AND meta_value LIKE %s',
Metabox::CONTRIBUTORS_META_KEY,
$like
)
);

$matched_post_ids = array();

foreach ( $meta_rows as $row ) {
$contributors = maybe_unserialize( $row->meta_value );
if ( is_array( $contributors ) && in_array( $author_id, $contributors ) ) { // phpcs:ignore
$matched_post_ids[] = (int) $row->post_id;
}
}

wp_cache_set( $cache_key, $matched_post_ids, 'cached_contributors', 60 );
}

$authored_post_ids = get_posts(
array(
'fields' => 'ids',
'author' => $author_id,
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => -1,
)
);

$all_post_ids = array_unique( array_merge( $authored_post_ids, $matched_post_ids ) );

if ( empty( $all_post_ids ) ) {
$all_post_ids = array( 0 );
}

return $all_post_ids;
}
}
76 changes: 76 additions & 0 deletions class-autoloader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php
/**
* File for autoloading the plugin classes.
*
* @created 2025-04-09
*
* @author atiqsu <atiqur.su@gmail.com>
* @package rtCamp
*/

namespace rtCamp;

defined( 'ABSPATH' ) || exit;

/**
* PHP class autoloader
*
* @since 1.0.0
*/
class Autoloader {

/**
* Autoloading all php class according to our rule/convention.
*
* PSR4 implementation will be added later
*
* @since 1.0.0
* @access public
*/
public static function run() {
spl_autoload_register( array( __CLASS__, 'autoload' ) );
}

/**
* Autoload.
*
* @param string $cls - actual class name.
* @since 1.0.0
* @access private
*/
private static function autoload( $cls ) {

if ( 0 !== strpos( $cls, __NAMESPACE__ ) ) {
return;
}

$nms = self::get_plg_nms();
$pattern = '/\b' . preg_quote( $nms, '/' ) . '\\\/';
$fl_nm = preg_replace( $pattern, '', $cls );
$fl_nm = preg_replace( '/\\\/', DIRECTORY_SEPARATOR, $fl_nm );

/**
* Preparig dash convention.
*/
$fl_nm = preg_replace( '/([a-z])([A-Z])/', '$1-$2', $fl_nm ); // when like AuthorContent -> Author-Content.
$fl_nm = str_replace( '_', '-', $fl_nm ); // when like Author_Content -> Author-Content.

$fl_nm = plugin_dir_path( __FILE__ ) . 'class-' . $fl_nm . '.php';
$fl_nm = strtolower( $fl_nm );

if ( file_exists( $fl_nm ) ) {
require_once $fl_nm;
}
}

/**
* Get the plugin namespace.
*
* @return string
*/
public static function get_plg_nms(): string {
return __NAMESPACE__;
}
}

Autoloader::run();
62 changes: 62 additions & 0 deletions class-boot.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php
/**
* File for plugin bootstrapping.
*
* @created 2025-04-09
* @author atiqsu <atiqur.su@gmail.com>
* @package rtCamp
*/

namespace rtCamp;

use rtCamp\Contributor;
use rtCamp\Metabox;
use rtCamp\Author_Archive;

/**
* Class Boot.
*/
class Boot {

/**
* The path to the plugin.
*
* @var string
*/
protected string $path;

/**
* Constructor.
*
* @param string $path The path to the plugin.
*/
public function __construct( string $path ) {

$this->path = $path;

add_action( 'init', array( $this, 'i18n' ) );
add_action( 'wp_enqueue_scripts', array( $this, 'frontend_assets' ) );

( new Metabox() )->init();
( new Contributor() )->init();
( new Author_Archive() )->init();
}

/**
* Load the plugin text domain.
*/
public function i18n(): void {
load_plugin_textdomain(
'rtc-wp-assignment',
false,
plugin_dir_path( plugin_basename( $this->path ) ) . '/languages/'
);
}

/**
* Enqueue the frontend assets.
*/
public function frontend_assets() {
wp_enqueue_style( 'rtc-front-style', plugins_url( 'assets/style.css', $this->path ), array(), '1.0.0' );
}
}
Loading