<?php
namespace App\Service;
use App\Entity\BrandDomain;
use App\Entity\Check;
use App\Entity\CheckHistory;
use App\Entity\Customer;
use App\Entity\NotificationQueue;
use App\Entity\File;
use App\Entity\Keyword;
use App\Entity\Log;
use App\Entity\NotificationTemplate;
use App\Entity\Page;
use App\Entity\SuspiciousDomain;
use Symfony\Component\Filesystem\Filesystem;
use App\Entity\Server;
use App\Entity\Setting;
use App\Entity\Smtp;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Component\HttpFoundation\Response;
use Twig\Environment;
use Symfony\Component\HttpClient\HttpClient;
use DateTime;
class Utils
{
private $translator;
private $em;
private $tokenStorage;
private $requestStack;
private $twig;
private $router;
private $flash;
public function __construct(TranslatorInterface $translator, TokenStorageInterface $tokenStorage, RequestStack $requestStack, EntityManagerInterface $em, Environment $twig, RouterInterface $router, FlashBagInterface $flash)
{
$this->translator = $translator;
$this->requestStack = $requestStack;
$this->tokenStorage = $tokenStorage;
$this->em = $em;
$this->twig = $twig;
$this->router = $router;
$this->flash = $flash;
$this->settings = $this->em->getRepository( Setting::class )->findAllGlobal();
foreach ($this->settings as $setting) {
$this->settings[$setting['name']] = $setting['value'];
}
}
public function scheduledTask_checkServerStatus($version, $utils, $twig, $em, $settings): array
{
$now = new DateTime();
$servers = $em->getRepository(Server::class)->findBy(['status' => true]);
$servers_down = array();
foreach ($servers as $server) {
$difference = $now->diff($server->getLastActivity());
if ($difference->i > 5) {
$servers_down[] = $server;
}
}
if (count($servers_down) > 0) {
$smtp = $em->getRepository(Smtp::class)->findOneBy(['is_default' => true]);
foreach ($servers_down as $server_down) {
//Utils::{"sendNotification"}($smtp->getId(), array('tech@wedoit-group.com'), array(), array(), false, 'Server: ' . $server_down->getName() . ' - Location: ' . $server_down->getLocation() . ' DOWN', 'Detected no activity for 5 minutes', null, null, $em);
}
}
$result['check'] = true;
$result['result'] = 'ok';
$result['data'] = [];
return $result;
}
/**
* @throws RedirectionExceptionInterface
* @throws ClientExceptionInterface
* @throws TransportExceptionInterface
* @throws ServerExceptionInterface
*/
public function scheduledTask_importDomainsFromDnpedia($version, $utils, $twig, $em, $settings): array
{
$client = HttpClient::create();
$response = $client->request('GET', 'https://api.codepunch.com/dnfeed.php?c=auth&k=' . $settings['dnpedia_key'] . '&s=' . $settings['dnpedia_secret']);
$token = trim(substr($response->getContent(), strpos($response->getContent(), ":") + 1));
$keywords = $em->getRepository(Keyword::class)->findBy(['type' => 'include', 'status' => true]);
foreach ($keywords as $keyword) {
$excluded_keywords = $em->getRepository(Keyword::class)->findBy(['brand' => $keyword->getBrand(), 'type' => 'exclude', 'status' => true]);
$excluded_keywords_string = '';
foreach($excluded_keywords as $excluded_keyword) {
$excluded_keywords_string .= $excluded_keyword->getName() . '|';
}
$response = $client->request('GET', 'https://api.codepunch.com/dnfeed.php?t=' . $token . '&kw=%' . trim(strtolower($keyword->getName())) . '%');
$data = json_decode($response->getContent(), true);
$counter_import = 0;
if ($data !== null) {
foreach ($data['domains'] as $domain){
$perform_check = true;
if ($excluded_keywords_string !== '') {
if (preg_match_all('#\b(' . substr($excluded_keywords_string, 0, -1) . ')\b#', $domain['domain'], $matches)) {
$perform_check = false;
}
}
if (str_contains($domain['domain'], $keyword->getName()) && $perform_check) {
$result_check = call_user_func_array(array('App\\Service\\Utils', 'checkDomain'), array($version, $twig, $em, $domain['domain'], 'dnpedia', $keyword->getBrand(), $keyword));
if ($result_check) {
$counter_import++;
}
}
}
}
$keyword->setImportedFromDnpedia($keyword->getImportedFromDnpedia() + $counter_import);
$em->persist($keyword);
$em->flush();
}
$result['check'] = true;
$result['result'] = 'ok';
$result['data'] = [];
return $result;
}
/**
* @throws TransportExceptionInterface
* @throws ServerExceptionInterface
* @throws RedirectionExceptionInterface
* @throws ClientExceptionInterface
*/
public function scheduledTask_importDomainsFromPhishTank($version, $utils, $twig, $em, $settings): array
{
$client = HttpClient::create();
$response = $client->request('GET', 'https://data.phishtank.com/data/' . $settings['phishtank_key'] . '/online-valid.json');
if ($response->getStatusCode() === 200) {
$domains = json_decode($response->getContent(), true);
if ($domains) {
$keywords = $em->getRepository(Keyword::class)->findBy(['type' => 'include', 'status' => true]);
foreach ($keywords as $keyword) {
$excluded_keywords = $em->getRepository(Keyword::class)->findBy(['brand' => $keyword->getBrand(), 'type' => 'exclude', 'status' => true]);
$excluded_keywords_string = '';
foreach ($excluded_keywords as $excluded_keyword) {
$excluded_keywords_string .= $excluded_keyword->getName() . '|';
}
$counter_import = 0;
foreach ($domains as $domain) {
$perform_check = true;
if ($excluded_keywords_string !== '') {
if (preg_match_all('#\b(' . substr($excluded_keywords_string, 0, -1) . ')\b#', $domain['url'], $matches)) {
$perform_check = false;
}
}
if (str_contains($domain['url'], $keyword->getName()) && $perform_check) {
$result_check = call_user_func_array(array('App\\Service\\Utils', 'checkDomain'), array($version, $twig, $em, $domain['url'], 'phish_tank', $keyword->getBrand(), $keyword));
if ($result_check) {
$counter_import++;
}
}
}
$keyword->setImportedFromPhishTank($keyword->getImportedFromPhishtank() + $counter_import);
$em->persist($keyword);
$em->flush();
}
}
$result['result'] = 'ok';
}
else {
$result['result'] = 'nok';
}
$result['check'] = true;
$result['data'] = [];
return $result;
}
/**
* @throws RedirectionExceptionInterface
* @throws ClientExceptionInterface
* @throws TransportExceptionInterface
* @throws ServerExceptionInterface
*/
public function scheduledTask_checkPhishTank($version, $utils, $twig, $em, $settings): array
{
$brand_domains = $em->getRepository(BrandDomain::class)->findBy(['status' => 'monitor']);
foreach ($brand_domains as $brand_domain) {
$checks = $em->getRepository(Check::class)->findBy(['brandDomain' => $brand_domain]);
foreach ($checks as $check) {
$client = HttpClient::create();
$result_array = array();
$url_http = '';
$url_https = '';
if (!str_starts_with($brand_domain->getUrl(), 'http') and !str_starts_with($brand_domain->getUrl(), 'https')) {
if ($brand_domain->getDomain() === $brand_domain->getUrl()) {
$url_http = 'http://' . $brand_domain->getDomain();
$url_https = 'https://' . $brand_domain->getDomain();
}
else {
$url_http = 'http://' . $brand_domain->getUrl();
$url_https = 'https://' . $brand_domain->getUrl();
}
}
else {
if (!str_starts_with($brand_domain->getUrl(), 'https')) {
$url_https = $brand_domain->getUrl();
}
else {
$url_http = $brand_domain->getUrl();
}
}
$result_array['http']['status'] = 'false';
$result_array['http']['url'] = '';
$result_array['http']['verified'] = '';
if ($url_http != '') {
$response = $client->request('POST', 'https://checkurl.phishtank.com/checkurl/index.php', [
'headers' => [
'User-Agent' => 'phishtank/' . $settings['phishtank_username'],
],
'body' => [
'url' => $url_http,
'format' => 'json',
'api_key' => $settings['phishtank_key'],
],
]);
if ($response->getStatusCode() === 200) {
$phishtank_json = json_decode($response->getContent());
$result_array['http']['status'] = $phishtank_json->results->in_database;
$result_array['http']['url'] = '';
if (property_exists($phishtank_json->results, 'phish_detail_page')) {
$result_array['http']['url'] = $phishtank_json->results->phish_detail_page;
}
$result_array['http']['verified'] = '';
if (property_exists($phishtank_json->results, 'verified')) {
$result_array['http']['verified'] = $phishtank_json->results->verified;
}
}
}
$result_array['https']['status'] = 'false';
$result_array['https']['url'] = '';
$result_array['https']['verified'] = '';
if ($url_https != '') {
$response = $client->request('POST', 'https://checkurl.phishtank.com/checkurl/index.php', [
'headers' => [
'User-Agent' => 'phishtank/' . $settings['phishtank_username'],
],
'body' => [
'url' => $url_https,
'format' => 'json',
'api_key' => $settings['phishtank_key'],
],
]);
if ($response->getStatusCode() === 200) {
$phishtank_json = json_decode($response->getContent());
$result_array['https']['status'] = $phishtank_json->results->in_database;
$result_array['https']['url'] = '';
if (property_exists($phishtank_json->results, 'phish_detail_page')) {
$result_array['https']['url'] = $phishtank_json->results->phish_detail_page;
}
$result_array['https']['verified'] = '';
if (property_exists($phishtank_json->results, 'verified')) {
$result_array['https']['verified'] = $phishtank_json->results->verified;
}
}
}
$phishtank_array = [
'check_status' => 'checked',
'last_check' => new DateTime(),
'info' => [
'http' => [
'status' => $result_array['http']['status'],
'url' => $result_array['http']['url'],
'verified' => $result_array['http']['verified']
],
'https' => [
'status' => $result_array['https']['status'],
'url' => $result_array['https']['url'],
'verified' => $result_array['https']['verified']
]
]
];
$check->setPhishTank($phishtank_array);
if (count($checks) > 0) {
$em->persist($check);
}
}
}
$em->flush();
$result['check'] = true;
$result['result'] = 'ok';
$result['data'] = [];
return $result;
}
public function scheduledTask_cleanDB($version, $utils, $twig, $em, $settings): array
{
// Clean list of domain older then X days and in waiting or false positive status
$suspicious_domains = $em->getRepository(SuspiciousDomain::class)->findToBeCleaned();
$brad_domains_array = [];
foreach ($suspicious_domains as $suspicious_domain) {
if ($utils->timeDiffMinutes(new DateTime(), $suspicious_domain->getLastActivity()) >= $settings['cleandb_domains_difference_in_minute']) {
$total_brand_domains = count($suspicious_domain->getBrandDomains());
$total_brand_domains_counter = 0;
foreach ($suspicious_domain->getBrandDomains() as $brand_domain) {
if ($brand_domain->getStatus() === 'waiting' or $brand_domain->getStatus() === 'false_positive' or $brand_domain->getStatus() === 'deleted') {
$total_brand_domains_counter++;
$brad_domains_array[] = $brand_domain;
}
}
if ($total_brand_domains === $total_brand_domains_counter) {
foreach ($brad_domains_array as $bd) {
$em->remove($bd);
}
$em->remove($suspicious_domain);
}
}
}
$filesystem = new Filesystem();
$check_histories = $em->getRepository(CheckHistory::class)->findToBeCleaned();
foreach ($check_histories as $check_history) {
if ($utils->timeDiffMinutes(new DateTime(), $check_history->getCreatedAt()) >= $settings['cleandb_checkhistory_difference_in_minute']) {
if ($check_history->getScreenshotHttp() !== null) {
$filesystem->remove('../storage/screenshots/' . $check_history->getScreenshotHttp());
}
if ($check_history->getScreenshotHttps() !== null) {
$filesystem->remove('../storage/screenshots/' . $check_history->getScreenshotHttps());
}
$em->remove($check_history);
}
}
$em->flush();
$result['check'] = true;
$result['result'] = 'ok';
$result['data'] = array('cleaned');
return $result;
}
public function checkDomain($version, $twig, $em, $dom, $source, $brand, $keyword, $server = null): bool
{
$result = false;
if (!str_starts_with($dom, 'http') and !str_starts_with($dom, 'https')) {
$url = parse_url('https://' . $dom);
}
else {
$url = parse_url($dom);
}
$entity_id = null;
$suspicious_domain = $em->getRepository(SuspiciousDomain::class)->findOneBy(['domain' => trim($url['host'])]);
$server_array = array();
if ($server) {
$server_array['id'] = $server->getId();
$server_array['name'] = $server->getName();
$server_array['group_number'] = $server->getGroupNumber();
$server_array['ip_address'] = $server->getIpAddress();
$server_array['country'] = $server->getCountry()->getCode();
$server_array['location'] = $server->getLocation();
}
$check_exclusion = false;
$excluded_pages_array = [];
$pages = $em->getRepository(Page::class)->findBy(['brand' => $brand, 'status' => true]);
foreach ($pages as $page) {
$excluded_pages_array[] = str_replace('www.', '', parse_url($page->getUrl(), PHP_URL_HOST));
}
foreach ($excluded_pages_array as $page) {
if (str_ends_with(trim($url['host']), $page)) {
$check_exclusion = true;
}
}
if (!$check_exclusion) {
if (!$suspicious_domain) {
$suspicious_domain = New SuspiciousDomain();
$suspicious_domain->setDomain(rtrim($url['host'], '/'));
$suspicious_domain->setUrl(rtrim($dom, '/'));
$suspicious_domain->setSource($source);
$suspicious_domain->setKeyword($keyword->getName());
$suspicious_domain->setServer($server_array);
$suspicious_domain->setCreatedAt(new DateTime());
$suspicious_domain->setLastActivity(new DateTime());
$suspicious_domain->setStatus(true);
$em->persist($suspicious_domain);
$em->flush();
$entity_id = $suspicious_domain->getId();
$brand_domain = New BrandDomain();
$brand_domain->setBrand($brand);
$brand_domain->setKeyword($keyword);
$brand_domain->setSuspiciousDomain($suspicious_domain);
$brand_domain->setDomain($suspicious_domain->getDomain());
$brand_domain->setUrl($suspicious_domain->getUrl());
$brand_domain->setStatus('waiting');
$em->persist($brand_domain);
$keyword->setLastImport(new DateTime());
$em->persist($keyword);
$em->flush();
$result = true;
}
else {
$brand_domain_checker = $em->getRepository(BrandDomain::class)->findOneBy(['brand' => $brand, 'suspiciousDomain' => $suspicious_domain]);
if (!$brand_domain_checker) {
$brand_domain = New BrandDomain();
$brand_domain->setBrand($brand);
$brand_domain->setKeyword($keyword);
$brand_domain->setSuspiciousDomain($suspicious_domain);
$brand_domain->setDomain($suspicious_domain->getDomain());
$brand_domain->setUrl($suspicious_domain->getUrl());
$brand_domain->setStatus('waiting');
$em->persist($brand_domain);
$em->flush();
$result = true;
}
}
}
if ($result == true) {
$settings = $em->getRepository( Setting::class )->findAllGlobal();
foreach ($settings as $setting) {
$settings[$setting['name']] = $setting['value'];
}
call_user_func_array(array('App\\Service\\Utils', 'sendNotification'), array(false, 'pushover', null, null, array(), array(), $settings['pushover_api_key'], $settings['pushover_group_api_key'], false, '', '', 'suspicious_domain', $entity_id, 1, null, $twig, $em));
$smtp = $em->getRepository(Smtp::class)->findOneBy(['is_default' => true]);
if ($smtp) {
call_user_func_array(array('App\\Service\\Utils', 'sendNotification'), array(false, 'e-mail', -1, 'tech@wedoit-group.com', array(), array(), null, null, false, '', '', 'suspicious_domain', $entity_id, 1, null, $twig, $em));
}
}
return $result;
}
public function checkSecurityToken($server_token, $security_token, $ip_address): bool
{
$response = false;
if ($this->settings['api_disable_security_check'] === '0') {
$server = $this->em->getRepository(Server::class)->findOneBy(['token' => $server_token]);
if ($server and $server->getIpAddress() == $ip_address) {
$secret_key = 'XHMGJ4ceqjtHnSNmKj7TN99YQhVXbDgsWfRCj3fTVNM6jdpR4eVbqMkG9kme3DSK';
$secret_key_2 = 'c6GytFtYMpU2XpY53c2yDjSUR76WtkzB';
$token = strtoupper(substr(md5($server->getToken() . $secret_key . date('Ymd') . $secret_key_2), 0 , 50));
if ($security_token === $token) {
$response = true;
}
}
}
else {
$response = true;
}
return $response;
}
public function storeFile($file_name, $path, $params = array(), $object = null, $object_id = null)
{
//$file_name = md5(uniqid()) . '.' . $file->guessExtension();
$size = filesize($path);
$extension = pathinfo($file_name, PATHINFO_EXTENSION);
$upload_dir = $path;
$file_document = new File();
$file_document->setFileName($file_name);
$file_document->setPath($path);
$file_document->setParams($params);
$file_document->setExtension($extension);
$file_document->setSize($size);
$file_document->setObject($object);
$file_document->setObjectId($object_id);
$file_document->setCreatedAt(new DateTime());
$this->em->persist($file_document);
$this->em->flush();
}
public function writeLog($type, $action, $message = null, $object = null, $object_id = null, $customer_id = null)
{
if ($this->requestStack->getCurrentRequest() != null) {
$ip = $this->requestStack->getCurrentRequest()->getClientIp();
if ($ip == 'unknown') {
$ip = $_SERVER['REMOTE_ADDR'];
}
} else {
$ip = '000.000.000.000';
}
/*if ($customer_id != null) {
$customer = $this->em->getRepository(Customer::class)->find($customer_id);
}
else {
$customer = $this->em->getRepository(Customer::class)->find($this->requestStack->getSession()->get('customer_id'));
}*/
if ($this->tokenStorage->getToken() === null) {
$user = null;
}
else {
$user = $this->tokenStorage->getToken()->getUser();
}
$log = new Log();
//$log->setCustomer($customer);
//$log->setUser($user);
$log->setIpaddress(ip2long($ip));
$log->setCreatedAt(new DateTime());
$log->setType($type);
$log->setAction($action);
$log->setMessage(array('message' => $message));
$log->setObject($object);
$log->setObjectId($object_id);
//$log->setObjectCode(null);
//$log->setObjectBefore($object_before);
//$log->setObjectAfter($object_after);
$this->em->persist($log);
$this->em->flush();
}
public function sendNotification($external = false, $type, $smtp_id = null, $to = null, $cc = null, $bcc = null, $pushover_api_key = null, $pushover_group_api_key = null, $read_receipt, $subject, $body, $entity = null, $entity_id = null, $template_id = null, $customer_id = null, $twig, $em): bool
{
if ($customer_id === null) {
$customer = $em->getRepository(Customer::class)->find(1);
}
else {
$customer = $em->getRepository(Customer::class)->find($customer_id);
}
$smtp = null;
if ($type === 'e-mail') {
if ($smtp_id === -1) {
$smtp = $em->getRepository(Smtp::class)->findOneBy(['is_default' => true]);
}
else {
$smtp = $em->getRepository(Smtp::class)->find($smtp_id);
}
$email_from = $smtp->getEmailFrom();
$email_to = $to;
$email_cc = implode( ',', $cc);
$email_bcc = implode( ',', $bcc);
}
else if ($type === 'pushover') {
$email_from = '';
$email_to = '';
$email_cc = '';
$email_bcc = '';
}
if ($template_id !== null) {
$template = $em->getRepository(NotificationTemplate::class)->find($template_id);
if ($template) {
$entity = $template->getEntity();
if ($type === 'e-mail') {
$subject = $template->getSubject();
$body = $template->getBody();
}
else if ($type === 'pushover') {
$subject = $template->getSubjectPushover();
$body = $template->getBodyPushover();
}
if ($template->getEntity() !== null) {
$entity_for_body_string = str_replace(' ', '', ucwords(str_replace('_', ' ', $template->getEntity())));
$entity_data = $em->getRepository('App\Entity\\' . $entity_for_body_string)->findOneBy(['id' => $entity_id]);
$template_path = '';
if ($external == true) {
$template_path = 'templates/';
}
$template_subject_temp = $twig->render($template_path . 'notification_template/notification_template.html.twig', array('body' => htmlspecialchars_decode($subject, ENT_QUOTES)));
if ($type === 'e-mail') {
$template_temp = $twig->render($template_path . 'notification_template/notification_template_with_layout.html.twig', array('title' => htmlspecialchars_decode($subject, ENT_QUOTES), 'body' => htmlspecialchars_decode($body, ENT_QUOTES), 'background_color' => $template->getBackgroundColor(), 'font_color' => $template->getFontColor()));
}
else if ($type === 'pushover') {
$template_temp = $twig->render($template_path . 'notification_template/notification_template.html.twig', array('body' => htmlspecialchars_decode($body, ENT_QUOTES)));
}
$template_subject_twig = $twig->createTemplate($template_subject_temp);
$subject = $template_subject_twig->render(array('entity' => $entity_data));
$template_twig = $twig->createTemplate($template_temp);
$body = $template_twig->render(array('entity' => $entity_data));
}
}
}
/*$object = null;
if ($entity != null and $entity_id != null) {
$entity_for_body_string = str_replace(' ', '', ucwords(str_replace('_', ' ', $entity)));
$entity_for_body = $this->em->getRepository('App\Entity\\' . $entity_for_body_string)->findOneBy(['id' => $entity_id]);
$object_lines['name'] = '';
$object_lines['content'] = array();
if ($entity === 'quote' or $entity === 'customer_order' or $entity === 'invoice' or $entity === 'credit_note' or $entity === 'shipping_note' or $entity === 'purchase_request' or $entity === 'purchase_quotation' or $entity === 'purchase_order' or $entity === 'passive_invoice' or $entity === 'passive_credit_note' or $entity === 'service_call' or $entity === 'good_receipt' or $entity === 'work_order') {
$entity_for_line = lcfirst(str_replace(' ', '', $entity_for_body_string));
$entity_line = $entity_for_body_string . 'Line';
$entity_lines = $this->em->getRepository('App\Entity\\' . $entity_line)->findBy([$entity_for_line => $entity_for_body]);
$object_lines['name'] = $entity . '_lines';
$object_lines['content'] = $entity_lines;
}
$object['name'] = $entity;
$object['content'] = $entity_for_body;
$template_temp = $this->twig->render('email_template/email_template.html.twig', array('body' => htmlspecialchars_decode($body, ENT_QUOTES)));
$template_twig = $this->twig->createTemplate($template_temp);
$body = $template_twig->render(array($object['name'] => $object['content'], $object_lines['name'] => $object_lines['content']));
}*/
/*$notification = New NotificationQueue();
//$email->setCustomer($company);
$notification->setSmtp($smtp);
$notification->setType($type);
$notification->setEmailFrom($email_from);
$notification->setEmailTo($email_to);
$notification->setEmailCC($email_cc);
$notification->setEmailBcc($email_bcc);
$notification->setPushoverApiKey($pushover_api_key);
$notification->setPushoverGroupApiKey($pushover_group_api_key);
$notification->setReadReceipt($read_receipt);
$notification->setSubject($subject);
$notification->setBody($body);
$notification->setEntity($entity);
$notification->setEntityId($entity_id);
//$email->setTryCounter(0);
$notification->setStatus('waiting');
$notification->setCreatedAt(new DateTime());
$em->persist($notification);
$em->flush();*/
return true;
}
function getServerArray(): array
{
return array(
'cpu_percent' => '',
'memory_total' => '',
'memory_percent' => '',
'memory_used' => '',
'memory_free' => '',
'disk_total' => '',
'disk_used' => '',
'disk_free' => '',
'last_check' => '',
'data' => '',
'run_time' => ''
);
}
function getUserSettingsArray(): array
{
return array(
'datatable_number_rows' => '25',
);
}
function timeDiffMinutes($start_time, $end_time) {
$interval = $start_time->diff($end_time);
$days = $interval->format("%d");
$hours = $interval->format('%h');
$minutes = $interval->format('%i');
if ($days > 0) {
return ($hours * 60 + $minutes) + ($days * 24 * 60);
}
return ($hours * 60 + $minutes);
}
}