Passed
Push — master ( 694c78...f1dcbc )
by Aimeos
06:27 queued 02:01
created

Standard::run()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 85
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 28
nc 2
nop 0
dl 0
loc 85
rs 9.472
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Metaways Infosystems GmbH, 2013
6
 * @copyright Aimeos (aimeos.org), 2015-2021
7
 * @package Controller
8
 * @subpackage Order
9
 */
10
11
12
namespace Aimeos\Controller\Jobs\Order\Email\Payment;
13
14
use \Aimeos\MW\Logger\Base as Log;
15
16
17
/**
18
 * Order payment e-mail job controller.
19
 *
20
 * @package Controller
21
 * @subpackage Order
22
 */
23
class Standard
24
	extends \Aimeos\Controller\Jobs\Base
25
	implements \Aimeos\Controller\Jobs\Iface
26
{
27
	/**
28
	 * Returns the localized name of the job.
29
	 *
30
	 * @return string Name of the job
31
	 */
32
	public function getName() : string
33
	{
34
		return $this->getContext()->translate( 'controller/jobs', 'Order payment related e-mails' );
35
	}
36
37
38
	/**
39
	 * Returns the localized description of the job.
40
	 *
41
	 * @return string Description of the job
42
	 */
43
	public function getDescription() : string
44
	{
45
		return $this->getContext()->translate( 'controller/jobs', 'Sends order confirmation or payment status update e-mails' );
46
	}
47
48
49
	/**
50
	 * Executes the job.
51
	 *
52
	 * @throws \Aimeos\Controller\Jobs\Exception If an error occurs
53
	 */
54
	public function run()
55
	{
56
		$context = $this->getContext();
57
		$config = $context->getConfig();
58
59
		$client = \Aimeos\Client\Html\Email\Payment\Factory::create( $context );
60
61
		$orderManager = \Aimeos\MShop::create( $context, 'order' );
62
63
		/** controller/jobs/order/email/payment/limit-days
64
		 * Only send payment e-mails of orders that were created in the past within the configured number of days
65
		 *
66
		 * The payment e-mails are normally send immediately after the payment
67
		 * status has changed. This option prevents e-mails for old order from
68
		 * being send in case anything went wrong or an update failed to avoid
69
		 * confusion of customers.
70
		 *
71
		 * @param integer Number of days
72
		 * @since 2014.03
73
		 * @category User
74
		 * @category Developer
75
		 * @see controller/jobs/order/email/delivery/limit-days
76
		 * @see controller/jobs/service/delivery/process/limit-days
77
		 */
78
		$limit = $config->get( 'controller/jobs/order/email/payment/limit-days', 30 );
79
		$limitDate = date( 'Y-m-d H:i:s', time() - $limit * 86400 );
80
81
		$default = array(
82
			\Aimeos\MShop\Order\Item\Base::PAY_REFUND,
83
			\Aimeos\MShop\Order\Item\Base::PAY_PENDING,
84
			\Aimeos\MShop\Order\Item\Base::PAY_AUTHORIZED,
85
			\Aimeos\MShop\Order\Item\Base::PAY_RECEIVED,
86
		);
87
88
		/** controller/jobs/order/email/payment/status
89
		 * Only send order payment notification e-mails for these payment status values
90
		 *
91
		 * Notification e-mail about payment status changes can be sent for these
92
		 * status values:
93
		 *
94
		 * * 0: deleted
95
		 * * 1: canceled
96
		 * * 2: refused
97
		 * * 3: refund
98
		 * * 4: pending
99
		 * * 5: authorized
100
		 * * 6: received
101
		 *
102
		 * User-defined status values are possible but should be in the private
103
		 * block of values between 30000 and 32767.
104
		 *
105
		 * @param integer Payment status constant
106
		 * @since 2014.03
107
		 * @category User
108
		 * @category Developer
109
		 * @see controller/jobs/order/email/delivery/status
110
		 * @see controller/jobs/order/email/payment/limit-days
111
		 */
112
		foreach( (array) $config->get( 'controller/jobs/order/email/payment/status', $default ) as $status )
113
		{
114
			$orderSearch = $orderManager->filter();
115
116
			$param = array( \Aimeos\MShop\Order\Item\Status\Base::EMAIL_PAYMENT, (string) $status );
117
			$orderFunc = $orderSearch->make( 'order:status', $param );
118
119
			$expr = array(
120
				$orderSearch->compare( '>=', 'order.mtime', $limitDate ),
121
				$orderSearch->compare( '==', 'order.statuspayment', $status ),
122
				$orderSearch->compare( '==', $orderFunc, 0 ),
123
			);
124
			$orderSearch->setConditions( $orderSearch->and( $expr ) );
125
126
			$start = 0;
127
128
			do
129
			{
130
				$items = $orderManager->search( $orderSearch );
131
132
				$this->process( $client, $items, $status );
133
134
				$count = count( $items );
135
				$start += $count;
136
				$orderSearch->slice( $start );
137
			}
138
			while( $count >= $orderSearch->getLimit() );
139
		}
140
	}
141
142
143
	/**
144
	 * Adds the status of the delivered e-mail for the given order ID
145
	 *
146
	 * @param string $orderId Unique order ID
147
	 * @param int $value Status value
148
	 */
149
	protected function addOrderStatus( string $orderId, int $value )
150
	{
151
		$orderStatusManager = \Aimeos\MShop::create( $this->getContext(), 'order/status' );
152
153
		$statusItem = $orderStatusManager->create();
154
		$statusItem->setParentId( $orderId );
155
		$statusItem->setType( \Aimeos\MShop\Order\Item\Status\Base::EMAIL_PAYMENT );
156
		$statusItem->setValue( $value );
157
158
		$orderStatusManager->save( $statusItem );
159
	}
160
161
162
	/**
163
	 * Returns the delivery address item of the order
164
	 *
165
	 * @param \Aimeos\MShop\Order\Item\Base\Iface $orderBaseItem Order including address items
166
	 * @return \Aimeos\MShop\Order\Item\Base\Address\Iface Delivery or payment address item
167
	 * @throws \Aimeos\Controller\Jobs\Exception If no address item is available
168
	 */
169
	protected function getAddressItem( \Aimeos\MShop\Order\Item\Base\Iface $orderBaseItem ) : \Aimeos\MShop\Order\Item\Base\Address\Iface
170
	{
171
		$type = \Aimeos\MShop\Order\Item\Base\Address\Base::TYPE_PAYMENT;
172
		if( ( $addr = current( $orderBaseItem->getAddress( $type ) ) ) !== false ) {
173
			return $addr;
174
		};
175
176
		$msg = sprintf( 'No address found in order base with ID "%1$s"', $orderBaseItem->getId() );
177
		throw new \Aimeos\Controller\Jobs\Exception( $msg );
178
	}
179
180
181
	/**
182
	 * Returns an initialized view object
183
	 *
184
	 * @param \Aimeos\MShop\Context\Item\Iface $context Context item
185
	 * @param \Aimeos\MShop\Order\Item\Base\Iface $orderBaseItem Complete order including addresses, products, services
186
	 * @param string|null $langId ISO language code, maybe country specific
187
	 * @return \Aimeos\MW\View\Iface Initialized view object
188
	 */
189
	protected function view( \Aimeos\MShop\Context\Item\Iface $context, \Aimeos\MShop\Order\Item\Base\Iface $orderBaseItem, string $langId = null ) : \Aimeos\MW\View\Iface
190
	{
191
		$view = $context->view();
192
193
		$params = [
194
			'locale' => $langId,
195
			'site' => $orderBaseItem->getSiteCode(),
196
			'currency' => $orderBaseItem->getLocale()->getCurrencyId()
197
		];
198
199
		$helper = new \Aimeos\MW\View\Helper\Param\Standard( $view, $params );
200
		$view->addHelper( 'param', $helper );
201
202
		$helper = new \Aimeos\MW\View\Helper\Number\Locale( $view, $langId );
203
		$view->addHelper( 'number', $helper );
204
205
		$helper = new \Aimeos\MW\View\Helper\Config\Standard( $view, $context->getConfig() );
206
		$view->addHelper( 'config', $helper );
207
208
		$helper = new \Aimeos\MW\View\Helper\Mail\Standard( $view, $context->getMail()->createMessage() );
209
		$view->addHelper( 'mail', $helper );
210
211
		$helper = new \Aimeos\MW\View\Helper\Translate\Standard( $view, $context->getI18n( $langId ) );
212
		$view->addHelper( 'translate', $helper );
213
214
		return $view;
215
	}
216
217
218
	/**
219
	 * Sends the payment e-mail for the given orders
220
	 *
221
	 * @param \Aimeos\Client\Html\Iface $client HTML client object for rendering the payment e-mails
222
	 * @param \Aimeos\Map $items List of order items implementing \Aimeos\MShop\Order\Item\Iface with their IDs as keys
223
	 * @param int $status Delivery status value
224
	 */
225
	protected function process( \Aimeos\Client\Html\Iface $client, \Aimeos\Map $items, int $status )
226
	{
227
		$context = $this->getContext();
228
		$orderBaseManager = \Aimeos\MShop::create( $context, 'order/base' );
229
230
		foreach( $items as $id => $item )
231
		{
232
			try
233
			{
234
				$orderBaseItem = $orderBaseManager->load( $item->getBaseId() );
235
				$addr = $this->getAddressItem( $orderBaseItem );
236
237
				if( $addr->getEmail() )
238
				{
239
					$this->processItem( $client, $item, $orderBaseItem, $addr );
240
241
					$str = sprintf( 'Sent order payment e-mail for status "%1$s" to "%2$s"', $status, $addr->getEmail() );
242
					$context->getLogger()->log( $str, Log::INFO, 'email/order/payment' );
243
				}
244
245
				$this->addOrderStatus( $id, $status );
246
			}
247
			catch( \Exception $e )
248
			{
249
				$str = 'Error while trying to send payment e-mail for order ID "%1$s" and status "%2$s": %3$s';
250
				$msg = sprintf( $str, $item->getId(), $item->getStatusPayment(), $e->getMessage() );
251
				$context->getLogger()->log( $msg . PHP_EOL . $e->getTraceAsString(), Log::ERR, 'email/order/payment' );
252
			}
253
		}
254
	}
255
256
257
	/**
258
	 * Sends the payment related e-mail for a single order
259
	 *
260
	 * @param \Aimeos\Client\Html\Iface $client HTML client object for rendering the payment e-mails
261
	 * @param \Aimeos\MShop\Order\Item\Iface $orderItem Order item the payment related e-mail should be sent for
262
	 * @param \Aimeos\MShop\Order\Item\Base\Iface $orderBaseItem Complete order including addresses, products, services
263
	 * @param \Aimeos\MShop\Order\Item\Base\Address\Iface $addrItem Address item to send the e-mail to
264
	 */
265
	protected function processItem( \Aimeos\Client\Html\Iface $client, \Aimeos\MShop\Order\Item\Iface $orderItem,
266
		\Aimeos\MShop\Order\Item\Base\Iface $orderBaseItem, \Aimeos\MShop\Order\Item\Base\Address\Iface $addrItem )
267
	{
268
		$context = $this->getContext();
269
		$langId = ( $addrItem->getLanguageId() ?: $orderBaseItem->getLocale()->getLanguageId() );
270
271
		$view = $this->view( $context, $orderBaseItem, $langId );
272
		$view->extAddressItem = $addrItem;
273
		$view->extOrderBaseItem = $orderBaseItem;
274
		$view->extOrderItem = $orderItem;
275
276
		$client->setView( $view );
277
		$client->header();
278
		$client->body();
279
280
		$context->getMail()->send( $view->mail() );
281
	}
282
}
283