Completed
Branch 0.4-dev (999b58)
by Evgenij
18:41
created

WriteIoHandler::writeDataToSocket()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 30
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 30
ccs 19
cts 19
cp 1
rs 8.439
cc 5
eloc 19
nc 6
nop 3
crap 5
1
<?php
2
/**
3
 * Async sockets
4
 *
5
 * @copyright Copyright (c) 2015-2016, Efimov Evgenij <[email protected]>
6
 *
7
 * This source file is subject to the MIT license that is bundled
8
 * with this source code in the file LICENSE.
9
 */
10
namespace AsyncSockets\RequestExecutor\Pipeline;
11
12
use AsyncSockets\Event\WriteEvent;
13
use AsyncSockets\Operation\InProgressWriteOperation;
14
use AsyncSockets\Operation\OperationInterface;
15
use AsyncSockets\Operation\WriteOperation;
16
use AsyncSockets\RequestExecutor\EventHandlerInterface;
17
use AsyncSockets\RequestExecutor\Metadata\RequestDescriptor;
18
use AsyncSockets\RequestExecutor\RequestExecutorInterface;
19
use AsyncSockets\Socket\SocketInterface;
20
21
/**
22
 * Class WriteIoHandler
23
 */
24
class WriteIoHandler extends AbstractOobHandler
25
{
26
    /** {@inheritdoc} */
27 38
    public function supports(OperationInterface $operation)
28
    {
29 38
        return ($operation instanceof WriteOperation) || ($operation instanceof InProgressWriteOperation);
30
    }
31
32
    /** {@inheritdoc} */
33 42
    protected function handleOperation(
34
        RequestDescriptor $descriptor,
35
        RequestExecutorInterface $executor,
36
        EventHandlerInterface $eventHandler
37
    ) {
38
        $operation = $descriptor->getOperation();
39
        $socket    = $descriptor->getSocket();
40 42
41
        /** @var WriteOperation $operation */
42 42
        $fireEvent = !($operation instanceof InProgressWriteOperation);
43 41
44 41
        if ($fireEvent) {
45 41
            $meta  = $executor->socketBag()->getSocketMetaData($socket);
46 41
            $event = new WriteEvent(
47 41
                $operation,
48 41
                $executor,
49 41
                $socket,
50 41
                $meta[ RequestExecutorInterface::META_USER_CONTEXT ]
51 30
            );
52 30
            $eventHandler->invokeEvent($event);
53 1
            $nextOperation = $event->getNextOperation();
54
        } else {
55
            $nextOperation = $operation;
56 31
        }
57
58
        return $this->writeDataToSocket($operation, $socket, $nextOperation);
59
    }
60
61
    /**
62
     * Perform data writing to socket and return suitable next socket operation
63
     *
64
     * @param WriteOperation     $operation Current write operation instance
65
     * @param SocketInterface    $socket Socket object
66
     * @param OperationInterface $nextOperation Desirable next operation
67
     *
68 31
     * @return OperationInterface Actual next operation
69
     */
70
    private function writeDataToSocket(
71
        WriteOperation $operation,
72
        SocketInterface $socket,
73 31
        OperationInterface $nextOperation = null
74 31
    ) {
75 31
        $result               = $nextOperation;
76 9
        $extractNextOperation = true;
77 9
        if ($operation->hasData()) {
78 9
            $data    = $operation->getData();
79 6
            $length  = strlen($data);
80 2
            $written = $socket->write($data, $operation->isOutOfBand());
81
            if ($length !== $written) {
82 2
                $extractNextOperation = false;
83 2
84 2
                $operation = $this->makeInProgressWriteOperation($operation, $nextOperation);
85 2
                $operation->setData(
86
                    substr($operation->getData(), $written)
87 2
                );
88 2
89 6
                $result = $operation;
90
            }
91 28
        }
92
93 1
        if ($extractNextOperation && ($operation instanceof InProgressWriteOperation)) {
94 1
            /** @var InProgressWriteOperation $operation */
95
            $result = $operation->getNextOperation();
96 28
        }
97
98
        return $result;
99
    }
100
101
    /**
102
     * Marks write operation as in progress
103
     *
104
     * @param WriteOperation     $operation Current operation object
105
     * @param OperationInterface $nextOperation Next planned operation
106
     *
107 2
     * @return InProgressWriteOperation Next operation object
108
     */
109 2
    private function makeInProgressWriteOperation(WriteOperation $operation, OperationInterface $nextOperation = null)
110 2
    {
111 2
        $result = $operation;
112 2
        if (!($result instanceof InProgressWriteOperation)) {
113
            $result = new InProgressWriteOperation($nextOperation, $operation->getData());
114 2
        }
115
116
        return $result;
117
    }
118
}
119