feat: Implement SMS sending functionality with KavehNegar and Rangineh providers

- Add SendSmsMessage class for encapsulating SMS message data.
- Create KavehNegarProvider and RanginehProvider classes implementing SmsProviderInterface for sending SMS.
- Implement SmsLogRepository and SmsTemplateRepository for managing SMS logs and templates.
- Develop SendSmsHandler for handling SMS sending messages.
- Create SmsService to manage SMS dispatching and logging.
- Add UserProfileController for managing user profiles with CRUD operations.
- Implement UserProfile entity and repository for user profile data management.
- Update symfony.lock and bootstrap.php for project dependencies and environment setup.
This commit is contained in:
hamed
2026-06-09 22:00:34 +03:30
commit de1a78a235
222 changed files with 36388 additions and 0 deletions
+97
View File
@@ -0,0 +1,97 @@
<?php
namespace App\Category\Service;
use App\Category\Entity\Category;
use App\Category\Repository\CategoryRepository;
use Psr\Cache\CacheItemPoolInterface;
class CategoryService
{
private const TTL = 3600;
public function __construct(
private readonly CategoryRepository $repository,
private readonly CacheItemPoolInterface $cache,
) {}
/** @return array[] */
public function listByBundle(string $bundle, ?int $parentId = null): array
{
$cacheKey = 'cat_' . $bundle . ($parentId !== null ? '_p' . $parentId : '');
$item = $this->cache->getItem($cacheKey);
if ($item->isHit()) {
return $item->get();
}
$rows = array_map(fn(Category $c) => $c->toArray(), $this->repository->findByBundle($bundle, $parentId));
$item->set($rows)->expiresAfter(self::TTL);
$this->cache->save($item);
return $rows;
}
public function create(string $bundle, string $label, array $extra = []): Category
{
$category = new Category($bundle, $label);
$this->applyExtra($category, $extra);
$this->repository->save($category);
$this->invalidate($bundle);
return $category;
}
public function update(Category $category, array $data): Category
{
$bundle = $data['bundle'] ?? $category->getBundle();
if (isset($data['label'])) $category->setLabel($data['label']);
if (isset($data['status'])) $category->setStatus((int) $data['status']);
if (isset($data['weight'])) $category->setWeight((int) $data['weight']);
if (isset($data['title'])) $category->setTitle($data['title']);
if (isset($data['bundle'])) $category->setBundle($data['bundle']);
if (array_key_exists('parent_id', $data)) $category->setParentId($data['parent_id']);
$this->applyExtra($category, $data);
$this->repository->save($category);
$this->invalidate($bundle);
$this->invalidate($category->getBundle());
return $category;
}
public function delete(Category $category): void
{
$bundle = $category->getBundle();
$this->repository->remove($category);
$this->invalidate($bundle);
}
private function applyExtra(Category $category, array $data): void
{
if (array_key_exists('parent_id', $data)) $category->setParentId($data['parent_id']);
if (array_key_exists('weight', $data)) $category->setWeight((int) $data['weight']);
if (array_key_exists('logo_id', $data)) $category->setLogoId($data['logo_id']);
if (array_key_exists('title', $data)) $category->setTitle($data['title']);
if (array_key_exists('contact_phone', $data)) $category->setContactPhone($data['contact_phone']);
if (array_key_exists('email', $data)) $category->setEmail($data['email']);
if (array_key_exists('description', $data)) $category->setDescription($data['description']);
if (array_key_exists('slogan', $data)) $category->setSlogan($data['slogan']);
if (array_key_exists('domain', $data)) $category->setDomain($data['domain']);
if (array_key_exists('keywords', $data)) $category->setKeywords($data['keywords']);
if (array_key_exists('footer_description', $data)) $category->setFooterDescription($data['footer_description']);
if (array_key_exists('footer_disclaimer', $data)) $category->setFooterDisclaimer($data['footer_disclaimer']);
if (array_key_exists('social_media', $data)) $category->setSocialMedia($data['social_media']);
}
private function invalidate(string $bundle): void
{
$this->cache->deleteItem('cat_' . $bundle);
// Also delete any parent-filtered variants
foreach (range(1, 50) as $id) {
$this->cache->deleteItem('cat_' . $bundle . '_p' . $id);
}
}
}