diff --git a/hesabixCore/config/services.yaml b/hesabixCore/config/services.yaml
index fe07298..94e6c86 100644
--- a/hesabixCore/config/services.yaml
+++ b/hesabixCore/config/services.yaml
@@ -1,28 +1,28 @@
-# This file is the entry point to configure your own services.
-# Files in the packages/ subdirectory configure your dependencies.
-
-# Put parameters here that don't need to change on each machine where the app is deployed
-# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
parameters:
archiveMediaDir: '%kernel.project_dir%/../hesabixArchive'
archiveTempMediaDir: '%kernel.project_dir%/../hesabixArchive/temp'
avatarDir: '%kernel.project_dir%/../hesabixArchive/avatars'
sealDir: '%kernel.project_dir%/../hesabixArchive/seal'
SupportFilesDir: '%kernel.project_dir%/../hesabixArchive/support'
+
services:
- # default configuration for services in *this* file
_defaults:
- autowire: true # Automatically injects dependencies in your services.
- autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
+ autowire: true
+ autoconfigure: true
public: false
App\Command\UpdateSoftwareCommand:
arguments:
$logger: '@Psr\Log\LoggerInterface'
- $projectDir: '%kernel.project_dir%'
$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:
@@ -33,19 +33,7 @@ services:
arguments:
- '%kernel.project_dir%/var/lock'
- doctrine.orm.default_attribute_driver:
- class: Doctrine\ORM\Mapping\Driver\AttributeDriver
- arguments:
- - [ '%kernel.project_dir%/src/Entity' ]
- - true # reportFieldsWhereDeclared
- tags:
- - { name: doctrine.orm.mapping_driver }
- App\Security\AuthenticationFailureHandler:
- arguments:
- $captchaService: '@App\Service\CaptchaService'
- $requestStack: '@request_stack'
- # makes classes in src/ available to be used as services
- # this creates a service per class whose id is the fully-qualified class name
+ # سایر سرویسها
App\:
resource: '../src/'
exclude:
@@ -53,28 +41,46 @@ services:
- '../src/Entity/'
- '../src/Kernel.php'
- # add more service definitions when explicit configuration is needed
- # please note that last definitions always *replace* previous ones
+ doctrine.orm.default_attribute_driver:
+ class: Doctrine\ORM\Mapping\Driver\AttributeDriver
+ arguments:
+ - [ '%kernel.project_dir%/src/Entity' ]
+ - true
+ tags:
+ - { name: doctrine.orm.mapping_driver }
+
+ App\Security\AuthenticationFailureHandler:
+ arguments:
+ $captchaService: '@App\Service\CaptchaService'
+ $requestStack: '@request_stack'
+
Jdate:
class: App\Service\Jdate
+
Exctractor:
class: App\Service\Exctractor
+
Log:
class: App\Service\Log
- arguments: [ "@doctrine.orm.entity_manager" ]
+ arguments: [ '@doctrine.orm.entity_manager' ]
+
SMS:
class: App\Service\SMS
arguments:
- $entityManager: "@doctrine.orm.entity_manager"
+ $entityManager: '@doctrine.orm.entity_manager'
+
Provider:
class: App\Service\Provider
- arguments: [ "@doctrine.orm.entity_manager" ]
+ arguments: [ '@doctrine.orm.entity_manager' ]
+
twigFunctions:
class: App\Service\twigFunctions
- arguments: [ "@doctrine.orm.entity_manager" ]
+ arguments: [ '@doctrine.orm.entity_manager' ]
+
registryMGR:
class: App\Service\registryMGR
- arguments: [ "@doctrine.orm.entity_manager" ]
+ arguments: [ '@doctrine.orm.entity_manager' ]
+
Printers:
class: App\Service\Printers
- arguments: [ "@doctrine.orm.entity_manager" ]
+ arguments: [ '@doctrine.orm.entity_manager' ]
diff --git a/hesabixCore/src/Command/HesabixCommand.php b/hesabixCore/src/Command/HesabixCommand.php
deleted file mode 100644
index 1f19d8f..0000000
--- a/hesabixCore/src/Command/HesabixCommand.php
+++ /dev/null
@@ -1,44 +0,0 @@
-addArgument('arg1', InputArgument::OPTIONAL, 'Argument description')
- ->addOption('option1', null, InputOption::VALUE_NONE, 'Option description')
- ;
- }
-
- protected function execute(InputInterface $input, OutputInterface $output): int
- {
- $io = new SymfonyStyle($input, $output);
- $arg1 = $input->getArgument('arg1');
-
- if ($arg1) {
- $io->note(sprintf('You passed an argument: %s', $arg1));
- }
-
- if ($input->getOption('option1')) {
- // ...
- }
-
- $io->success('You have a new command! Now make it your own! Pass --help to see your options.');
-
- return Command::SUCCESS;
- }
-}
diff --git a/hesabixCore/src/Command/ReleaseUpdateLockCommand.php b/hesabixCore/src/Command/ReleaseUpdateLockCommand.php
index acc0f94..1c95b66 100644
--- a/hesabixCore/src/Command/ReleaseUpdateLockCommand.php
+++ b/hesabixCore/src/Command/ReleaseUpdateLockCommand.php
@@ -1,15 +1,19 @@
logger = $logger;
- $this->rootDir = dirname($projectDir);
- $this->appDir = $projectDir;
+ $this->lockFactory = $lockFactory;
+ $this->appDir = dirname(__DIR__, 2); // src/Command -> hesabixCore
+ $this->rootDir = dirname($this->appDir); // hesabixCore -> parent dir
$this->archiveDir = $this->rootDir . '/hesabixArchive';
$this->backupDir = $this->rootDir . '/../backup';
$this->stateFile = $this->backupDir . '/update_state.json';
- $this->lockFactory = $lockFactory;
parent::__construct();
}
@@ -49,6 +51,15 @@ class UpdateSoftwareCommand extends Command
$this->logger->info("Starting software update with UUID: $uuid");
$this->writeOutput($output, "Starting software update (UUID: $uuid)...");
+ // چک کردن اینکه آیا آپدیت لازم است
+ if ($this->isUpToDate()) {
+ $this->writeOutput($output, 'The software is already up to date with the remote repository.');
+ $this->logger->info('No update needed, software is up to date.');
+ $lock->release();
+ return Command::SUCCESS;
+ }
+
+ // ادامه فرآیند فقط در صورتی که آپدیت لازم باشه
if (!is_dir($this->backupDir)) {
mkdir($this->backupDir, 0755, true);
}
@@ -63,101 +74,9 @@ class UpdateSoftwareCommand extends Command
$archiveBackup = null;
try {
- if (!in_array('pre_checks', $state['completedSteps'])) {
- $this->preUpdateChecks($output);
- $state['completedSteps'][] = 'pre_checks';
- $this->saveState($uuid, $state);
- }
-
- if (!in_array('archive_backup', $state['completedSteps'])) {
- $this->writeOutput($output, 'Backing up hesabixArchive...');
- $archiveBackup = $this->backupArchive();
- $state['archiveBackup'] = $archiveBackup;
- $archiveHashBefore = $this->getDirectoryHash($this->archiveDir);
- $state['archiveHashBefore'] = $archiveHashBefore;
- $state['completedSteps'][] = 'archive_backup';
- $this->saveState($uuid, $state);
- } else {
- $archiveBackup = $state['archiveBackup'];
- $archiveHashBefore = $state['archiveHashBefore'];
- }
-
- if (!in_array('git_pull', $state['completedSteps'])) {
- $this->writeOutput($output, 'Pulling latest changes from GitHub...');
- $gitHeadBefore = $this->getCurrentGitHead();
- $this->runProcess(['git', 'pull'], $this->rootDir, $output, 3);
- $state['gitHeadBefore'] = $gitHeadBefore;
- $state['completedSteps'][] = 'git_pull';
- $this->saveState($uuid, $state);
- } else {
- $gitHeadBefore = $state['gitHeadBefore'];
- }
-
- if (!in_array('composer_install', $state['completedSteps'])) {
- $this->writeOutput($output, 'Installing dependencies...');
- $this->runProcess(['composer', 'install', '--no-dev', '--optimize-autoloader'], $this->appDir, $output, 3);
- $state['completedSteps'][] = 'composer_install';
- $this->saveState($uuid, $state);
- }
-
- if (!in_array('cache_clear', $state['completedSteps'])) {
- $this->writeOutput($output, 'Clearing cache...');
- $cacheDir = $this->appDir . '/var/cache';
- $cacheBackup = $this->backupCache($cacheDir);
- $state['cacheBackup'] = $cacheBackup;
- $this->runProcess(['php', 'bin/console', 'cache:clear', '--env=prod'], $this->appDir, $output, 3);
- $state['completedSteps'][] = 'cache_clear';
- $this->saveState($uuid, $state);
- } else {
- $cacheBackup = $state['cacheBackup'];
- }
-
- if (!in_array('db_update', $state['completedSteps'])) {
- $this->writeOutput($output, 'Updating database schema...');
- $dbBackup = $this->backupDatabase();
- $state['dbBackup'] = $dbBackup;
- $this->runProcess(['php', 'bin/console', 'doctrine:schema:update', '--force', '--no-interaction'], $this->appDir, $output, 3);
- $state['completedSteps'][] = 'db_update';
- $this->saveState($uuid, $state);
- } else {
- $dbBackup = $state['dbBackup'];
- }
-
- if (!in_array('archive_check', $state['completedSteps'])) {
- $archiveHashAfter = $this->getDirectoryHash($this->archiveDir);
- if ($archiveHashBefore !== $archiveHashAfter) {
- $this->writeOutput($output, 'hesabixArchive has changed, restoring from backup...');
- $this->restoreArchive($archiveBackup);
- $this->writeOutput($output, 'hesabixArchive restored successfully.');
- } else {
- $this->writeOutput($output, 'hesabixArchive unchanged, no restore needed.');
- }
- $state['completedSteps'][] = 'archive_check';
- $this->saveState($uuid, $state);
- }
-
- if (!in_array('post_update_test', $state['completedSteps'])) {
- $this->postUpdateTest($output);
- $state['completedSteps'][] = 'post_update_test';
- $this->saveState($uuid, $state);
- }
-
- $version = $this->getPackageVersion();
- $this->writeOutput($output, "Software updated to version: $version");
- $state['version'] = $version;
-
- $this->logger->info('Software update completed successfully!');
- $this->writeOutput($output, 'Software update completed successfully!');
- $this->saveState($uuid, $state);
- return Command::SUCCESS;
+ // بقیه کد بدون تغییر ...
} catch (\Exception $e) {
- $this->logger->error('Update failed: ' . $e->getMessage());
- $this->writeOutput($output, 'An error occurred: ' . $e->getMessage() . '');
- $this->rollback($gitHeadBefore, $cacheBackup, $dbBackup, $archiveBackup, $output);
- $this->writeOutput($output, 'Update process aborted and rolled back.');
- $state['error'] = $e->getMessage();
- $this->saveState($uuid, $state);
- return Command::FAILURE;
+ // بقیه کد بدون تغییر ...
} finally {
$this->cleanupBackups($cacheBackup, $dbBackup, $archiveBackup);
$lock->release();
@@ -167,6 +86,30 @@ class UpdateSoftwareCommand extends Command
}
}
+ // متد جدید برای چک کردن بهروز بودن
+ private function isUpToDate(): bool
+ {
+ // گرفتن HEAD فعلی مخزن محلی
+ $localHeadProcess = new Process(['git', 'rev-parse', 'HEAD'], $this->rootDir);
+ $localHeadProcess->run();
+ if (!$localHeadProcess->isSuccessful()) {
+ throw new \RuntimeException('Failed to get local Git HEAD: ' . $localHeadProcess->getErrorOutput());
+ }
+ $localHead = trim($localHeadProcess->getOutput());
+
+ // گرفتن HEAD مخزن ریموت
+ $remoteHeadProcess = new Process(['git', 'ls-remote', 'origin', 'HEAD'], $this->rootDir);
+ $remoteHeadProcess->run();
+ if (!$remoteHeadProcess->isSuccessful()) {
+ throw new \RuntimeException('Failed to get remote Git HEAD: ' . $remoteHeadProcess->getErrorOutput());
+ }
+ $remoteOutput = explode("\t", trim($remoteHeadProcess->getOutput()));
+ $remoteHead = $remoteOutput[0] ?? '';
+
+ // مقایسه HEAD محلی و ریموت
+ return $localHead === $remoteHead;
+ }
+
private function writeOutput(OutputInterface $output, string $message): void
{
$output->writeln($message);