403Webshell
Server IP : 3.147.158.171  /  Your IP : 216.73.216.216
Web Server : Apache/2.4.67 (Amazon Linux) OpenSSL/3.5.5
System : Linux ip-172-31-2-178.us-east-2.compute.internal 6.1.172-216.329.amzn2023.x86_64 #1 SMP PREEMPT_DYNAMIC Wed May 20 06:31:34 UTC 2026 x86_64
User : ec2-user ( 1000)
PHP Version : 8.4.21
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : OFF
Directory :  /tsai/repo/sites/scike-astronomy/wp-content/plugins/tsai-plugin/includes/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /tsai/repo/sites/scike-astronomy/wp-content/plugins/tsai-plugin/includes/class-tsai-projects.php
<?php
if (!defined('ABSPATH')) {
    exit;
}

/**
 * [tsai_projects] — renders every "promoted" site (logo + name + tagline)
 * together with a short list of each site's recent articles.
 *
 * Site data comes from the TSAI API /site-index endpoint (the same feed the
 * Banner app uses). Recent articles are pulled per-site from each site's public
 * WordPress REST API.
 */
class TSAI_Projects {

    const ARTICLES_TTL      = 30 * MINUTE_IN_SECONDS;
    const ARTICLES_MISS_TTL = 5 * MINUTE_IN_SECONDS;

    public function __construct() {
        add_shortcode('tsai_projects', array($this, 'render'));
        add_action('wp_enqueue_scripts', array($this, 'enqueue_assets'));
    }

    public function render($atts) {
        $atts = shortcode_atts(array(
            'count'        => '5',   // recent articles per site
            'logo'         => '150', // logo size: 72 | 150 | 300 | full
            'exclude_self' => '0',   // '1' to drop the current site from the list
            'remote'       => '1',   // '1' to also include sites from remote servers
        ), $atts, 'tsai_projects');

        $count         = max(1, (int) $atts['count']);
        $exclude_self  = filter_var($atts['exclude_self'], FILTER_VALIDATE_BOOLEAN);
        $include_remote = filter_var($atts['remote'], FILTER_VALIDATE_BOOLEAN);

        $sites = $include_remote
            ? TSAI_Site_Index::get_all_sites()
            : TSAI_Site_Index::get_sites();
        if (empty($sites)) {
            return sprintf(
                '<div class="tsai-projects tsai-projects--empty"><p>%s</p></div>',
                esc_html__('No projects to show right now.', 'tsai')
            );
        }

        $home_host = wp_parse_url(home_url(), PHP_URL_HOST);

        $cards = '';
        foreach ($sites as $site) {
            if (!is_array($site) || empty($site['promoted'])) {
                continue;
            }
            if ($exclude_self) {
                $entry_host = wp_parse_url(isset($site['wpHost']) ? $site['wpHost'] : '', PHP_URL_HOST);
                if ($entry_host && $home_host && strcasecmp($entry_host, $home_host) === 0) {
                    continue;
                }
            }
            $cards .= $this->render_card($site, $count, $atts['logo']);
        }

        if ($cards === '') {
            return sprintf(
                '<div class="tsai-projects tsai-projects--empty"><p>%s</p></div>',
                esc_html__('No projects to show right now.', 'tsai')
            );
        }

        return sprintf('<div class="tsai-projects">%s</div>', $cards);
    }

    private function render_card($site, $count, $logo_size) {
        $name    = isset($site['name']) ? (string) $site['name'] : '';
        $tagline = isset($site['tagline']) ? (string) $site['tagline'] : '';
        $link    = isset($site['link']) ? (string) $site['link'] : '';
        $wp_host = isset($site['wpHost']) ? (string) $site['wpHost'] : '';
        $logo    = $this->pick_logo($site, $logo_size);

        // Header: logo (linked) + name (linked) + tagline.
        $logo_html = '';
        if ($logo !== '') {
            $img = sprintf(
                '<img class="tsai-projects__logo" src="%s" alt="%s" loading="lazy" />',
                esc_url($logo),
                esc_attr($name)
            );
            $logo_html = $link !== ''
                ? sprintf('<a class="tsai-projects__logo-link" href="%s">%s</a>', esc_url($link), $img)
                : $img;
        }

        $name_html = esc_html($name);
        if ($link !== '') {
            $name_html = sprintf('<a href="%s">%s</a>', esc_url($link), $name_html);
        }

        // Two sites on different servers can share a slug and a display name
        // (the tsai server and scike.ai both host a "News"), so print the host
        // to say which one this card leads to.
        $host      = $this->display_host($wp_host);
        $host_html = $host !== ''
            ? sprintf('<p class="tsai-projects__host">%s</p>', esc_html($host))
            : '';

        $tagline_html = $tagline !== ''
            ? sprintf('<p class="tsai-projects__tagline">%s</p>', esc_html($tagline))
            : '';

        $articles_html = $this->articles_html($wp_host, $count);

        return sprintf(
            '<div class="tsai-projects__card">'
                . '<div class="tsai-projects__header">%s<h3 class="tsai-projects__title">%s</h3>%s%s</div>'
                . '%s'
                . '</div>',
            $logo_html,
            $name_html,
            $host_html,
            $tagline_html,
            $articles_html
        );
    }

    /**
     * The host as shown to a visitor, minus "www.".
     */
    private function display_host($wp_host) {
        $wp_host = trim((string) $wp_host);
        if ($wp_host === '') {
            return '';
        }

        $host = wp_parse_url($wp_host, PHP_URL_HOST);
        $host = strtolower($host ? $host : $wp_host);

        return strpos($host, 'www.') === 0 ? substr($host, 4) : $host;
    }

    private function pick_logo($site, $logo_size) {
        $map = array(
            '72'   => 'logo72',
            '150'  => 'logo150',
            '300'  => 'logo300',
            'full' => 'logoFull',
        );
        $key = isset($map[$logo_size]) ? $map[$logo_size] : 'logo150';
        // Chosen size, then sensible fallbacks.
        foreach (array($key, 'logo150', 'logo300', 'logoFull', 'logo72') as $k) {
            if (!empty($site[$k])) {
                return (string) $site[$k];
            }
        }
        return '';
    }

    private function articles_html($wp_host, $count) {
        $articles = $this->get_recent_articles($wp_host, $count);
        if (empty($articles)) {
            return sprintf(
                '<p class="tsai-projects__empty">%s</p>',
                esc_html__('No recent articles.', 'tsai')
            );
        }

        $items = '';
        foreach ($articles as $a) {
            $meta_parts = array();
            if (!empty($a['author'])) {
                $meta_parts[] = esc_html($a['author']);
            }
            if (!empty($a['date'])) {
                $ts = strtotime($a['date']);
                if ($ts) {
                    $meta_parts[] = esc_html(date_i18n(get_option('date_format'), $ts));
                }
            }
            $meta_html = !empty($meta_parts)
                ? sprintf('<span class="tsai-projects__article-meta">%s</span>', implode(' &middot; ', $meta_parts))
                : '';

            $items .= sprintf(
                '<li class="tsai-projects__article"><a class="tsai-projects__article-title" href="%s">%s</a>%s</li>',
                esc_url($a['link']),
                esc_html($a['title']),
                $meta_html
            );
        }

        return sprintf('<ul class="tsai-projects__articles">%s</ul>', $items);
    }

    /**
     * Fetch recent published articles from a site's public WP REST API.
     * Cached per host+count in a transient.
     *
     * @return array List of ['title','link','date','author'] rows.
     */
    private function get_recent_articles($wp_host, $count) {
        $wp_host = trim((string) $wp_host);
        if ($wp_host === '') {
            return array();
        }

        $cache_key = 'tsai_projects_articles_' . md5($wp_host . '|' . $count);
        $cached = get_transient($cache_key);
        if (is_array($cached)) {
            return $cached;
        }

        $endpoint = trailingslashit($wp_host) . 'wp-json/wp/v2/posts';
        $endpoint = add_query_arg(array(
            '_embed'   => 'author,wp:featuredmedia',
            'per_page' => $count,
            'status'   => 'publish',
            'orderby'  => 'date',
            'order'    => 'desc',
        ), $endpoint);

        $response = wp_remote_get($endpoint, array('timeout' => 8));
        if (is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 200) {
            error_log('[TSAI] projects: recent articles fetch failed for ' . $wp_host);
            set_transient($cache_key, array(), self::ARTICLES_MISS_TTL);
            return array();
        }

        $posts = json_decode(wp_remote_retrieve_body($response), true);
        if (!is_array($posts)) {
            set_transient($cache_key, array(), self::ARTICLES_MISS_TTL);
            return array();
        }

        $articles = array();
        foreach ($posts as $post) {
            if (!is_array($post)) {
                continue;
            }
            $articles[] = array(
                'title'  => isset($post['title']['rendered']) ? wp_strip_all_tags($post['title']['rendered']) : '',
                'link'   => isset($post['link']) ? (string) $post['link'] : '',
                'date'   => isset($post['date']) ? (string) $post['date'] : '',
                'author' => $this->extract_author($post),
            );
        }

        set_transient($cache_key, $articles, self::ARTICLES_TTL);
        return $articles;
    }

    private function extract_author($post) {
        if (isset($post['_embedded']['author'][0]['name'])) {
            return (string) $post['_embedded']['author'][0]['name'];
        }
        return '';
    }

    public function enqueue_assets() {
        // Enqueue unconditionally: block themes leave post_content empty, so
        // has_shortcode() misses shortcodes rendered via patterns/templates.
        wp_enqueue_style('tsai-projects', TSAI_PLUGIN_URL . 'assets/css/tsai-projects.css', array(), '2.4.3');
    }
}

new TSAI_Projects();

Youez - 2016 - github.com/yon3zu
LinuXploit