JFIF$        dd7 

Viewing File: /opt/cloudlinux/venv/lib/python3.11/site-packages/xray/smart_advice_plugin_helpers.py

#!/opt/cloudlinux/venv/bin/python3 -Ibb
##
# Copyright (с) Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2022 All Rights Reserved
#
# Licensed under CLOUD LINUX LICENSE AGREEMENT
# https://www.cloudlinux.com/legal/
##

import os
import pwd
import logging
from enum import Enum
from datetime import datetime, timedelta
from clcommon.cpapi import docroot
from xray.internal.clwpos_safe_imports import wp_get_constant
from xray import gettext as _
from xray.internal.utils import user_context
from secureio import disable_quota

class PluginStatuses(Enum):
    """
    INSTALLED = plugin exists in MU directory

    ERROR = plugin should have been installed: there are advices w/o incompatibility
    and created_at > 2days (wordpress-install cron expected to trigger install)

    NOT_INSTALLED = plugin does not exist in MU directory:
    in ideal world it means whether there are no compatible advices or
    wordpress-plugin install cron has not worked yet

    """
    INSTALLED = 'INSTALLED'
    ERROR = 'ERROR'
    NOT_INSTALLED = 'NOT_INSTALLED'

def create_mu_plugins_dir_if_not_exist(user, mu_plugin_dir):
    """
    Creates MU plugin dir if does not exist yet
    """
    if os.path.isdir(mu_plugin_dir):
        return

    user_data = pwd.getpwnam(user)
    with user_context(user_data.pw_uid, user_data.pw_gid), disable_quota():
        try:
            os.makedirs(mu_plugin_dir)
        except OSError as e:
            logging.error("Failed creating must use plugin folder. Path: %s. Reason: %s",
                          mu_plugin_dir, str(e))

            raise ValueError(_('Unable to create MU plugins directory'))

def get_mu_directory(user, full_wp_path):
    """
    Resolve path to MU plugins directory for given site.
    Fast path: <full_wp_path>/wp-content/mu-plugins (and presence of our plugin there).
    Fallback: read WPMU_PLUGIN_DIR or WP_CONTENT_DIR via wp_get_constant (wp-cli), under user context.
    """
    # Fast path: default location
    fast_mu = os.path.join(full_wp_path, 'wp-content', 'mu-plugins')
    fast_mu_file = os.path.join(fast_mu, 'cl-smart-advice.php')
    fast_mu_folder = os.path.join(fast_mu, 'cl-smart-advice')

    if os.path.isdir(fast_mu) or (os.path.isfile(fast_mu_file) and os.path.isdir(fast_mu_folder)):
        return fast_mu

    # Fallback to reading WP constants
    mu_directory = None
    user_data = pwd.getpwnam(user)
    with user_context(user_data.pw_uid, user_data.pw_gid):
        try:
            mu_directory = wp_get_constant(full_wp_path, 'WPMU_PLUGIN_DIR', raise_exception=True)
        except Exception as e:
            logging.error('Unable to read WPMU_PLUGIN_DIR constant, "error=%s"', str(e))

        if not mu_directory:
            try:
                content_dir = wp_get_constant(full_wp_path, 'WP_CONTENT_DIR', raise_exception=True)
                if content_dir:
                    mu_directory = os.path.join(content_dir, 'mu-plugins')
            except Exception as e:
                logging.error('Unable to read WP_CONTENT_DIR constant, "error=%s"', str(e))
    return mu_directory

def is_plugin_installed(user, domain, website):
    """
    Checks whether there is cl-smart-advice.php in MU  plugins directory
    """
    full_website_path = docroot(domain)[0] + website
    mu_directory = get_mu_directory(user, full_website_path)
    if not mu_directory:
        logging.warning('Path to directory with MU plugins was not obtained')
        return None
    plugin_must_use_file = os.path.join(mu_directory, 'cl-smart-advice.php')
    return os.path.islink(plugin_must_use_file)

def should_have_been_installed(advices_for_website, issues):
    """
    1. At least 1 advice has no incompatibilities
    2. The newest advice w/o incompatibilities was created > 2 days ago
    """
    issue_types = []
    if issues:
        issue_types = [issue['advice_type'] for issue in issues]

    return [
        advice
        for advice in advices_for_website
        if is_advice_should_been_synced(advice, issue_types)
    ]

def is_advice_should_been_synced(advice, website_issue_types):
    """
    If advice does not have incompatibility and older than cron time (once a day) ->
    it should have been synced, which triggers plugin installation
    """
    created_at = datetime.fromisoformat(advice['created_at'])
    return advice['advice']['type'] not in website_issue_types and \
            created_at < datetime.now(created_at.tzinfo) - timedelta(days=2)

def get_plugin_status(username, domain, website, issues, current_advices):
    """
    If smart-advice.php in MU plugin dir -> INSTALLED
    If there is at least 1 advice w/o issues and the newest advice is > 2 days -> cron should've work
    and install plugin, most likely error happened -> ERROR
    otherwise: NOT_INSTALLED: all advices are incompatible or wordpress-plugin install cron did not work yet
    """
    if is_plugin_installed(username, domain, website):
        return PluginStatuses.INSTALLED.value
    elif should_have_been_installed(current_advices, issues):
        return PluginStatuses.ERROR.value
    return PluginStatuses.NOT_INSTALLED.value
Back to Directory  nL+D550H?Mx ,D"v]qv;6*Zqn)ZP0!1 A "#a$2Qr D8 a Ri[f\mIykIw0cuFcRı?lO7к_f˓[C$殷WF<_W ԣsKcëIzyQy/_LKℂ;C",pFA:/]=H  ~,ls/9ć:[=/#f;)x{ٛEQ )~ =𘙲r*2~ a _V=' kumFD}KYYC)({ *g&f`툪ry`=^cJ.I](*`wq1dđ#̩͑0;H]u搂@:~וKL Nsh}OIR*8:2 !lDJVo(3=M(zȰ+i*NAr6KnSl)!JJӁ* %݉?|D}d5:eP0R;{$X'xF@.ÊB {,WJuQɲRI;9QE琯62fT.DUJ;*cP A\ILNj!J۱+O\͔]ޒS߼Jȧc%ANolՎprULZԛerE2=XDXgVQeӓk yP7U*omQIs,K`)6\G3t?pgjrmۛجwluGtfh9uyP0D;Uڽ"OXlif$)&|ML0Zrm1[HXPlPR0'G=i2N+0e2]]9VTPO׮7h(F*癈'=QVZDF,d߬~TX G[`le69CR(!S2!P <0x<!1AQ "Raq02Br#SCTb ?Ζ"]mH5WR7k.ۛ!}Q~+yԏz|@T20S~Kek *zFf^2X*(@8r?CIuI|֓>^ExLgNUY+{.RѪ τV׸YTD I62'8Y27'\TP.6d&˦@Vqi|8-OΕ]ʔ U=TL8=;6c| !qfF3aů&~$l}'NWUs$Uk^SV:U# 6w++s&r+nڐ{@29 gL u"TÙM=6(^"7r}=6YݾlCuhquympǦ GjhsǜNlɻ}o7#S6aw4!OSrD57%|?x>L |/nD6?/8w#[)L7+6〼T ATg!%5MmZ/c-{1_Je"|^$'O&ޱմTrb$w)R$& N1EtdU3Uȉ1pM"N*(DNyd96.(jQ)X 5cQɎMyW?Q*!R>6=7)Xj5`J]e8%t!+'!1Q5 !1 AQaqё#2"0BRb?Gt^## .llQT $v,,m㵜5ubV =sY+@d{N! dnO<.-B;_wJt6;QJd.Qc%p{ 1,sNDdFHI0ГoXшe黅XۢF:)[FGXƹ/w_cMeD,ʡcc.WDtA$j@:) -# u c1<@ۗ9F)KJ-hpP]_x[qBlbpʖw q"LFGdƶ*s+ډ_Zc"?%t[IP 6J]#=ɺVvvCGsGh1 >)6|ey?Lӣm,4GWUi`]uJVoVDG< SB6ϏQ@ TiUlyOU0kfV~~}SZ@*WUUi##; s/[=!7}"WN]'(L! ~y5g9T̅JkbM' +s:S +B)v@Mj e Cf jE 0Y\QnzG1д~Wo{T9?`Rmyhsy3!HAD]mc1~2LSu7xT;j$`}4->L#vzŏILS ֭T{rjGKC;bpU=-`BsK.SFw4Mq]ZdHS0)tLg