#
#
#yamynginx2020-01-13 01:04:44
PHP
#yamynginx, 2020-01-13 01:04:44

What's wrong with this class?

Hello. I wrote two classes and I want to put them on github, but, according to the classics, I want the code to be beautiful and correct.
Actually, this is my first experience with OOP, and I would like to hear criticism from experts.
The first class for processing Callback API from VK:

spoiler

class VKCallback {
    private static array $json;

    public static function run() : void {
        if (!empty($json = json_decode(file_get_contents('php://input'), true))) {
            self::$json = $json;
        } else {
            self::close();
        }
    }

    public static function type(string $type, callable $function) : bool {
        return self::$json['type'] == $type ? call_user_func($function, self::$json) : self::close();
    }

    public static function on(string $string, callable $function) : bool {
        return strstr(strtolower(self::$json['object']['message']['text']), strtolower($string)) ? call_user_func($function, self::$json) : false;
    }

    public static function close(string $string = 'ok') : bool {
        echo $string;
        return fastcgi_finish_request();
    }
}


The second class is a regular class for working with the VK API:
spoiler
class VK {
    private static string $access_token;
    private static float $v;

    public static function setup(string $access_token, float $v = 5.101) : void {
        self::$access_token = $access_token;
        self::$v = $v;
    }

    public static function sendMessage(array $array) : array {
        return self::API('messages.send', array_merge($array, ['random_id' => rand(0, 9999999999)]));
    }

    public static function API(string $method, array $array) : array {
        $array['access_token'] = self::$access_token;
        $array['v'] = self::$v;

        return json_decode(
            self::cURL('https://api.vk.com/method/' . $method . '?' . http_build_query($array)),
            true
        );
    }

    private static function cURL(string $url) : string {
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HEADER => false,
            CURLOPT_FOLLOWLOCATION => false,
            CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0',
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_SSL_VERIFYPEER => false,
        ]);
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
}

Here's how I apply the whole thing:
spoiler
use VKCallback as App;

VK::setup('213');

App::run();

App::type('confirmation', function() {
    App::close('8c58af93');
});

App::type('message_new', function(array $json) : void {

    App::on('Пока', function (array $json) : void {
        VK::sendMessage([
            'user_ids' => $json['object']['message']['from_id'],
            'message' => 'Пока',
        ]);
    });

    VK::sendMessage([
        'user_ids' => $json['object']['message']['from_id'],
        'message' => 'Твой ID: ' . $json['object']['message']['from_id'] . ' | Ты сказал: ' . $json['object']['message']['text'],
    ]);
    App::close();
});

Actually, it all worked the first time, to which my surprise knew no bounds.
But, I repeat, I would like to achieve complete perfectionism. Is the structure of the VKCallback class done correctly at all? Is it possible to combine these two classes into one without violating one of the OOP rules? I'm not asking you to do something for me, I would be grateful if you tell me the shortcomings.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
H
HemulGM, 2020-01-13
@muxui

Agree with other answerers, it's not exactly OOP. Only one OOP principle is used - the class and that is how simple the namespace is.
Here is something like OOP and VK API in Delphi:

TAuth = class(TVKEntity)
    /// <summary>
    /// Проверяет правильность введённого номера (возможность его использования для регистрации или авторизации).
    /// </summary>
    /// <param name="Phone">номер телефона регистрируемого пользователя</param>
    /// <param name="ClientId">идентификатор Вашего приложения</param>
    /// <param name="ClientSecret">секретный ключ приложения, доступный в разделе редактирования приложения</param>
    /// <param name="AuthByPhone">True — проверить правильность номера для авторизации,
    ///                           а не для регистрации нового аккаунта. По умолчанию: False.</param>
    function CheckPhone(Phone: string; ClientId, ClientSecret: string; AuthByPhone: Boolean = False): Boolean; overload;
    /// <summary>
    /// Проверяет правильность введённого номера (возможность его использования для регистрации или авторизации).
    /// С указанием текущих данных приложения ClientId и ClientSecret
    /// </summary>
    /// <param name="Phone">номер телефона регистрируемого пользователя</param>
    /// <param name="AuthByPhone">True — проверить правильность номера для авторизации,
    ///                           а не для регистрации нового аккаунта. По умолчанию: False.</param>
    function CheckPhone(Phone: string; AuthByPhone: Boolean = False): Boolean; overload;
    /// <summary>
    /// https://vk.com/dev/auth.restore
    /// </summary>
    function Restore(Phone, LastName: string): TResponse;
  end;

TVKHandler = class
    const
      RequestLimit = 3; //Round(1000 / 3) + 10; //задержка между запросами 3 запроса в секунду + 10 мс страховка
  private
    FStartRequest: Cardinal;
    FRequests: Integer;
    FRESTClient: TRESTClient;
    FOnConfirm: TOnConfirm;
    FOnError: TOnVKError;
    FOnLog: TOnLog;
    FUseServiceKeyOnly: Boolean;
    FOwner: TObject;
    FOnCaptcha: TOnCaptcha;
    function DoConfirm(Answer: string): Boolean;
    procedure ProcError(Code: Integer; Text: string = ''); overload;
    procedure ProcError(E: Exception); overload;
    procedure ProcError(Msg: string); overload;
    procedure SetOnConfirm(const Value: TOnConfirm);
    procedure SetOnError(const Value: TOnVKError);
    procedure FLog(const Value: string);
    procedure SetOnLog(const Value: TOnLog);
    procedure SetUseServiceKeyOnly(const Value: Boolean);
    procedure SetOwner(const Value: TObject);
    procedure SetOnCaptcha(const Value: TOnCaptcha);
  public
    constructor Create(AOwner: TObject);
    destructor Destroy; override;
    function AskCaptcha(Sender: TObject; const CaptchaImg: string; var Answer: string): Boolean;
    function Execute(Request: string; Params: TParams): TResponse; overload;
    function Execute(Request: string; Param: TParam): TResponse; overload;
    function Execute(Request: string): TResponse; overload;
    function Execute(Request: TRESTRequest; FreeRequset: Boolean = False): TResponse; overload;
    property RESTClient: TRESTClient read FRESTClient;
    property OnConfirm: TOnConfirm read FOnConfirm write SetOnConfirm;
    property OnCaptcha: TOnCaptcha read FOnCaptcha write SetOnCaptcha;
    property OnError: TOnVKError read FOnError write SetOnError;
    property OnLog: TOnLog read FOnLog write SetOnLog;
    property UseServiceKeyOnly: Boolean read FUseServiceKeyOnly write SetUseServiceKeyOnly;
    property Owner: TObject read FOwner write SetOwner;
  end;

TLongPollServer = class
   ...
    function Start: Boolean;
    procedure Stop;
    constructor Create; overload;
    constructor Create(AClient: TRESTClient; AMethod: string; AParams: TParams); overload;
    destructor Destroy; override;
    property OnError: TOnVKError read FOnError write SetOnError;
    property Interval: Integer read FInterval write SetInterval;
    property GroupID: string read FGroupID write SetGroupID;
    property OnUpdate: TOnLongPollServerUpdate read FOnUpdate write SetOnUpdate;
    property Client: TCustomRESTClient read GetClient write SetClient;
    property Method: string read FMethod write SetMethod;
    property Params: TParams read FParams write SetParams;
  end;

TCustomVK = class(TComponent)
  private
    FOAuth2Authenticator: TOAuth2Authenticator;
    FOnLogin: TOnLogin;
    FPermissionsList: TPermissions;
    FGroupLongPollServers: TGroupLongPollServers;
    FAuthForm: TFormOAuth2;
    FAppID: string;
    FAppKey: string;
    FEndPoint: string;
    FHandler: TVKHandler;
    FBaseURL: string;
    FAPIVersion: string;
    FAccount: TAccount;
    FAuth: TAuth;
    FServiceKey: string;
    FUseServiceKeyOnly: Boolean;
    FIsLogin: Boolean;
    FOnError: TOnVKError;
    FOnLog: TOnLog;
    FOnErrorLogin: TOnVKError;
    FChangePasswordHash: string;
    FUsers: TUsers;
    FOnCaptcha: TOnCaptcha;
    FOnConfirm: TOnConfirm;
    FOnAuth: TOnAuth;
    function GetPermissions: string;
    procedure FAskCaptcha(Sender: TObject; const CaptchaImg: string; var Answer: string);
    procedure FAfterRedirect(const AURL: string; var DoCloseWebView: boolean);
    procedure FAuthError(const AURL: string; AStatusCode: Integer; var Cancel: WordBool);
    procedure FLog(Sender: TObject; const Value: string);
    procedure FVKError(Sender: TObject; Code: Integer; Text: string);
    procedure SetOnLogin(const Value: TOnLogin);
    procedure SetPermissionsList(const Value: TPermissions);
    procedure DoLogin;
    procedure SetAppID(const Value: string);
    procedure SetAppKey(const Value: string);
    procedure SetEndPoint(const Value: string);
    procedure SetPermissions(const Value: string);
    procedure SetHandler(const Value: TVKHandler);
    procedure SetBaseURL(const Value: string);
    procedure SetAPIVersion(const Value: string);
    procedure SetServiceKey(const Value: string);
    procedure SetUseServiceKeyOnly(const Value: Boolean);
    procedure SetOnError(const Value: TOnVKError);
    procedure SetOnLog(const Value: TOnLog);
    procedure SetOnErrorLogin(const Value: TOnVKError);
    procedure SetOnCaptcha(const Value: TOnCaptcha);
    procedure SetOnConfirm(const Value: TOnConfirm);
    procedure SetOnAuth(const Value: TOnAuth);
    procedure DoAuth(const AURL: string);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure DoLog(Sender: TObject; Text: string);
    procedure Login(AParentWindow: TWinControl = nil);
    procedure CallMethod(MethodName: string; Params: TParams; Callback: TCallMethodCallback = nil);
    procedure GroupLongPollServerStart(GroupID: string);
    procedure GroupLongPollServerStop(GroupID: string);
    /// <summary>
    /// Универсальный метод, который позволяет запускать последовательность других методов, сохраняя и фильтруя промежуточные результаты.
    /// https://vk.com/dev/execute
    /// </summary>
    /// <param name="Code">код алгоритма в VKScript - формате, похожем на JavaSсript или ActionScript (предполагается совместимость с ECMAScript). Алгоритм должен завершаться командой return %выражение%. Операторы должны быть разделены точкой с запятой. </param>
    function Execute(Code: string): TResponse;
    property PermissionsList: TPermissions read FPermissionsList write SetPermissionsList;
    //Группы методов
    property Account: TAccount read FAccount;
    property Auth: TAuth read FAuth;
    property Users: TUsers read FUsers;
    //
    property AppID: string read FAppID write SetAppID;
    property AppKey: string read FAppKey write SetAppKey;
    property EndPoint: string read FEndPoint write SetEndPoint;
    property Permissions: string read GetPermissions write SetPermissions;
    property Handler: TVKHandler read FHandler write SetHandler;
    property APIVersion: string read FAPIVersion write SetAPIVersion;
    property BaseURL: string read FBaseURL write SetBaseURL;
    property ServiceKey: string read FServiceKey write SetServiceKey;
    property UseServiceKeyOnly: Boolean read FUseServiceKeyOnly write SetUseServiceKeyOnly;
    property IsLogin: Boolean read FIsLogin;
    property ChangePasswordHash: string read FChangePasswordHash;
    //
    property OnLogin: TOnLogin read FOnLogin write SetOnLogin;
    property OnError: TOnVKError read FOnError write SetOnError;
    property OnErrorLogin: TOnVKError read FOnErrorLogin write SetOnErrorLogin;
    property OnLog: TOnLog read FOnLog write SetOnLog;
    property OnCaptcha: TOnCaptcha read FOnCaptcha write SetOnCaptcha;
    property OnConfirm: TOnConfirm read FOnConfirm write SetOnConfirm;
    property OnAuth: TOnAuth read FOnAuth write SetOnAuth;
  end;

Of course, not a sample of ideal code ... But what is

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question