add membership system

This commit is contained in:
Hesabix 2025-03-07 19:59:24 +00:00
parent 7a3bcbf086
commit 9a24e4a675
407 changed files with 375 additions and 10296 deletions

View file

@ -15,8 +15,6 @@
"doctrine/doctrine-migrations-bundle": "^3.2",
"doctrine/orm": "^2.14",
"dompdf/dompdf": "^2.0",
"friendsofsymfony/ckeditor-bundle": "*",
"gregwar/captcha-bundle": "^2.2",
"melipayamak/php": "1.0.0",
"mpdf/mpdf": "^8.2",
"nelmio/api-doc-bundle": "^4.34",
@ -86,8 +84,7 @@
"scripts": {
"auto-scripts": {
"cache:clear": "symfony-cmd",
"assets:install %PUBLIC_DIR%": "symfony-cmd",
"ckeditor:install --tag=4.22.1": "symfony-cmd"
"assets:install %PUBLIC_DIR%": "symfony-cmd"
},
"post-install-cmd": [
"@auto-scripts"

View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "cad0936f39dcdd676939ccbf7de779e9",
"content-hash": "e638a5251ea627f595280beb30b3838f",
"packages": [
{
"name": "brick/math",
@ -1729,212 +1729,6 @@
},
"time": "2024-11-01T03:51:45+00:00"
},
{
"name": "friendsofsymfony/ckeditor-bundle",
"version": "2.6.0",
"source": {
"type": "git",
"url": "https://github.com/FriendsOfSymfony/FOSCKEditorBundle.git",
"reference": "dc0f0dc1ba328e0adf5df0a37f1676b6072f46de"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/FriendsOfSymfony/FOSCKEditorBundle/zipball/dc0f0dc1ba328e0adf5df0a37f1676b6072f46de",
"reference": "dc0f0dc1ba328e0adf5df0a37f1676b6072f46de",
"shasum": ""
},
"require": {
"ext-json": "*",
"ext-zip": "*",
"php": "^8.0",
"symfony/asset": "^5.4 || ^6.0 || ^7.0",
"symfony/config": "^5.4 || ^6.0 || ^7.0",
"symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0",
"symfony/expression-language": "^5.4 || ^6.0 || ^7.0",
"symfony/form": "^5.4 || ^6.0 || ^7.0",
"symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0",
"symfony/http-foundation": "^5.4 || ^6.0 || ^7.0",
"symfony/http-kernel": "^5.4 || ^6.0 || ^7.0",
"symfony/options-resolver": "^5.4 || ^6.0 || ^7.0",
"symfony/property-access": "^5.4 || ^6.0 || ^7.0",
"symfony/routing": "^5.4 || ^6.0 || ^7.0",
"symfony/twig-bundle": "^5.4 || ^6.0 || ^7.0",
"twig/twig": "^2.4 || ^3.0"
},
"conflict": {
"sebastian/environment": "<1.3.4",
"sebastian/exporter": "<2.0.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.41",
"matthiasnoback/symfony-dependency-injection-test": "^4.0 || ^5.0",
"phpunit/phpunit": "^9.6",
"symfony/console": "^5.4 || ^6.0 || ^7.0",
"symfony/phpunit-bridge": "^5.4 || ^6.0 || ^7.0",
"symfony/yaml": "^5.4 || ^6.0 || ^7.0"
},
"suggest": {
"egeloen/form-extra-bundle": "Allows to load CKEditor asynchronously"
},
"type": "symfony-bundle",
"extra": {
"branch-alias": {
"dev-master": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"FOS\\CKEditorBundle\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Eric GELOEN",
"email": "geloen.eric@gmail.com"
},
{
"name": "FriendsOfSymfony Community",
"homepage": "https://github.com/FriendsOfSymfony/FOSCKEditorBundle/graphs/contributors"
}
],
"description": "Provides a CKEditor integration for your Symfony project.",
"keywords": [
"CKEditor"
],
"support": {
"issues": "https://github.com/FriendsOfSymfony/FOSCKEditorBundle/issues",
"source": "https://github.com/FriendsOfSymfony/FOSCKEditorBundle/tree/2.6.0"
},
"time": "2025-01-13T15:11:41+00:00"
},
{
"name": "gregwar/captcha",
"version": "v1.2.1",
"source": {
"type": "git",
"url": "https://github.com/Gregwar/Captcha.git",
"reference": "229d3cdfe33d6f1349e0aec94a26e9205a6db08e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Gregwar/Captcha/zipball/229d3cdfe33d6f1349e0aec94a26e9205a6db08e",
"reference": "229d3cdfe33d6f1349e0aec94a26e9205a6db08e",
"shasum": ""
},
"require": {
"ext-gd": "*",
"ext-mbstring": "*",
"php": ">=5.3.0",
"symfony/finder": "*"
},
"require-dev": {
"phpunit/phpunit": "^6.4"
},
"type": "library",
"autoload": {
"psr-4": {
"Gregwar\\": "src/Gregwar"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Grégoire Passault",
"email": "g.passault@gmail.com",
"homepage": "http://www.gregwar.com/"
},
{
"name": "Jeremy Livingston",
"email": "jeremy.j.livingston@gmail.com"
}
],
"description": "Captcha generator",
"homepage": "https://github.com/Gregwar/Captcha",
"keywords": [
"bot",
"captcha",
"spam"
],
"support": {
"issues": "https://github.com/Gregwar/Captcha/issues",
"source": "https://github.com/Gregwar/Captcha/tree/v1.2.1"
},
"time": "2023-09-26T13:45:37+00:00"
},
{
"name": "gregwar/captcha-bundle",
"version": "v2.3.0",
"source": {
"type": "git",
"url": "https://github.com/Gregwar/CaptchaBundle.git",
"reference": "8eb95c0911a1db9e3b2f368f6319e0945b959a6c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Gregwar/CaptchaBundle/zipball/8eb95c0911a1db9e3b2f368f6319e0945b959a6c",
"reference": "8eb95c0911a1db9e3b2f368f6319e0945b959a6c",
"shasum": ""
},
"require": {
"ext-gd": "*",
"gregwar/captcha": "^1.2.1",
"php": ">=8.0.2",
"symfony/form": "~6.0|~7.0",
"symfony/framework-bundle": "~6.0|~7.0",
"symfony/translation": "~6.0|^7.0",
"twig/twig": "^3.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.45",
"phpstan/phpstan": "^1.10",
"symplify/easy-coding-standard": "^12"
},
"type": "symfony-bundle",
"autoload": {
"psr-4": {
"Gregwar\\CaptchaBundle\\": "/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Grégoire Passault",
"email": "g.passault@gmail.com",
"homepage": "https://www.gregwar.com/"
},
{
"name": "Jeremy Livingston",
"email": "jeremy.j.livingston@gmail.com"
}
],
"description": "Captcha bundle",
"homepage": "https://github.com/Gregwar/CaptchaBundle",
"keywords": [
"Symfony2",
"bot",
"captcha",
"code",
"security",
"spam",
"symfony",
"visual"
],
"support": {
"issues": "https://github.com/Gregwar/CaptchaBundle/issues",
"source": "https://github.com/Gregwar/CaptchaBundle/tree/v2.3.0"
},
"time": "2024-06-06T13:14:57+00:00"
},
{
"name": "maennchen/zipstream-php",
"version": "3.1.2",
@ -5447,16 +5241,16 @@
},
{
"name": "symfony/flex",
"version": "v2.4.7",
"version": "v2.5.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/flex.git",
"reference": "92f4fba342161ff36072bd3b8e0b3c6c23160402"
"reference": "8ce1acd9842abe0e9b4c4a0bd3f259859516c018"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/flex/zipball/92f4fba342161ff36072bd3b8e0b3c6c23160402",
"reference": "92f4fba342161ff36072bd3b8e0b3c6c23160402",
"url": "https://api.github.com/repos/symfony/flex/zipball/8ce1acd9842abe0e9b4c4a0bd3f259859516c018",
"reference": "8ce1acd9842abe0e9b4c4a0bd3f259859516c018",
"shasum": ""
},
"require": {
@ -5495,7 +5289,7 @@
"description": "Composer plugin for Symfony",
"support": {
"issues": "https://github.com/symfony/flex/issues",
"source": "https://github.com/symfony/flex/tree/v2.4.7"
"source": "https://github.com/symfony/flex/tree/v2.5.0"
},
"funding": [
{
@ -5511,7 +5305,7 @@
"type": "tidelift"
}
],
"time": "2024-10-07T08:51:54+00:00"
"time": "2025-03-03T07:50:46+00:00"
},
{
"name": "symfony/form",
@ -9557,16 +9351,16 @@
},
{
"name": "zircote/swagger-php",
"version": "5.0.5",
"version": "5.0.6",
"source": {
"type": "git",
"url": "https://github.com/zircote/swagger-php.git",
"reference": "2eb4005840058d8844a0bcc14403932331331068"
"reference": "ea60f1439aa4fefba230a4386a403eeb1ee52f08"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/zircote/swagger-php/zipball/2eb4005840058d8844a0bcc14403932331331068",
"reference": "2eb4005840058d8844a0bcc14403932331331068",
"url": "https://api.github.com/repos/zircote/swagger-php/zipball/ea60f1439aa4fefba230a4386a403eeb1ee52f08",
"reference": "ea60f1439aa4fefba230a4386a403eeb1ee52f08",
"shasum": ""
},
"require": {
@ -9637,9 +9431,9 @@
],
"support": {
"issues": "https://github.com/zircote/swagger-php/issues",
"source": "https://github.com/zircote/swagger-php/tree/5.0.5"
"source": "https://github.com/zircote/swagger-php/tree/5.0.6"
},
"time": "2025-02-24T00:48:00+00:00"
"time": "2025-03-05T19:40:05+00:00"
}
],
"packages-dev": [

View file

@ -12,8 +12,6 @@ return [
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
Gregwar\CaptchaBundle\GregwarCaptchaBundle::class => ['all' => true],
FOS\CKEditorBundle\FOSCKEditorBundle::class => ['all' => true],
Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true],
Nelmio\ApiDocBundle\NelmioApiDocBundle::class => ['all' => true],
];

View file

@ -1,9 +1,7 @@
doctrine:
dbal:
url: '%env(resolve:DATABASE_URL)%'
# IMPORTANT: You MUST configure your server version,
# either here or in the DATABASE_URL env var (see .env file)
#server_version: '15'
orm:
auto_generate_proxy_classes: false
enable_lazy_ghost_objects: true
@ -17,6 +15,8 @@ doctrine:
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: App
type: attribute
mapping: true
dql:
string_functions:
CAST: App\Doctrine\Cast
@ -24,7 +24,6 @@ doctrine:
when@test:
doctrine:
dbal:
# "TEST_TOKEN" is typically set by ParaTest
dbname_suffix: '_test%env(default::TEST_TOKEN)%'
when@prod:

View file

@ -17,13 +17,13 @@ services:
$lockFactory: '@Symfony\Component\Lock\LockFactory'
tags:
- { name: 'console.command' }
App\Command\ReleaseUpdateLockCommand:
arguments:
$lockFactory: '@Symfony\Component\Lock\LockFactory'
tags:
- { name: 'console.command' }
# تنظیمات Lock
Symfony\Component\Lock\LockFactory:
arguments:
$store: '@lock.store.flock'
@ -33,7 +33,6 @@ services:
arguments:
- '%kernel.project_dir%/var/lock'
# سایر سرویس‌ها
App\:
resource: '../src/'
exclude:
@ -45,10 +44,19 @@ services:
class: Doctrine\ORM\Mapping\Driver\AttributeDriver
arguments:
- [ '%kernel.project_dir%/src/Entity' ]
- true
- true # تنظیم reportFieldsWhereDeclared روی true برای رفع Deprecation
tags:
- { name: doctrine.orm.mapping_driver }
App\EventListener\DoctrineExceptionListener:
arguments:
$kernel: '@kernel'
$logger: '@logger'
$lockFactory: '@lock.default.factory'
$entityManager: '@doctrine.orm.default_entity_manager'
tags:
- { name: kernel.event_listener, event: kernel.exception }
App\Security\AuthenticationFailureHandler:
arguments:
$captchaService: '@App\Service\CaptchaService'

View file

@ -157,7 +157,9 @@ class PluginController extends AbstractController
* ),
* @OA\Response(response=200, description="پرداخت موفق و فعال‌سازی افزونه"),
* @OA\Response(response=400, description="پرداخت ناموفق"),
* @OA\Response(response=404, description="افزونه یافت نشد")
* @OA\Response(response=404, description="افزونه یافت نشد"),
* @OA\Response(response=405, description="پرداخت ناموفق"),
* )
*/
#[Route('/api/plugin/buy/verify/{id}', name: 'api_plugin_buy_verify', requirements: ['id' => '.+'])]

View file

@ -0,0 +1,147 @@
<?php
namespace App\Controller\Plugins\Membership;
use App\Entity\User;
use App\Service\Jdate;
use App\Service\Extractor;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Attribute\Route;
use Doctrine\ORM\EntityManagerInterface;
final class MembershipController extends AbstractController
{
private $entityManager;
private $jdate;
private $extractor;
public function __construct(EntityManagerInterface $entityManager, Jdate $jdate, Extractor $extractor)
{
$this->entityManager = $entityManager;
$this->jdate = $jdate;
$this->extractor = $extractor;
}
#[Route('/api/membership/stats', name: 'api_membership_stats', methods: ['GET'])]
public function getMembershipStats(): JsonResponse
{
$user = $this->getUser();
if (!$user) {
return new JsonResponse($this->extractor->operationFail('User not authenticated'), 401);
}
$userRepo = $this->entityManager->getRepository(User::class);
$currentTime = time();
// تاریخ‌های شمسی
$todayStart = $this->jdate->jdate('Ymd', $currentTime, '', 'Asia/Tehran', 'en') . '000000';
$todayStartTimestamp = $this->jdate->jmktime(0, 0, 0, substr($todayStart, 4, 2), substr($todayStart, 6, 2), substr($todayStart, 0, 4));
$monthStart = $this->jdate->jdate('Ym01', $currentTime, '', 'Asia/Tehran', 'en') . '000000';
$monthStartTimestamp = $this->jdate->jmktime(0, 0, 0, substr($monthStart, 4, 2), 1, substr($monthStart, 0, 4));
$yearStart = $this->jdate->jdate('Y0101', $currentTime, '', 'Asia/Tehran', 'en') . '000000';
$yearStartTimestamp = $this->jdate->jmktime(0, 0, 0, 1, 1, substr($yearStart, 0, 4));
// آمار (فقط کاربران فعال)
$stats = [
'joinedToday' => (int) $userRepo->createQueryBuilder('u')
->where('u.invitedBy = :user')
->andWhere('CAST(u.dateRegister AS UNSIGNED) >= :start')
->andWhere('u.active = :active')
->setParameter('user', $user)
->setParameter('start', $todayStartTimestamp)
->setParameter('active', true)
->select('COUNT(u.id)')
->getQuery()
->getSingleScalarResult(),
'joinedThisMonth' => (int) $userRepo->createQueryBuilder('u')
->where('u.invitedBy = :user')
->andWhere('CAST(u.dateRegister AS UNSIGNED) >= :start')
->andWhere('u.active = :active')
->setParameter('user', $user)
->setParameter('start', $monthStartTimestamp)
->setParameter('active', true)
->select('COUNT(u.id)')
->getQuery()
->getSingleScalarResult(),
'joinedThisYear' => (int) $userRepo->createQueryBuilder('u')
->where('u.invitedBy = :user')
->andWhere('CAST(u.dateRegister AS UNSIGNED) >= :start')
->andWhere('u.active = :active')
->setParameter('user', $user)
->setParameter('start', $yearStartTimestamp)
->setParameter('active', true)
->select('COUNT(u.id)')
->getQuery()
->getSingleScalarResult(),
'totalInvited' => (int) $userRepo->createQueryBuilder('u')
->where('u.invitedBy = :user')
->andWhere('u.active = :active')
->setParameter('user', $user)
->setParameter('active', true)
->select('COUNT(u.id)')
->getQuery()
->getSingleScalarResult(),
];
// کاربران اخیر (همه کاربران، چه فعال و چه غیرفعال)
$recentUsers = $userRepo->createQueryBuilder('u')
->where('u.invitedBy = :user')
->setParameter('user', $user)
->orderBy('u.dateRegister', 'DESC')
->setMaxResults(10)
->select('u.email, u.fullName, u.dateRegister, u.active')
->getQuery()
->getArrayResult();
// چارت ۶ ماه گذشته (فقط کاربران فعال)
$sixMonthsAgo = $this->jdate->jmktime(0, 0, 0, $this->jdate->jdate('m', $currentTime, '', 'Asia/Tehran', 'en') - 5, 1, $this->jdate->jdate('Y', $currentTime, '', 'Asia/Tehran', 'en'));
$query = $userRepo->createQueryBuilder('u')
->where('u.invitedBy = :user')
->andWhere('CAST(u.dateRegister AS UNSIGNED) >= :start')
->andWhere('u.active = :active')
->setParameter('user', $user)
->setParameter('start', $sixMonthsAgo)
->setParameter('active', true)
->select('u.dateRegister')
->orderBy('u.dateRegister', 'ASC')
->getQuery()
->getArrayResult();
$monthlyData = [];
foreach ($query as $row) {
$date = (int) $row['dateRegister'];
$jDate = $this->jdate->jdate('Ym', $date, '', 'Asia/Tehran', 'en');
$monthlyData[$jDate] = ($monthlyData[$jDate] ?? 0) + 1;
}
$months = [];
$users = [];
$currentJMonth = (int) $this->jdate->jdate('m', $sixMonthsAgo, '', 'Asia/Tehran', 'en');
$currentJYear = (int) $this->jdate->jdate('Y', $sixMonthsAgo, '', 'Asia/Tehran', 'en');
for ($i = 0; $i < 6; $i++) {
$monthName = $this->jdate->jdate('F', $this->jdate->jmktime(0, 0, 0, $currentJMonth, 1, $currentJYear));
$months[] = $monthName;
$key = sprintf('%04d%02d', $currentJYear, $currentJMonth);
$users[] = $monthlyData[$key] ?? 0;
$currentJMonth++;
if ($currentJMonth > 12) {
$currentJMonth = 1;
$currentJYear++;
}
}
$chart = [
'months' => $months,
'users' => $users,
];
return new JsonResponse($this->extractor->operationSuccess([
'stats' => $stats,
'recentUsers' => $recentUsers,
'chart' => $chart,
]));
}
}

View file

@ -208,14 +208,21 @@ class UserController extends AbstractController
#[Route('/api/user/current/info', name: 'api_user_current_info')]
public function api_user_current_info(#[CurrentUser] ?User $user, Provider $provider, EntityManagerInterface $entityManager): Response
{
return $this->json([
$result = [
'id' => $user->getId(),
'email' => $user->getEmail(),
'fullname' => $user->getFullName(),
'businessCount' => count($user->getBusinesses()),
'hash_email' => $provider->gravatarHash($user->getEmail()),
'mobile' => $user->getMobile()
]);
'mobile' => $user->getMobile(),
];
if (!$user->getInvateCode()) {
$user->setInvateCode($this->RandomString(7));
$entityManager->persist($user);
$entityManager->flush();
}
$result['invateCode'] = $user->getInvateCode();
return $this->json($result);
}
#[Route('/api2/user/current/info', name: 'api2_user_current_info')]
@ -358,6 +365,16 @@ class UserController extends AbstractController
)
);
$user->setActive(false);
//چک کردن کد معرف
$invateCode = $params['inviteCode'];
if ($invateCode != '0') {
$invater = $entityManager->getRepository(User::class)->findOneBy(['invateCode' => $invateCode]);
if ($invater) {
$user->setInvitedBy($invater);
}
}
$entityManager->persist($user);
$entityManager->flush();
@ -382,7 +399,6 @@ class UserController extends AbstractController
} catch (Exception $exception) {
// خطای ارسال ایمیل رو می‌تونید لاگ کنید، فعلاً نادیده می‌گیره
}
return $this->json($extractor->operationSuccess([
'id' => $user->getId()
]));

View file

@ -113,6 +113,12 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
#[ORM\OneToMany(mappedBy: 'submitter', targetEntity: DashboardSettings::class, orphanRemoval: true)]
private Collection $dashboardSettings;
#[ORM\Column(length: 20, nullable: true)]
private ?string $invateCode = null;
#[ORM\ManyToOne(targetEntity: self::class)]
private ?self $invitedBy = null;
public function __construct()
{
$this->userTokens = new ArrayCollection();
@ -856,4 +862,28 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
return $this;
}
public function getInvateCode(): ?string
{
return $this->invateCode;
}
public function setInvateCode(?string $invateCode): static
{
$this->invateCode = $invateCode;
return $this;
}
public function getInvitedBy(): ?self
{
return $this->invitedBy;
}
public function setInvitedBy(?self $invitedBy): static
{
$this->invitedBy = $invitedBy;
return $this;
}
}

View file

@ -0,0 +1,127 @@
<?php
namespace App\EventListener;
use Doctrine\DBAL\Exception\InvalidFieldNameException;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Tools\Console\Command\SchemaTool\UpdateCommand;
use Doctrine\ORM\Tools\Console\EntityManagerProvider\SingleManagerProvider;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Bundle\FrameworkBundle\Console\Application as SymfonyApplication;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Lock\LockFactory;
class DoctrineExceptionListener
{
private $kernel;
private $logger;
private $lockFactory;
private $entityManager;
public function __construct(
KernelInterface $kernel,
LoggerInterface $logger,
LockFactory $lockFactory,
EntityManagerInterface $entityManager
) {
$this->kernel = $kernel;
$this->logger = $logger;
$this->lockFactory = $lockFactory;
$this->entityManager = $entityManager;
}
public function onKernelException(ExceptionEvent $event)
{
$exception = $event->getThrowable();
if (!$exception instanceof InvalidFieldNameException) {
return;
}
$request = $event->getRequest();
$attemptCount = $request->attributes->getInt('_schema_update_attempts', 0);
if ($attemptCount >= 1) {
$this->logger->warning('Schema update already attempted for this request, skipping.', [
'attempt' => $attemptCount,
]);
return;
}
$this->logger->error('Database schema error occurred: ' . $exception->getMessage(), [
'exception' => $exception,
'trace' => $exception->getTraceAsString(),
]);
$lock = $this->lockFactory->createLock('schema_update_lock', 30);
if (!$lock->acquire()) {
$this->logger->info('Waiting for schema update lock to be released.');
$lock->acquire(true); // Blocking wait
$response = $this->kernel->handle($request);
$this->logger->info('Request handled after waiting for schema update.', [
'status_code' => $response->getStatusCode(),
]);
$event->setResponse($response);
$lock->release();
return;
}
try {
$application = new SymfonyApplication($this->kernel);
$application->setAutoExit(false);
$command = new UpdateCommand(new SingleManagerProvider($this->entityManager));
$application->add($command);
$input = new ArrayInput([
'command' => 'doctrine:schema:update',
'--force' => true,
'--complete' => true, // برای سازگاری با DBAL 4 در آینده
]);
$output = new BufferedOutput();
$exitCode = $application->run($input, $output);
$outputContent = $output->fetch();
$this->logger->info('Schema update executed.', [
'attempt' => $attemptCount + 1,
'exit_code' => $exitCode,
'output' => $outputContent,
]);
if ($exitCode !== 0) {
$event->setResponse(new Response(
'Failed to update database schema: ' . $outputContent,
Response::HTTP_INTERNAL_SERVER_ERROR
));
return;
}
$request->attributes->set('_schema_update_attempts', $attemptCount + 1);
$response = $this->kernel->handle($request);
$this->logger->info('Request handled successfully after schema update.', [
'attempt' => $attemptCount + 1,
'status_code' => $response->getStatusCode(),
]);
$event->setResponse($response);
} catch (\Exception $e) {
$this->logger->critical('Exception during schema update: ' . $e->getMessage(), [
'exception' => $e,
'trace' => $e->getTraceAsString(),
]);
$event->setResponse(new Response(
'A critical error occurred while updating the schema: ' . $e->getMessage(),
Response::HTTP_INTERNAL_SERVER_ERROR
));
} finally {
$lock->release();
$this->logger->debug('Schema update lock released.');
}
}
}

View file

@ -35,21 +35,6 @@
"./migrations/.gitignore"
]
},
"friendsofsymfony/ckeditor-bundle": {
"version": "2.4",
"recipe": {
"repo": "github.com/symfony/recipes-contrib",
"branch": "main",
"version": "2.0",
"ref": "f5ad42002183a6881962683e6d84bbb25cdfce5d"
},
"files": [
"./config/packages/fos_ckeditor.yaml"
]
},
"gregwar/captcha-bundle": {
"version": "v2.2.0"
},
"nelmio/api-doc-bundle": {
"version": "4.34",
"recipe": {

View file

@ -0,0 +1,20 @@
<!DOCTYPE html>
<title>Hello MembershipController!</title>
{% block body %}
<style>
.example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
.example-wrapper code { background: #F5F5F5; padding: 2px 6px; }
</style>
<div class="example-wrapper">
<h1>Hello {{ controller_name }}! ✅</h1>
This friendly message is coming from:
<ul>
<li>Your controller at <code>/var/www/html/next.hesabix.ir/hesabixCore/src/Controller/MembershipController.php</code></li>
<li>Your template at <code>/var/www/html/next.hesabix.ir/hesabixCore/templates/membership/index.html.twig</code></li>
</ul>
</div>
{% endblock %}

View file

@ -1 +0,0 @@
.*/**

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,82 +0,0 @@
CKEditor 4 - Releases
=====================
## Releases Code
This repository contains the official release versions of [CKEditor 4](https://ckeditor.com/ckeditor-4/).
There are four versions for each release &mdash; `standard-all`, `basic`, `standard`, and `full`.
They differ in the number of plugins that are compiled into the main `ckeditor.js` file as well as the toolbar configuration.
See the [comparison](https://ckeditor.com/cke4/presets) of the `basic`, `standard`, and `full` installation presets for more details.
The `standard-all` build includes all official CKSource plugins with only those from the `standard` installation preset compiled into the `ckeditor.js` file and enabled in the configuration.
All versions available in this repository were built using [CKBuilder](https://ckeditor.com/cke4/builder), so they are optimized and ready to be used in a production environment.
## Documentation
Developer documentation for CKEditor is available online at: <https://ckeditor.com/docs/>.
## Installation
### Git clone
To install one of the available releases, just clone this repository and switch to the respective branch (see next section):
git clone -b <release branch> git://github.com/ckeditor/ckeditor4-releases.git
### Git submodule
If you are using git for your project and you want to integrate CKEditor, we recommend to add this repository as a
[submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules).
git submodule add -b <release branch> git://github.com/ckeditor/ckeditor-releases.git <clone dir>
git commit -m "Added CKEditor submodule in <clone dir> directory."
### Using Package Managers
See the [Installing CKEditor with Package Managers](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_package_managers.html) article for more details about installing CKEditor with [Bower](https://bower.io), [Composer](https://getcomposer.org/) and [npm](https://www.npmjs.com/).
## Repository Structure
### Branches
This repository contains the following branches:
- `master` and `latest` &ndash; the latest release of the `standard-all` preset (including betas).
- `stable` &ndash; the latest stable release of the `standard-all` preset (non-beta).
- `A.B.x` (e.g. `4.3.x`) &ndash; the latest release of the `standard-all` preset in the `A.B` branch.
- `(basic|standard|full)/stable` &ndash; the latest stable release tag point (non-beta).
- `(basic|standard|full)/latest` &ndash; the latest release tag point (including betas).
- `(basic|standard|full)/A.B.x` (e.g. `basic/4.0.x`) &ndash; the latest releases in the `A.B` branch.
### Tags
**Since version 4.3.3** this repository uses the following tag naming rules:
- `x.y.z` &ndash; contains the `standard-all` editor build, e.g. `4.3.3`, `4.4.0` etc.
- `(basic|standard|full)/x.y.z` &ndash; contains the editor build with a given preset, e.g. `basic/4.3.3`.
The version numbers follow the [Semantic Versioning 2.0.0](http://semver.org/) scheme.
Up to version **4.3.2** the tags were released in the following form `x.y[.z]/(basic|standard|full)`.
For example: `4.0/basic`, `4.0.1/standard`. This convention was changed in CKEditor 4.3.3 to conform to the Semantic Versioning scheme.
## Checking Your Installation
The editor comes with a few sample pages that can be used to verify if the installation succeeded. Take a look at the `samples` directory.
To test your installation, just call the following page for your website:
http://<your site>/<CKEditor installation path>/samples/index.html
For example:
http://www.example.com/ckeditor/samples/index.html
### License
Licensed under the GPL, LGPL, and MPL licenses, at your choice.
Please check the `LICENSE.md` file for more information about the license.

View file

@ -1,10 +0,0 @@
# Reporting a security issues
If you believe you have found a security issue in the CKEditor 4 software, please contact us immediately.
When reporting a potential security problem, please bear this in mind:
* Make sure to provide as many details as possible about the vulnerability.
* Please do not disclose publicly any security issues until we fix them and publish security releases.
Contact the security team at security@cksource.com. As soon as we receive the security report, we will work promptly to confirm the issue and then to provide a security fix.

View file

@ -1,10 +0,0 @@
/*
Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/
(function(a){if("undefined"==typeof a)throw Error("jQuery should be loaded before CKEditor jQuery adapter.");if("undefined"==typeof CKEDITOR)throw Error("CKEditor should be loaded before CKEditor jQuery adapter.");CKEDITOR.config.jqueryOverrideVal="undefined"==typeof CKEDITOR.config.jqueryOverrideVal?!0:CKEDITOR.config.jqueryOverrideVal;a.extend(a.fn,{ckeditorGet:function(){var a=this.eq(0).data("ckeditorInstance");if(!a)throw"CKEditor is not initialized yet, use ckeditor() with a callback.";return a},
ckeditor:function(g,e){if(!CKEDITOR.env.isCompatible)throw Error("The environment is incompatible.");if("function"!==typeof g){var m=e;e=g;g=m}var k=[];e=e||{};this.each(function(){var b=a(this),c=b.data("ckeditorInstance"),f=b.data("_ckeditorInstanceLock"),h=this,l=new a.Deferred;k.push(l.promise());if(c&&!f)g&&g.apply(c,[this]),l.resolve();else if(f)c.once("instanceReady",function(){setTimeout(function d(){c.element?(c.element.$==h&&g&&g.apply(c,[h]),l.resolve()):setTimeout(d,100)},0)},null,null,
9999);else{if(e.autoUpdateElement||"undefined"==typeof e.autoUpdateElement&&CKEDITOR.config.autoUpdateElement)e.autoUpdateElementJquery=!0;e.autoUpdateElement=!1;b.data("_ckeditorInstanceLock",!0);c=a(this).is("textarea")?CKEDITOR.replace(h,e):CKEDITOR.inline(h,e);b.data("ckeditorInstance",c);c.on("instanceReady",function(e){var d=e.editor;setTimeout(function n(){if(d.element){e.removeListener();d.on("dataReady",function(){b.trigger("dataReady.ckeditor",[d])});d.on("setData",function(a){b.trigger("setData.ckeditor",
[d,a.data])});d.on("getData",function(a){b.trigger("getData.ckeditor",[d,a.data])},999);d.on("destroy",function(){b.trigger("destroy.ckeditor",[d])});d.on("save",function(){a(h.form).trigger("submit");return!1},null,null,20);if(d.config.autoUpdateElementJquery&&b.is("textarea")&&a(h.form).length){var c=function(){b.ckeditor(function(){d.updateElement()})};a(h.form).on("submit",c);a(h.form).on("form-pre-serialize",c);b.on("destroy.ckeditor",function(){a(h.form).off("submit",c);a(h.form).off("form-pre-serialize",
c)})}d.on("destroy",function(){b.removeData("ckeditorInstance")});b.removeData("_ckeditorInstanceLock");b.trigger("instanceReady.ckeditor",[d]);g&&g.apply(d,[h]);l.resolve()}else setTimeout(n,100)},0)},null,null,9999)}});var f=new a.Deferred;this.promise=f.promise();a.when.apply(this,k).then(function(){f.resolve()});this.editor=this.eq(0).data("ckeditorInstance");return this}});CKEDITOR.config.jqueryOverrideVal&&(a.fn.val=CKEDITOR.tools.override(a.fn.val,function(g){return function(e){if(arguments.length){var m=
this,k=[],f=this.each(function(){var b=a(this),c=b.data("ckeditorInstance");if(b.is("textarea")&&c){var f=new a.Deferred;c.setData(e,function(){f.resolve()});k.push(f.promise());return!0}return g.call(b,e)});if(k.length){var b=new a.Deferred;a.when.apply(this,k).done(function(){b.resolveWith(m)});return b.promise()}return f}var f=a(this).eq(0),c=f.data("ckeditorInstance");return f.is("textarea")&&c?c.getData():g.call(f)}}))})(window.jQuery);

View file

@ -1,16 +0,0 @@
{
"bender": {
"port": 9001
},
"server": {
"port": 9002
},
"paths": {
"ckeditor4": "../ckeditor4/",
"runner": "./src/runner.html"
},
"browsers": {
"linux": [ "chrome", "firefox" ],
"macos": [ "safari" ]
}
}

View file

@ -1,10 +0,0 @@
{
"name": "ckeditor",
"description": "JavaScript WYSIWYG web text editor.",
"keywords": [ "ckeditor4", "ckeditor", "fckeditor", "editor", "wysiwyg", "html", "richtext", "text", "javascript" ],
"authors": "CKSource (https://cksource.com/)",
"license": "For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license/.",
"homepage": "https://ckeditor.com",
"main": "./ckeditor.js",
"moduleType": "globals"
}

View file

@ -1,194 +0,0 @@
/**
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license/
*/
/**
* This file was added automatically by CKEditor builder.
* You may re-use it at any time to build CKEditor again.
*
* If you would like to build CKEditor online again
* (for example to upgrade), visit one the following links:
*
* (1) https://ckeditor.com/cke4/builder
* Visit online builder to build CKEditor from scratch.
*
* (2) https://ckeditor.com/cke4/builder/6490967e78ab135a44d8c0998d90e841
* Visit online builder to build CKEditor, starting with the same setup as before.
*
* (3) https://ckeditor.com/cke4/builder/download/6490967e78ab135a44d8c0998d90e841
* Straight download link to the latest version of CKEditor (Optimized) with the same setup as before.
*
* NOTE:
* This file is not used by CKEditor, you may remove it.
* Changing this file will not change your CKEditor configuration.
*/
var CKBUILDER_CONFIG = {
skin: 'moono-lisa',
preset: 'full',
ignore: [
'.DS_Store',
'.bender',
'.editorconfig',
'.gitattributes',
'.gitignore',
'.idea',
'.jscsrc',
'.jshintignore',
'.jshintrc',
'.mailmap',
'.npm',
'.nvmrc',
'.travis.yml',
'bender-err.log',
'bender-out.log',
'bender.ci.js',
'bender.js',
'dev',
'gruntfile.js',
'less',
'node_modules',
'package-lock.json',
'package.json',
'tests'
],
plugins : {
'a11yhelp' : 1,
'about' : 1,
'basicstyles' : 1,
'bidi' : 1,
'blockquote' : 1,
'clipboard' : 1,
'colorbutton' : 1,
'colordialog' : 1,
'contextmenu' : 1,
'copyformatting' : 1,
'dialogadvtab' : 1,
'div' : 1,
'editorplaceholder' : 1,
'elementspath' : 1,
'enterkey' : 1,
'entities' : 1,
'exportpdf' : 1,
'filebrowser' : 1,
'find' : 1,
'floatingspace' : 1,
'font' : 1,
'format' : 1,
'forms' : 1,
'horizontalrule' : 1,
'htmlwriter' : 1,
'iframe' : 1,
'image' : 1,
'indentblock' : 1,
'indentlist' : 1,
'justify' : 1,
'language' : 1,
'link' : 1,
'list' : 1,
'liststyle' : 1,
'magicline' : 1,
'maximize' : 1,
'newpage' : 1,
'pagebreak' : 1,
'pastefromgdocs' : 1,
'pastefromlibreoffice' : 1,
'pastefromword' : 1,
'pastetext' : 1,
'preview' : 1,
'print' : 1,
'removeformat' : 1,
'resize' : 1,
'save' : 1,
'scayt' : 1,
'selectall' : 1,
'showblocks' : 1,
'showborders' : 1,
'smiley' : 1,
'sourcearea' : 1,
'specialchar' : 1,
'stylescombo' : 1,
'tab' : 1,
'table' : 1,
'tableselection' : 1,
'tabletools' : 1,
'templates' : 1,
'toolbar' : 1,
'undo' : 1,
'uploadimage' : 1,
'wysiwygarea' : 1
},
languages : {
'af' : 1,
'ar' : 1,
'az' : 1,
'bg' : 1,
'bn' : 1,
'bs' : 1,
'ca' : 1,
'cs' : 1,
'cy' : 1,
'da' : 1,
'de' : 1,
'de-ch' : 1,
'el' : 1,
'en' : 1,
'en-au' : 1,
'en-ca' : 1,
'en-gb' : 1,
'eo' : 1,
'es' : 1,
'es-mx' : 1,
'et' : 1,
'eu' : 1,
'fa' : 1,
'fi' : 1,
'fo' : 1,
'fr' : 1,
'fr-ca' : 1,
'gl' : 1,
'gu' : 1,
'he' : 1,
'hi' : 1,
'hr' : 1,
'hu' : 1,
'id' : 1,
'is' : 1,
'it' : 1,
'ja' : 1,
'ka' : 1,
'km' : 1,
'ko' : 1,
'ku' : 1,
'lt' : 1,
'lv' : 1,
'mk' : 1,
'mn' : 1,
'ms' : 1,
'nb' : 1,
'nl' : 1,
'no' : 1,
'oc' : 1,
'pl' : 1,
'pt' : 1,
'pt-br' : 1,
'ro' : 1,
'ru' : 1,
'si' : 1,
'sk' : 1,
'sl' : 1,
'sq' : 1,
'sr' : 1,
'sr-latn' : 1,
'sv' : 1,
'th' : 1,
'tr' : 1,
'tt' : 1,
'ug' : 1,
'uk' : 1,
'vi' : 1,
'zh' : 1,
'zh-cn' : 1
}
};

File diff suppressed because one or more lines are too long

View file

@ -1,20 +0,0 @@
{
"name": "ckeditor/ckeditor",
"description": "JavaScript WYSIWYG web text editor.",
"type": "library",
"keywords": [ "ckeditor4", "ckeditor", "fckeditor", "editor", "wysiwyg", "html", "richtext", "text", "javascript" ],
"homepage": "https://ckeditor.com/ckeditor-4/",
"license": [ "GPL-2.0+", "LGPL-2.1+", "MPL-1.1+" ],
"authors": [
{
"name": "CKSource",
"homepage": "https://cksource.com"
}
],
"support": {
"issues": "https://github.com/ckeditor/ckeditor4/issues",
"forum": "https://stackoverflow.com/tags/ckeditor",
"wiki": "https://ckeditor.com/docs/ckeditor4/latest/",
"source": "https://github.com/ckeditor/ckeditor4"
}
}

View file

@ -1,10 +0,0 @@
/**
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see https://ckeditor.com/legal/ckeditor-oss-license
*/
CKEDITOR.editorConfig = function( config ) {
// Define changes to default configuration here. For example:
// config.language = 'fr';
// config.uiColor = '#AADC6E';
};

View file

@ -1,208 +0,0 @@
/*
Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/
body
{
/* Font */
/* Emoji fonts are added to visualise them nicely in Internet Explorer. */
font-family: sans-serif, Arial, Verdana, "Trebuchet MS", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
font-size: 12px;
/* Text color */
color: #333;
/* Remove the background color to make it transparent. */
background-color: #fff;
margin: 20px;
}
.cke_editable
{
font-size: 13px;
line-height: 1.6;
/* Fix for missing scrollbars with RTL texts. (#10488) */
word-wrap: break-word;
}
blockquote
{
font-style: italic;
font-family: Georgia, Times, "Times New Roman", serif;
padding: 2px 0;
border-style: solid;
border-color: #ccc;
border-width: 0;
}
.cke_contents_ltr blockquote
{
padding-left: 20px;
padding-right: 8px;
border-left-width: 5px;
}
.cke_contents_rtl blockquote
{
padding-left: 8px;
padding-right: 20px;
border-right-width: 5px;
}
a
{
color: #0782C1;
}
ol,ul,dl
{
/* IE7: reset rtl list margin. (#7334) */
*margin-right: 0px;
/* Preserved spaces for list items with text direction different than the list. (#6249,#8049)*/
padding: 0 40px;
}
h1,h2,h3,h4,h5,h6
{
font-weight: normal;
line-height: 1.2;
}
hr
{
border: 0px;
border-top: 1px solid #ccc;
}
img.right
{
border: 1px solid #ccc;
float: right;
margin-left: 15px;
padding: 5px;
}
img.left
{
border: 1px solid #ccc;
float: left;
margin-right: 15px;
padding: 5px;
}
pre
{
white-space: pre-wrap; /* CSS 2.1 */
word-wrap: break-word; /* IE7 */
-moz-tab-size: 4;
tab-size: 4;
}
.marker
{
background-color: Yellow;
}
span[lang]
{
font-style: italic;
}
figure
{
text-align: center;
outline: solid 1px #ccc;
background: rgba(0,0,0,0.05);
padding: 10px;
margin: 10px 20px;
display: inline-block;
}
figure > figcaption
{
text-align: center;
display: block; /* For IE8 */
}
a > img {
padding: 1px;
margin: 1px;
border: none;
outline: 1px solid #0782C1;
}
/* Widget Styles */
.code-featured
{
border: 5px solid red;
}
.math-featured
{
padding: 20px;
box-shadow: 0 0 2px rgba(200, 0, 0, 1);
background-color: rgba(255, 0, 0, 0.05);
margin: 10px;
}
.image-clean
{
border: 0;
background: none;
padding: 0;
}
.image-clean > figcaption
{
font-size: .9em;
text-align: right;
}
.image-grayscale
{
background-color: white;
color: #666;
}
.image-grayscale img, img.image-grayscale
{
filter: grayscale(100%);
}
.embed-240p
{
max-width: 426px;
max-height: 240px;
margin:0 auto;
}
.embed-360p
{
max-width: 640px;
max-height: 360px;
margin:0 auto;
}
.embed-480p
{
max-width: 854px;
max-height: 480px;
margin:0 auto;
}
.embed-720p
{
max-width: 1280px;
max-height: 720px;
margin:0 auto;
}
.embed-1080p
{
max-width: 1920px;
max-height: 1080px;
margin:0 auto;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,27 +0,0 @@
{
"name": "ckeditor4",
"version": "4.22.1",
"description": "JavaScript WYSIWYG web text editor.",
"main": "ckeditor.js",
"repository": {
"type": "git",
"url": "git+https://github.com/ckeditor/ckeditor4-releases.git"
},
"keywords": [
"ckeditor4",
"ckeditor",
"fckeditor",
"editor",
"wysiwyg",
"html",
"richtext",
"text",
"javascript"
],
"author": "CKSource (https://cksource.com/)",
"license": "(GPL-2.0 OR LGPL-2.1 OR MPL-1.1)",
"bugs": {
"url": "https://github.com/ckeditor/ckeditor4/issues"
},
"homepage": "https://ckeditor.com/ckeditor-4/"
}

View file

@ -1,10 +0,0 @@
/*
Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/
CKEDITOR.dialog.add("a11yHelp",function(f){function m(a){for(var b,c,h=[],d=0;d<g.length;d++)c=g[d],b=a/g[d],1<b&&2>=b&&(a-=c,h.push(e[c]));h.push(e[a]||String.fromCharCode(a));return h.join("+")}function t(a,b){var c=f.getCommandKeystroke(b,!0);return c.length?CKEDITOR.tools.array.map(c,m).join(" / "):a}var a=f.lang.a11yhelp,b=f.lang.common.keyboard,p=CKEDITOR.tools.getNextId(),q=/\$\{(.*?)\}/g,g=[CKEDITOR.ALT,CKEDITOR.SHIFT,CKEDITOR.CTRL],e={8:b[8],9:a.tab,13:b[13],16:b[16],17:b[17],18:b[18],19:a.pause,
20:a.capslock,27:a.escape,33:a.pageUp,34:a.pageDown,35:b[35],36:b[36],37:a.leftArrow,38:a.upArrow,39:a.rightArrow,40:a.downArrow,45:a.insert,46:b[46],91:a.leftWindowKey,92:a.rightWindowKey,93:a.selectKey,96:a.numpad0,97:a.numpad1,98:a.numpad2,99:a.numpad3,100:a.numpad4,101:a.numpad5,102:a.numpad6,103:a.numpad7,104:a.numpad8,105:a.numpad9,106:a.multiply,107:a.add,109:a.subtract,110:a.decimalPoint,111:a.divide,112:a.f1,113:a.f2,114:a.f3,115:a.f4,116:a.f5,117:a.f6,118:a.f7,119:a.f8,120:a.f9,121:a.f10,
122:a.f11,123:a.f12,144:a.numLock,145:a.scrollLock,186:a.semiColon,187:a.equalSign,188:a.comma,189:a.dash,190:a.period,191:a.forwardSlash,192:a.graveAccent,219:a.openBracket,220:a.backSlash,221:a.closeBracket,222:a.singleQuote};e[CKEDITOR.ALT]=b[18];e[CKEDITOR.SHIFT]=b[16];e[CKEDITOR.CTRL]=CKEDITOR.env.mac?b[224]:b[17];return{title:a.title,minWidth:600,minHeight:400,contents:[{id:"info",label:f.lang.common.generalTab,expand:!0,elements:[{type:"html",id:"legends",style:"white-space:normal;",focus:function(){this.getElement().focus()},
html:function(){for(var b='\x3cdiv class\x3d"cke_accessibility_legend" role\x3d"document" aria-labelledby\x3d"'+p+'_arialbl" tabIndex\x3d"-1"\x3e%1\x3c/div\x3e\x3cspan id\x3d"'+p+'_arialbl" class\x3d"cke_voice_label"\x3e'+a.contents+" \x3c/span\x3e",e=[],c=a.legend,h=c.length,d=0;d<h;d++){for(var f=c[d],g=[],r=f.items,m=r.length,n=0;n<m;n++){var k=r[n],l=CKEDITOR.env.edge&&k.legendEdge?k.legendEdge:k.legend,l=l.replace(q,t);l.match(q)||g.push("\x3cdt\x3e%1\x3c/dt\x3e\x3cdd\x3e%2\x3c/dd\x3e".replace("%1",
k.name).replace("%2",l))}e.push("\x3ch1\x3e%1\x3c/h1\x3e\x3cdl\x3e%2\x3c/dl\x3e".replace("%1",f.name).replace("%2",g.join("")))}return b.replace("%1",e.join(""))}()+'\x3cstyle type\x3d"text/css"\x3e.cke_accessibility_legend{width:600px;height:400px;padding-right:5px;overflow-y:auto;overflow-x:hidden;}.cke_browser_quirks .cke_accessibility_legend,{height:390px}.cke_accessibility_legend *{white-space:normal;}.cke_accessibility_legend h1{font-size: 20px;border-bottom: 1px solid #AAA;margin: 5px 0px 15px;}.cke_accessibility_legend dl{margin-left: 5px;}.cke_accessibility_legend dt{font-size: 13px;font-weight: bold;}.cke_accessibility_legend dd{margin:10px}\x3c/style\x3e'}]}],
buttons:[CKEDITOR.dialog.cancelButton]}});

View file

@ -1,25 +0,0 @@
Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
cs.js Found: 30 Missing: 0
cy.js Found: 30 Missing: 0
da.js Found: 12 Missing: 18
de.js Found: 30 Missing: 0
el.js Found: 25 Missing: 5
eo.js Found: 30 Missing: 0
fa.js Found: 30 Missing: 0
fi.js Found: 30 Missing: 0
fr.js Found: 30 Missing: 0
gu.js Found: 12 Missing: 18
he.js Found: 30 Missing: 0
it.js Found: 30 Missing: 0
mk.js Found: 5 Missing: 25
nb.js Found: 30 Missing: 0
nl.js Found: 30 Missing: 0
no.js Found: 30 Missing: 0
pt-br.js Found: 30 Missing: 0
ro.js Found: 6 Missing: 24
tr.js Found: 30 Missing: 0
ug.js Found: 27 Missing: 3
vi.js Found: 6 Missing: 24
zh-cn.js Found: 30 Missing: 0

View file

@ -1,11 +0,0 @@
/*
Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/
CKEDITOR.plugins.setLang("a11yhelp","af",{title:"Toeganglikheid instruksies",contents:"Hulp inhoud. Druk ESC om toe te maak.",legend:[{name:"Algemeen",items:[{name:"Bewerker balk",legend:"Druk ${toolbarFocus} om op die werkbalk te land. Beweeg na die volgende en voorige wekrbalkgroep met TAB and SHIFT+TAB. Beweeg na die volgende en voorige werkbalkknop met die regter of linker pyl. Druk SPASIE of ENTER om die knop te bevestig."},{name:"Bewerker dialoog",legend:"Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively. Press ESC to discard changes and close the dialog. The focus will be moved back to the editing area upon leaving the dialog."},
{name:"Bewerkerinhoudmenu",legend:"Press ${contextMenu} or APPLICATION KEY to open context-menu. Then move to next menu option with TAB or DOWN ARROW. Move to previous option with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the menu option. Open sub-menu of current option with SPACE or ENTER or RIGHT ARROW. Go back to parent menu item with ESC or LEFT ARROW. Close context menu with ESC."},{name:"Editor List Box",legend:"Inside a list-box, move to next list item with TAB OR DOWN ARROW. Move to previous list item with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the list option. Press ESC to close the list-box."},
{name:"Editor Element Path Bar",legend:"Press ${elementsPathFocus} to navigate to the elements path bar. Move to next element button with TAB or RIGHT ARROW. Move to previous button with SHIFT+TAB or LEFT ARROW. Press SPACE or ENTER to select the element in editor."}]},{name:"Commands",items:[{name:" Undo command",legend:"Press ${undo}"},{name:" Redo command",legend:"Press ${redo}"},{name:" Bold command",legend:"Press ${bold}"},{name:" Italic command",legend:"Press ${italic}"},{name:" Underline command",
legend:"Press ${underline}"},{name:" Link command",legend:"Press ${link}"},{name:" Toolbar Collapse command",legend:"Press ${toolbarCollapse}"},{name:" Access previous focus space command",legend:"Press ${accessPreviousSpace} to access the closest unreachable focus space before the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces."},{name:" Access next focus space command",legend:"Press ${accessNextSpace} to access the closest unreachable focus space after the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces."},
{name:" Accessibility Help",legend:"Press ${a11yHelp}"},{name:" Paste as plain text",legend:"Press ${pastetext}",legendEdge:"Press ${pastetext}, followed by ${paste}"}]}],tab:"Tab",pause:"Pouse",capslock:"Hoofletterslot",escape:"Ontsnap",pageUp:"Blaaiop",pageDown:"Blaaiaf",leftArrow:"Linkspyl",upArrow:"Oppyl",rightArrow:"Regterpyl",downArrow:"Afpyl",insert:"Toevoeg",leftWindowKey:"Left Windows key",rightWindowKey:"Right Windows key",selectKey:"Select key",numpad0:"Nommerblok 0",numpad1:"Nommerblok 1",
numpad2:"Nommerblok 2",numpad3:"Nommerblok 3",numpad4:"Nommerblok 4",numpad5:"Nommerblok 5",numpad6:"Nommerblok 6",numpad7:"Nommerblok 7",numpad8:"Nommerblok 8",numpad9:"Nommerblok 9",multiply:"Maal",add:"Plus",subtract:"Minus",decimalPoint:"Desimaalepunt",divide:"Gedeeldeur",f1:"F1",f2:"F2",f3:"F3",f4:"F4",f5:"F5",f6:"F6",f7:"F7",f8:"F8",f9:"F9",f10:"F10",f11:"F11",f12:"F12",numLock:"Nommervergrendel",scrollLock:"Rolvergrendel",semiColon:"Kommapunt",equalSign:"Isgelykaan",comma:"Komma",dash:"Koppelteken",
period:"Punt",forwardSlash:"Skuinsstreep",graveAccent:"Aksentteken",openBracket:"Oopblokhakkie",backSlash:"Trustreep",closeBracket:"Toeblokhakkie",singleQuote:"Enkelaanhaalingsteken"});

View file

@ -1,12 +0,0 @@
/*
Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/
CKEDITOR.plugins.setLang("a11yhelp","ar",{title:"Accessibility Instructions",contents:"Help Contents. To close this dialog press ESC.",legend:[{name:"عام",items:[{name:"Editor Toolbar",legend:"Press ${toolbarFocus} to navigate to the toolbar. Move to the next and previous toolbar group with TAB and SHIFT+TAB. Move to the next and previous toolbar button with RIGHT ARROW or LEFT ARROW. Press SPACE or ENTER to activate the toolbar button. The focus will be moved back to the editing area upon activating the toolbar button."},
{name:"Editor Dialog",legend:"Inside a dialog, press TAB to navigate to the next dialog element, press SHIFT+TAB to move to the previous dialog element, press ENTER to submit the dialog, press ESC to cancel the dialog. When a dialog has multiple tabs, the tab list can be reached either with ALT+F10 or with TAB as part of the dialog tabbing order. With tab list focused, move to the next and previous tab with RIGHT and LEFT ARROW, respectively. Press ESC to discard changes and close the dialog. The focus will be moved back to the editing area upon leaving the dialog."},
{name:"Editor Context Menu",legend:"Press ${contextMenu} or APPLICATION KEY to open context-menu. Then move to next menu option with TAB or DOWN ARROW. Move to previous option with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the menu option. Open sub-menu of current option with SPACE or ENTER or RIGHT ARROW. Go back to parent menu item with ESC or LEFT ARROW. Close context menu with ESC."},{name:"Editor List Box",legend:"Inside a list-box, move to next list item with TAB OR DOWN ARROW. Move to previous list item with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the list option. Press ESC to close the list-box."},
{name:"Editor Element Path Bar",legend:"Press ${elementsPathFocus} to navigate to the elements path bar. Move to next element button with TAB or RIGHT ARROW. Move to previous button with SHIFT+TAB or LEFT ARROW. Press SPACE or ENTER to select the element in editor."}]},{name:"الاوامر",items:[{name:"تراجع",legend:"Press ${undo}"},{name:" Redo command",legend:"Press ${redo}"},{name:"نص غامق",legend:"Press ${bold}"},{name:"نص مائل",legend:"Press ${italic}"},{name:"نص تحته خط",legend:"Press ${underline}"},
{name:" Link command",legend:"Press ${link}"},{name:" Toolbar Collapse command",legend:"Press ${toolbarCollapse}"},{name:" Access previous focus space command",legend:"Press ${accessPreviousSpace} to access the closest unreachable focus space before the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces."},{name:" Access next focus space command",legend:"Press ${accessNextSpace} to access the closest unreachable focus space after the caret, for example: two adjacent HR elements. Repeat the key combination to reach distant focus spaces."},
{name:" Accessibility Help",legend:"Press ${a11yHelp}"},{name:" Paste as plain text",legend:"Press ${pastetext}",legendEdge:"Press ${pastetext}, followed by ${paste}"}]}],tab:"Tab",pause:"Pause",capslock:"Caps Lock",escape:"هروب",pageUp:"اعلى الصفحة",pageDown:"اسفل الصفحة",leftArrow:"السهم الايسر",upArrow:"السهم العلوي",rightArrow:"السهم الأيمن",downArrow:"السهم السفلي",insert:"Insert",leftWindowKey:"Left Windows key",rightWindowKey:"Right Windows key",selectKey:"Select key",numpad0:"Numpad 0",numpad1:"Numpad 1",
numpad2:"Numpad 2",numpad3:"Numpad 3",numpad4:"Numpad 4",numpad5:"Numpad 5",numpad6:"Numpad 6",numpad7:"Numpad 7",numpad8:"Numpad 8",numpad9:"Numpad 9",multiply:"مضروب",add:"إضافة",subtract:"طرح",decimalPoint:"Decimal Point",divide:"تقسيم",f1:"F1",f2:"F2",f3:"F3",f4:"F4",f5:"F5",f6:"F6",f7:"F7",f8:"F8",f9:"F9",f10:"F10",f11:"F11",f12:"F12",numLock:"Num Lock",scrollLock:"Scroll Lock",semiColon:"الفاصلة المنقوطة",equalSign:'علامة "يساوي"',comma:"فاصلة",dash:"شرطة",period:"نقطة",forwardSlash:"Forward Slash",
graveAccent:"Grave Accent",openBracket:"افتح القوس",backSlash:"Backslash",closeBracket:"اغلق القوس",singleQuote:"Single Quote"});

Some files were not shown because too many files have changed in this diff Show more