From 9934802183f938ac34ea79fef3d97bcffaa4a453 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 2 Mar 2024 11:53:51 +0800 Subject: [PATCH] phase 1 completed --- app/Gateways/AbstractGateway.php | 459 ++++++++++++++++++++++++++++ app/Gateways/CryptoPayLite.php | 52 ++++ app/Loader.php | 46 +++ app/Models/TransactionsLite.php | 22 +- app/Models/TransactionsPro.php | 22 +- assets/images/icon.png | Bin 0 -> 1789 bytes assets/images/icon.svg | 3 + assets/js/main.js | 85 ++++++ gravity-forms-cryptopay-gateway.php | 70 ++--- vendor/autoload.php | 2 +- vendor/composer/autoload_real.php | 8 +- vendor/composer/autoload_static.php | 8 +- vendor/composer/installed.php | 4 +- 13 files changed, 724 insertions(+), 57 deletions(-) create mode 100644 app/Gateways/AbstractGateway.php create mode 100644 app/Gateways/CryptoPayLite.php create mode 100644 assets/images/icon.png create mode 100644 assets/images/icon.svg create mode 100644 assets/js/main.js diff --git a/app/Gateways/AbstractGateway.php b/app/Gateways/AbstractGateway.php new file mode 100644 index 0000000..db20f0b --- /dev/null +++ b/app/Gateways/AbstractGateway.php @@ -0,0 +1,459 @@ + $properties + */ + public function __construct(array $properties = []) + { + parent::__construct($properties); + $this->field_input_id = 'input_' . $this->id; + + // Actions. + if (!has_action('gform_editor_js_set_default_values', [$this, 'editor_js_set_default_values'])) { + add_action('gform_editor_js_set_default_values', [$this, 'editor_js_set_default_values']); + } + + if (!has_action('gform_editor_js', [$this, 'editor_script'])) { + add_action('gform_editor_js', [$this, 'editor_script']); + } + + add_filter('gform_submit_button', array($this, 'form_submit_button'), 10, 2); + // Creating multiple fields, when this fixed, enable this. + // add_action('gform_field_standard_settings', [ $this, 'field_standard_settings' ], 10, 2); + } + + /** + * @param int $formId + * @return string + */ + abstract public function run(int $formId): string; + + /** + * @return array + */ + public function get_form_editor_button(): array + { + return [ + 'group' => 'cryptopay_fields', + 'text' => $this->get_form_editor_field_title() + ]; + } + + /** + * @param array $fieldGroups + * @return array + */ + private function add_pay_field_group(array $fieldGroups): array + { + if (!isset($fieldGroups['cryptopay_fields'])) { + $fieldGroups['cryptopay_fields'] = [ + 'name' => 'cryptopay_fields', + 'label' => __('CryptoPay Fields', 'gf-cryptopay'), + 'fields' => [], + ]; + } + + return $fieldGroups; + } + + /** + * @param array $fieldGroups + * @return array + */ + // @phpcs:ignore + public function add_button($fieldGroups): array + { + return parent::add_button(self::add_pay_field_group($fieldGroups)); + } + + /** + * @param int $position + * @param int $formId + * @return void + */ + // @phpcs:ignore + public function field_standard_settings($position, $formId): void + { + if (10 !== $position) { + return; + } + ?> +
  • + + +
  • + + */ + public function get_form_editor_field_settings(): array + { + return array( + 'cryptopay_field_setting', + ); + } + + /** + * @param bool $works + * @return string + */ + private function get_field_works_or_expect_msg(bool $works = true): string + { + $msg = $works + ? esc_html__('The %s process will appear on the front-end and the form can be sent when the user completes the payment.', 'gf-cryptopay') // phpcs:ignore + : esc_html__('Please add a total field to your form for %s works.', 'gf-cryptopay'); + + return sprintf($msg, $this->get_form_editor_field_title()); + } +/** + * @return void + */ + public function editor_script(): void + { + ?> + + + case 'type); ?>' : + if (!field.label) { + field.label = 'get_form_editor_field_title()); ?>'; + } + break; + $form + * @param string $value + * @param array $entry + * @return string + */ + // @phpcs:ignore + public function get_field_input($form, $value = '', $entry = null): string + { + ob_start(); + ?> +
    + get_field_works_or_expect_msg($this->form_hash_total_field($form)); ?> +
    + $form + * @return bool + */ + private function form_hash_total_field(array $form): bool + { + return (bool) array_search('total', array_column($form['fields'], 'type')); + } + + /** + * @param array $form + * @return bool + */ + private function form_has_this_field(array $form): bool + { + return (bool) array_search($this->id, array_column($form['fields'], 'id')); + } + + /** + * @param array $form + * @return bool + */ + private function is_this_field_works(array $form): bool + { + return $this->form_hash_total_field($form) && $this->form_has_this_field($form); + } + + /** + * @param string $value + * @return string + */ + private function create_hidden_tx_input(string $value = ''): string + { + // phpcs:ignore + $field = ''; + + if ($value != '') { + $field .= ''; + } + + return $field; + } + + /** + * @param array $form + * @param object|null $tx + * @return bool + */ + private function is_this_form_needs_payment(array $form, ?object $tx = null): bool + { + if (!$tx) { + $tx = $this->get_tx_with_user_and_form_id(strval($form['id'])); + } + + if (!$tx) { + return true; + } + + return (bool) $this->get_entry_with_tx($tx); + } + + /** + * @param string $formId + * @return object|null + */ + private function get_tx_with_user_and_form_id(string $formId): ?object + { + $model = Helpers::run('getModelByAddon', 'gravityforms'); + return $model->findOneByUserAndFormId(get_current_user_id(), $formId); + } + /** + * @param object $tx + * @return array|null + */ + private function get_entry_with_tx(object $tx): ?array + { + $params = json_decode($tx?->params ?? ''); + $entries = \GFAPI::get_entries([$params?->formId], [ + 'status' => 'active', + 'field_filters' => [ + [ + 'key' => $this->id, + 'value' => $tx->hash, + ] + ] + ]); + + return $entries[0] ?? null; + } + + /** + * @param string $formId + * @return string + */ + private function create_custom_submit_button(string $formId): string + { + return ''; // phpcs:ignore + } + + /** + * @param string $button + * @param array $form + * @return string + */ + // @phpcs:ignore + public function form_submit_button($button, $form): string + { + if ($this->is_this_field_works($form) && $this->is_this_form_needs_payment($form)) { + return '
    '; + } + + return $button; + } + + /** + * @param string $formId + * @param array $deps + * @return void + */ + public function custom_enqueue_scripts(string $formId, array $deps): void + { + wp_enqueue_script( + 'cryptopay_main_js', + GF_CRYPTOPAY_URL . 'assets/js/main.js', + array_merge($deps, ['jquery']), + GF_CRYPTOPAY_VERSION, + true + ); + + wp_localize_script( + 'cryptopay_main_js', + 'gf_cryptopay_vars', + array( + 'fieldId' => $this->id, + 'fieldInputId' => $this->field_input_id, + 'currency' => \GFCommon::get_currency(), + 'submitButton' => $this->create_custom_submit_button($formId), + 'pleaseFillForm' => esc_html__('Please fill in the required fields in the form before proceeding to the payment step!', 'gf-cryptopay'), // phpcs:ignore + ) + ); + } + + /** + * @param string $value + * @param bool $forceFrontendLabel + * @param array $form + * @return string + */ + // @phpcs:ignore + public function get_field_content($value, $forceFrontendLabel, $form): string + { + $formId = absint($form['id']); + $adminButtons = $this->get_admin_buttons(); + $isEntryDetail = $this->is_entry_detail(); + $isFormEditor = $this->is_form_editor(); + $isAdmin = $isEntryDetail || $isFormEditor; + $fieldLabel = $this->get_field_label($forceFrontendLabel, $value); + + if ($isAdmin) { + return sprintf( + "%s{FIELD}", + $adminButtons, + "input_{$this->id}", + esc_html($fieldLabel) + ); + } + + if (!$this->form_hash_total_field($form)) { + $msg = esc_html__('Please add a total field to your form for %s works.', 'gf-cryptopay'); + return sprintf($msg, $this->get_form_editor_field_title()); + } + + Hook::addFilter('theme', function () { + return $this->theme ?? 'light'; + }); + + $tx = $this->get_tx_with_user_and_form_id(strval($formId)); + $status = $this->is_this_form_needs_payment($form, $tx); + + if (!$status) { + return $this->create_hidden_tx_input($tx->hash); + } + + $html = $this->run(intval($formId)); + $html .= $this->create_hidden_tx_input(); + $this->custom_enqueue_scripts(strval($formId), []); + + return $html; + } + + /** + * @param string $value + * @param array $form + * @return string + */ + // @phpcs:ignore + public function validate($value, $form): void + { + $txHash = sanitize_text_field($_POST[$this->field_input_id] ?? ''); + + if (empty($txHash)) { + $this->failed_validation = true; + $msg = esc_html__('It looks like the payment was not completed!', 'gf-cryptopay'); + $this->validation_message = empty($this->errorMessage) ? $msg : $this->errorMessage; + } + } +} diff --git a/app/Gateways/CryptoPayLite.php b/app/Gateways/CryptoPayLite.php new file mode 100644 index 0000000..1a0bed6 --- /dev/null +++ b/app/Gateways/CryptoPayLite.php @@ -0,0 +1,52 @@ + $properties + */ + public function __construct(array $properties = []) + { + parent::__construct($properties); + } + + /** + * @return string + */ + public function get_form_editor_field_title(): string + { + return esc_attr__('CryptoPay Lite', 'gf-cryptopay'); + } + + /** + * @return string + */ + public function get_form_editor_field_description(): string + { + return esc_attr__('Adds cryptocurrency payments to your form.', 'gf-cryptopay'); + } + + /** + * @param int $formId + * @return string + */ + public function run(int $formId): string + { + return (new Payment('gravityforms'))->html(); + } +} diff --git a/app/Loader.php b/app/Loader.php index a78a454..ba8f875 100644 --- a/app/Loader.php +++ b/app/Loader.php @@ -4,6 +4,52 @@ namespace BeycanPress\CryptoPay\GravityForms; +use BeycanPress\CryptoPay\Integrator\Hook; +use BeycanPress\CryptoPay\Integrator\Helpers; + class Loader { + /** + * Loader constructor. + */ + public function __construct() + { + add_action('gform_loaded', [$this, 'register'], 5); + + Helpers::registerIntegration('gravityforms'); + Helpers::createTransactionPage( + esc_html__('GravityForms transactions', 'gf-cryptopay'), + 'gravityforms', + 10, + [], + ['orderId'] + ); + + Hook::addFilter('payment_redirect_urls_gravityforms', [$this, 'paymentRedirectUrls']); + } + + /** + * Payment redirect urls + * @param object $data + * @return array + */ + public function paymentRedirectUrls(object $data): array + { + return [ + 'success' => '#', + 'failed' => 'reload' + ]; + } + + /** + * @return void + */ + public function register(): void + { + if (Helpers::exists()) { + \GF_Fields::register(new Gateways\CryptoPayLite()); + } else { + \GF_Fields::register(new Gateways\CryptoPayLite()); + } + } } diff --git a/app/Models/TransactionsLite.php b/app/Models/TransactionsLite.php index 588e214..efc8d89 100644 --- a/app/Models/TransactionsLite.php +++ b/app/Models/TransactionsLite.php @@ -8,13 +8,31 @@ class TransactionsLite extends AbstractTransaction { - public string $addon = 'gravity_forms'; + public string $addon = 'gravityforms'; /** * @return void */ public function __construct() { - parent::__construct('gravity_forms_transaction'); + parent::__construct('gravityforms_transaction'); + } + + /** + * @param int $userId + * @param string $formId + * @return object|null + */ + public function findOneByUserAndFormId(int $userId, string $formId): ?object + { + return $this->getRow(str_ireplace( + ['%d', '%s'], + [$userId, $formId], + "SELECT * FROM {$this->tableName} + WHERE `userId` = %d + AND `params` LIKE '%{\"formId\":\"%s\"}%' + ORDER BY `id` DESC + LIMIT 1" + )); } } diff --git a/app/Models/TransactionsPro.php b/app/Models/TransactionsPro.php index e677ff8..99fa9dd 100644 --- a/app/Models/TransactionsPro.php +++ b/app/Models/TransactionsPro.php @@ -8,13 +8,31 @@ class TransactionsPro extends AbstractTransaction { - public string $addon = 'gravity_forms'; + public string $addon = 'gravityforms'; /** * @return void */ public function __construct() { - parent::__construct('gravity_forms_transaction'); + parent::__construct('gravityforms_transaction'); + } + + /** + * @param int $userId + * @param string $formId + * @return object + */ + public function findOneByUserAndFormId(int $userId, string $formId): object + { + return $this->getRow(str_ireplace( + ['%d', '%s'], + [$userId, $formId], + "SELECT * FROM {$this->tableName} + WHERE `userId` = %d + AND `params` LIKE '%{\"formId\":\"%s\"}%' + ORDER BY `id` DESC + LIMIT 1" + )); } } diff --git a/assets/images/icon.png b/assets/images/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1cb008991892c01b3bba67fe660f99cfde7c34c1 GIT binary patch literal 1789 zcmV3$g6h8O8c{81EY(cOfARt&N6aof>0#?Nm1O=1eNYVjs9@dNc4dfPgG>S!D(Y#LRuOd346x;ZkN z2jJJdu4Grfg@Qq3(>jyTqlgQYm|Z6_E)t`Y_)MbSLoPNIMDqX?=6j$Z9l~{zas?5a zg?C1hzQ=c}rBukp)Guk?!v+wNFM|)Y3;}?|{~iFNGe>(s*-lv9GpMwhB=Uf%K6qm~ zJm9qEC6y3YUZMWa{BFI48R0{4W?vLh^h(H?h|Nk+o&m}IC~-(pAPEm9GSyL7%Pm-D z+o@go8`M6fvM~&e0bo>^KO2^PjZL;XLL})@^LL_N$z|63nZu7WvRw-9F|D@b;z8nX zF74RAgfcQjLqHk^aIRo5l4&~*w8aJnK?dIELTn;qYzBntlIhO_*Agr%Sewrj_ESKq zT#CxLK&qN)0=GaA-6T~`q=cm0`XK58$j!A;Yi&14NTY#MJe}UEw2MC$Nooa=7iWneUn_)8FQRG98WgeMkwkH5M|Ux z=}M2?BdhxWupj^->0RnOWVt1zFfWxc zC1i*>)PLw+>-_1wbVX4-CIH!F08F~6Pf`}0JvM_$vC6CfGoBbf66f=&|M2s5;(0o^ z3m9<$JTyJ9mmyJ=Ui8$U5;}V%O_6GL(*RT;1VnLyksGeeqI1XGior7xze>zardxUr zB_|sVWi&Efp|LLvhxUUAfe^Ysk)BR2qSF9C3II@<^dbbc?u)u1$jNai?P80dti2Fo zE)5vAf==bTRVgwhqf!x5-kqKpN{Y+LDt?>Q{D)n2Xb&xe;{5 z9!srloZ<)mQ`>;>OqhSfZL>VUO8K42@BkWh&;5&a0hlpNN*ZD#)nRadF{PyZtsFY! zRz(1SQC%G#0JsEpK8rMzhOYkt8I^S4KnI&t;tk?HI(js}HY?tj19oP=1b4@ARDl>d zB1_qK001OH007e06aXzXFE<+%p>v){qf?61oc(FYfow2CnZIRZ<4I`ush5yIaS{OZ zaU-*|?fcy*!%PVDaZWS2jM+x62Xs9~UXv%XQN?9` zBerYp^Y?im;x@yjBICFqw?1uDmVLvX@z}Hu_3Z=;nDkc6b(wBljx3;zU^#*%ZH~BP zRZ~sA=x9+gV?LiWdef9KCEEI&G$e913@h{6D*(V%)3((GkeTC%aPj~TNIBP+{_LeTP7)zt-*17K&JE>Tp8#4c>LbTMO$ziGRx|E z!@TRQW(A>>a5&^CA{*MMz{0L`DSV=$zzR-VZ03vTHh}hIt@kcVwhd^(83v9SZ{F zLUA#utrSL&z&nJo=Yj-vN*8*TgV|086>Y@-1XN9YsDly;%dS%C1Iln!)JNVZ5joxK zJK8jLGY||k(<;!LSnk$^&)2E)M$`@3>=F^P*LKmg`W+FR&Saq>*m&>K*Z-<*b!`yg znQ+1;HKMIPOe47#7p;}yxGRLu5tx7>u$EDu=nUR)d%+oH`p>D8B)U%YykI=5y~(J`%5$;aPiv7T@-uaBwu f0GeP`bGG~ox~>FH!;uqP00000NkvXXu0mjfEe$7T literal 0 HcmV?d00001 diff --git a/assets/images/icon.svg b/assets/images/icon.svg new file mode 100644 index 0000000..92cb2af --- /dev/null +++ b/assets/images/icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/js/main.js b/assets/js/main.js new file mode 100644 index 0000000..44af647 --- /dev/null +++ b/assets/js/main.js @@ -0,0 +1,85 @@ +;(($) => { + $(document).ready(() => { + let startedApp; + let oldAmount = 0; + const currency = gf_cryptopay_vars.currency; + const submitButton = gf_cryptopay_vars.submitButton; + const fieldInputId = gf_cryptopay_vars.fieldInputId; + + $(".gform_body [aria-required='true']").each(function() { + $(this).attr('required', true); + }); + + const paymentCompleted = async (ctx, formId) => { + const form = $('#gform_' + formId); + const helpers = window.cpHelpers || window.cplHelpers; + const txHash = ctx.transaction.hash || ctx.transaction.id; + + console.log(ctx) + // Modal yapısına geçilecek ve manuel olarak required alan kontrolü yapılacak + // Create temporary payment completed record + // Submit form + // entry'ler ile transactionlar ilişkilendirilecek, + // eğer bir kullanıcıya ve form id'sine ait tx varsa ödeme yapılmıştır sayılacak + // ve entry oluşturulduğunda tx ile ilişkilendirilecek + // eğer yoksa ödeme yapılması zorunlu olacak + helpers.closePopup(); + await helpers.sleep(100); + helpers.successPopup('Payment completed successfully!').then(() => { + $('.overlay').remove(); + startedApp.store.payment.$reset(); + $('#cryptopay, #cryptopay-lite').remove(); + + // scroll to form + const wrapperOffset = $('.gform_wrapper').offset().top; + $('html, body').animate({scrollTop: wrapperOffset}, 1000); + + // set tx hash to hidden input + $('#' + fieldInputId).val(txHash); + $('#' + fieldInputId).closest('.gfield').hide(); + + // submit form + form.find('#custom-submit-placeholder').append(submitButton); + form.submit(); + }); + } + + gform?.addFilter('gform_product_total', function (amount, formId) { + if (amount !== oldAmount) { + oldAmount = amount; + if (window.CryptoPayApp) { + CryptoPayApp.events.add('confirmationCompleted', async (ctx) => { + paymentCompleted(ctx, formId); + }, 'gravity_forms'); + if (!startedApp) { + startedApp = window.CryptoPayApp.start({ + amount, + currency, + }, { formId }); + } else { + startedApp.reStart({ + amount, + currency, + }, { formId }) + } + } else if (window.CryptoPayLiteApp) { + CryptoPayLiteApp.events.add('confirmationCompleted', async (ctx) => { + paymentCompleted(ctx, formId); + }, 'gravity_forms'); + if (!startedApp) { + startedApp = window.CryptoPayLiteApp.start({ + amount, + currency, + }, { formId }); + } else { + startedApp.reStart({ + amount, + currency, + }, { formId }) + } + } + } + return amount; + }); + }); +})(jQuery); \ No newline at end of file diff --git a/gravity-forms-cryptopay-gateway.php b/gravity-forms-cryptopay-gateway.php index 5da5431..510b290 100644 --- a/gravity-forms-cryptopay-gateway.php +++ b/gravity-forms-cryptopay-gateway.php @@ -18,7 +18,7 @@ * Author URI: https://beycanpress.com * License: GPLv3 * License URI: https://www.gnu.org/licenses/gpl-3.0.html - * Text Domain: md-cryptopay + * Text Domain: gf-cryptopay * Tags: Cryptopay, Cryptocurrency, WooCommerce, WordPress, MetaMask, Trust, Binance, Wallet, Ethereum, Bitcoin, Binance smart chain, Payment, Plugin, Gateway, Moralis, Converter, API, coin market cap, CMC * Requires at least: 5.0 * Tested up to: 6.4.3 @@ -28,50 +28,36 @@ // Autoload require_once __DIR__ . '/vendor/autoload.php'; -use BeycanPress\CryptoPay\Integrator\Helpers; - define('GF_CRYPTOPAY_FILE', __FILE__); define('GF_CRYPTOPAY_VERSION', '1.0.0'); +define('GF_CRYPTOPAY_KEY', basename(__DIR__)); define('GF_CRYPTOPAY_URL', plugin_dir_url(__FILE__)); define('GF_CRYPTOPAY_DIR', plugin_dir_path(__FILE__)); +define('GF_CRYPTOPAY_SLUG', plugin_basename(__FILE__)); -/** - * @return void - */ -function gf_cryptopay_addModels(): void -{ - Helpers::registerModel(BeycanPress\CryptoPay\GravityForms\Models\TransactionsPro::class); - Helpers::registerLiteModel(BeycanPress\CryptoPay\GravityForms\Models\TransactionsLite::class); -} - -gf_cryptopay_addModels(); - -add_action('plugins_loaded', function (): void { - - gf_cryptopay_addModels(); - - load_plugin_textdomain('md-cryptopay', false, basename(__DIR__) . '/languages'); - - if (!defined('GF_MIN_WP_VERSION')) { - add_action('admin_notices', function (): void { - ?> -
    -

    ' . esc_html__('clicking here', 'md-cryptopay') . ''); ?>

    -
    - -
    -

    ' . esc_html__('clicking here', 'md-cryptopay') . ''); ?>

    -
    - +
    +

    ' . esc_html__('clicking here', 'gf-cryptopay') . ''); ?>

    +
    + +
    +

    ' . esc_html__('clicking here', 'gf-cryptopay') . ''); ?>

    +
    + register(true); diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index b1f82be..3fd9eb1 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -4,7 +4,7 @@ namespace Composer\Autoload; -class ComposerStaticInit6be0de7c2c544c6b51cbdeae0bbe23be +class ComposerStaticInitf99ffda5f6e370daee8d691b9e8af453 { public static $prefixLengthsPsr4 = array ( 'B' => @@ -32,9 +32,9 @@ class ComposerStaticInit6be0de7c2c544c6b51cbdeae0bbe23be public static function getInitializer(ClassLoader $loader) { return \Closure::bind(function () use ($loader) { - $loader->prefixLengthsPsr4 = ComposerStaticInit6be0de7c2c544c6b51cbdeae0bbe23be::$prefixLengthsPsr4; - $loader->prefixDirsPsr4 = ComposerStaticInit6be0de7c2c544c6b51cbdeae0bbe23be::$prefixDirsPsr4; - $loader->classMap = ComposerStaticInit6be0de7c2c544c6b51cbdeae0bbe23be::$classMap; + $loader->prefixLengthsPsr4 = ComposerStaticInitf99ffda5f6e370daee8d691b9e8af453::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInitf99ffda5f6e370daee8d691b9e8af453::$prefixDirsPsr4; + $loader->classMap = ComposerStaticInitf99ffda5f6e370daee8d691b9e8af453::$classMap; }, null, ClassLoader::class); } diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index c33edb1..8fb6649 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -3,7 +3,7 @@ 'name' => '__root__', 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '1d6c97eb14b0638b33294e9255ee7948b8772218', + 'reference' => '46ce28210b987ff83dafb47a621676fd873c6f6f', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -13,7 +13,7 @@ '__root__' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '1d6c97eb14b0638b33294e9255ee7948b8772218', + 'reference' => '46ce28210b987ff83dafb47a621676fd873c6f6f', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(),