<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Gustavo Rodrigues]]></title>
  <link href="http://gustavobeavis.github.io/atom.xml" rel="self"/>
  <link href="http://gustavobeavis.github.io/"/>
  <updated>2014-12-10T22:50:19-02:00</updated>
  <id>http://gustavobeavis.github.io/</id>
  <author>
    <name><![CDATA[Gustavo da Silva Rodrigues]]></name>
    <email><![CDATA[gustavo.beavis@gmail.com]]></email>
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[web-socket-php]]></title>
    <link href="http://gustavobeavis.github.io/blog/2014/09/11/web-socket-php/"/>
    <updated>2014-09-11T21:14:11-03:00</updated>
    <id>http://gustavobeavis.github.io/blog/2014/09/11/web-socket-php</id>
    <content type="html"><![CDATA[<p><img src="http://gustavobeavis.github.io/../images/title_post_socket.png" alt="imagem" /></p>

<p>A web como conhecemos é baseada em solicitação/resposta de HTTP, ou seja, em cada site que você acessa, em cada solicitação AJAX que é feita ao servidor, temos uma alocação de um novo processo HTTP que entrará em uma fila pra ser respondido e o tempo de retorno pode variar de acordo com a capacidade do servidor em lidar com esses processos, sejam eles paralelos ou concorrentes, requisições simples ou requisições que dependam de uma grande capacidade computacional.</p>

<p>Agora quando pensamos em uma aplicação de respostas em tempo real, logo nos deparamos com um problema, chamado alta latência, pois, precisaremos consultar nosso servidor muito mais vezes, isso sem contar no número de clientes ativos fazendo requisições ao mesmo recurso ou áreas diferentes do mesmo sistema, causando lentidão no servidor e em casos mais graves, teremos problemas como timeout de execução ou queda do servidor.</p>

<h2>Event loop</h2>

<p><img src="http://gustavobeavis.github.io/../images/event_loop.png" alt="imagem" /></p>

<p>Toda aplicação realtime, necessariamente possui um loop de consulta de estado ou evento, isso pode estar tanto do lado cliente como do lado servidor. Esse loop ficará escutando a aplicação aguardando alguma mudança de estado, e caso haja atualização, o sistema deve enviar esses dados, a diferença entre o loop do cliente e o do servidor é que no caso do servidor temos um único serviço que irá ficar escutando todas as requisições e mandando as mudanças em tempo real para todos ou algum cliente específico via socket, já no caso do cliente, teremos um script long pooling em todos os clientes, que irá consultar periodicamente o servidor e receber as possíveis alterações do servidor.</p>

<h2>Primeiro socket PHP</h2>

<p>Para criar um socket com php, você deve seguir 6 passos, que vão da abertura de um socket até remover a mascara da mensagem resolver seu encode.</p>

<h4>Passos:</h4>

<ol>
<li>Abrir um socket.</li>
<li>Vincular a um endereço.</li>
<li>Escutar conexões de entrada</li>
<li>Aceitar conexões</li>
<li>WebSocket Handshake.</li>
</ol>


<h3>Passo 1 – Abrir um socket:</h3>

<p>Primeiro vamos criar um socket com <a href="http://php.net/manual/pt_BR/function.socket-create.php">socket_create</a>(Domain, Type, Protocol) do PHP:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="nv">$socket</span> <span class="o">=</span> <span class="nb">socket_create</span><span class="p">(</span><span class="nx">AF_INET</span><span class="p">,</span> <span class="nx">SOCK_STREAM</span><span class="p">,</span> <span class="nx">SOL_TCP</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Passo 2 – Vincular a um endereço:</h3>

<p><a href="http://php.net/manual/pt_BR/function.socket-bind.php">socket_bind()</a> recebe como parâmetro o resource do socket que já foi criado com o socket_create(), o endereço e  opcionalmente a porta.
Isto tem que ser feito antes que uma conexão seja estabelecida, usando socket_connect() ou socket_listen().</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="nb">socket_bind</span><span class="p">(</span><span class="nv">$socket</span><span class="p">,</span> <span class="s1">&#39;localhost&#39;</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Passo 3 – Escutar conexões de entrada</h3>

<p>Após o socket ter sido criado usando socket_create e associado para um nome com socket_bind() , ele deve dizer para aguardar por escuta em conexões que irão entrar socket com o <a href="http://php.net/manual/pt_BR/function.socket-listen.php">socket_listen()</a>.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="nb">socket_listen</span><span class="p">(</span><span class="nv">$socket</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Passo 4 – Aceitar conexões</h3>

<p>Após o socket ter sido criado usando socket_create(), passar um nome com socket_bind(), e dizer para listar conexões com socket_listen(), a função <a href="http://php.net/manual/pt_BR/function.socket-accept.php">socket_accept()</a> irá aceitar conexões vindas neste socket. Uma vez que uma conexão é feita com sucesso , um novo “resource” do socket é retornado, que deve ser usado para comunicação. Se há múltiplas conexões na fila do socket, a primeira irá ser usada. Se não há conexões pendentes, socket_accept() irá bloquear até que uma conexão esteja presente.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="nb">socket_accept</span><span class="p">(</span><span class="nv">$socket</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Passo 5 – WebSocket Handshake</h3>

<p>O cliente tem de apresentar-se, enviando uma solicitação WebSocket handshake para estabelecer uma conexão bem sucedida com o servidor, o pedido contém um Sec-WebSocket-Key que é uma chave em base64 de 16 bytes</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="nv">$secKey</span> <span class="o">=</span> <span class="nv">$headers</span><span class="p">[</span><span class="s1">&#39;Sec-WebSocket-Key&#39;</span><span class="p">];</span>
</span><span class='line'><span class="nv">$secAccept</span> <span class="o">=</span> <span class="nb">base64_encode</span><span class="p">(</span><span class="nb">pack</span><span class="p">(</span><span class="s1">&#39;H*&#39;</span><span class="p">,</span> <span class="nb">sha1</span><span class="p">(</span><span class="nv">$secKey</span> <span class="o">.</span> <span class="s1">&#39;258EAFA5-E914-47DA-95CA-C5AB0DC85B11&#39;</span><span class="p">)));</span>
</span><span class='line'><span class="nv">$upgrade</span>  <span class="o">=</span> <span class="s2">&quot;HTTP/1.1 101 Web Socket Protocol Handshake</span><span class="se">\r\n</span><span class="s2">&quot;</span> <span class="o">.</span>
</span><span class='line'><span class="s2">&quot;Upgrade: websocket</span><span class="se">\r\n</span><span class="s2">&quot;</span> <span class="o">.</span>
</span><span class='line'><span class="s2">&quot;Connection: Upgrade</span><span class="se">\r\n</span><span class="s2">&quot;</span> <span class="o">.</span>
</span><span class='line'><span class="s2">&quot;WebSocket-Origin: </span><span class="si">$host</span><span class="se">\r\n</span><span class="s2">&quot;</span> <span class="o">.</span>
</span><span class='line'><span class="s2">&quot;WebSocket-Location: ws://</span><span class="si">$host</span><span class="s2">:</span><span class="si">$port</span><span class="s2">/deamon.php</span><span class="se">\r\n</span><span class="s2">&quot;</span><span class="o">.</span>
</span><span class='line'><span class="s2">&quot;Sec-WebSocket-Accept:</span><span class="si">$secAccept</span><span class="se">\r\n\r\n</span><span class="s2">&quot;</span><span class="p">;</span>
</span><span class='line'><span class="nb">socket_write</span><span class="p">(</span><span class="nv">$client_conn</span><span class="p">,</span><span class="nv">$upgrade</span><span class="p">,</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$upgrade</span><span class="p">));</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Passo 5 – WebSocket Handshake</h3>

<p>Depois de fazer handshaking, o cliente pode enviar e receber mensagens, mas as mensagens enviadas são todas criptografadas, por isso, se queremos exibi-las, precisamos remover a mascara de cada frame de dado, conforme o <a href="http://tools.ietf.org/html/rfc6455#section-5.2">rfc6455</a>.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="c1">//Unmask incoming framed message</span>
</span><span class='line'>
</span><span class='line'><span class="k">function</span> <span class="nf">unmask</span><span class="p">(</span><span class="nv">$text</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="nv">$length</span> <span class="o">=</span> <span class="nb">ord</span><span class="p">(</span><span class="nv">$text</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="o">&amp;</span> <span class="mi">127</span><span class="p">;</span>
</span><span class='line'>    <span class="k">if</span><span class="p">(</span><span class="nv">$length</span> <span class="o">==</span> <span class="mi">126</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="nv">$masks</span> <span class="o">=</span> <span class="nx">substr</span><span class="p">(</span><span class="nv">$text</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">4</span><span class="p">);</span>
</span><span class='line'>        <span class="nv">$data</span> <span class="o">=</span> <span class="nx">substr</span><span class="p">(</span><span class="nv">$text</span><span class="p">,</span> <span class="mi">8</span><span class="p">);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="k">elseif</span><span class="p">(</span><span class="nv">$length</span> <span class="o">==</span> <span class="mi">127</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="nv">$masks</span> <span class="o">=</span> <span class="nx">substr</span><span class="p">(</span><span class="nv">$text</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">4</span><span class="p">);</span>
</span><span class='line'>        <span class="nv">$data</span> <span class="o">=</span> <span class="nx">substr</span><span class="p">(</span><span class="nv">$text</span><span class="p">,</span> <span class="mi">14</span><span class="p">);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>        <span class="nv">$masks</span> <span class="o">=</span> <span class="nx">substr</span><span class="p">(</span><span class="nv">$text</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">4</span><span class="p">);</span>
</span><span class='line'>        <span class="nv">$data</span> <span class="o">=</span> <span class="nx">substr</span><span class="p">(</span><span class="nv">$text</span><span class="p">,</span> <span class="mi">6</span><span class="p">);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="nv">$text</span> <span class="o">=</span> <span class="s2">&quot;&quot;</span><span class="p">;</span>
</span><span class='line'>    <span class="k">for</span> <span class="p">(</span><span class="nv">$i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nv">$i</span> <span class="o">&lt;</span> <span class="nb">strlen</span><span class="p">(</span><span class="nv">$data</span><span class="p">);</span> <span class="o">++</span><span class="nv">$i</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="nv">$text</span> <span class="o">.=</span> <span class="nv">$data</span><span class="p">[</span><span class="nv">$i</span><span class="p">]</span> <span class="o">^</span> <span class="nv">$masks</span><span class="p">[</span><span class="nv">$i</span><span class="o">%</span><span class="mi">4</span><span class="p">];</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="k">return</span> <span class="nv">$text</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="c1">//Encode message for transfer to client.</span>
</span><span class='line'><span class="k">function</span> <span class="nf">mask</span><span class="p">(</span><span class="nv">$text</span><span class="p">)</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'>    <span class="nv">$b1</span> <span class="o">=</span> <span class="mh">0x80</span> <span class="o">|</span> <span class="p">(</span><span class="mh">0x1</span> <span class="o">&amp;</span> <span class="mh">0x0f</span><span class="p">);</span>
</span><span class='line'>    <span class="nv">$length</span> <span class="o">=</span> <span class="nb">strlen</span><span class="p">(</span><span class="nv">$text</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">if</span><span class="p">(</span><span class="nv">$length</span> <span class="o">&lt;=</span> <span class="mi">125</span><span class="p">)</span>
</span><span class='line'>        <span class="nv">$header</span> <span class="o">=</span> <span class="nb">pack</span><span class="p">(</span><span class="s1">&#39;CC&#39;</span><span class="p">,</span> <span class="nv">$b1</span><span class="p">,</span> <span class="nv">$length</span><span class="p">);</span>
</span><span class='line'>    <span class="k">elseif</span><span class="p">(</span><span class="nv">$length</span> <span class="o">&gt;</span> <span class="mi">125</span> <span class="o">&amp;&amp;</span> <span class="nv">$length</span> <span class="o">&lt;</span> <span class="mi">65536</span><span class="p">)</span>
</span><span class='line'>        <span class="nv">$header</span> <span class="o">=</span> <span class="nb">pack</span><span class="p">(</span><span class="s1">&#39;CCn&#39;</span><span class="p">,</span> <span class="nv">$b1</span><span class="p">,</span> <span class="mi">126</span><span class="p">,</span> <span class="nv">$length</span><span class="p">);</span>
</span><span class='line'>    <span class="k">elseif</span><span class="p">(</span><span class="nv">$length</span> <span class="o">&gt;=</span> <span class="mi">65536</span><span class="p">)</span>
</span><span class='line'>        <span class="nv">$header</span> <span class="o">=</span> <span class="nb">pack</span><span class="p">(</span><span class="s1">&#39;CCNN&#39;</span><span class="p">,</span> <span class="nv">$b1</span><span class="p">,</span> <span class="mi">127</span><span class="p">,</span> <span class="nv">$length</span><span class="p">);</span>
</span><span class='line'>    <span class="k">return</span> <span class="nv">$header</span><span class="o">.</span><span class="nv">$text</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Executar</h3>

<p>Para executar o Socket basta você acessar o seu terminal e executar o script que serve como servidor, pois se inicia-lo via browser, o seu socket não funcionará.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="nx">php</span> <span class="o">-</span><span class="nx">q</span> <span class="nx">path</span><span class="o">-</span><span class="nx">to</span><span class="o">-</span><span class="nx">server</span><span class="o">/</span><span class="nx">server</span><span class="o">.</span><span class="nx">php</span>
</span></code></pre></td></tr></table></div></figure>


<p>Veja o Exemplo completo no <a href="https://github.com/gustavobeavis/ws_pure_php">github</a>.</p>

<h2>O React PHP</h2>

<p>O React PHP é uma biblioteca que foi criada para suprir uma necessidade crescente de computação reativa, ela fornece entre outras coisas a possibilidade de criar aplicações com IO não blocante, como o NodeJS.</p>

<h3>Um chat com React e Ratchet</h3>

<p>O Rachet possui um conjunto de soluções que abstraem e facilitam a criação, manutenção, envios e recebimentos de mensagens de um socket. Você terá que gerenciar os eventos do seu socket, com as funções.</p>

<h4>Funções</h4>

<ol>
<li>onOpen</li>
<li>onMessage</li>
<li>onClose</li>
<li>onError</li>
</ol>


<h3>onOpen</h3>

<p>Essa função é chamada assim que ocorre uma nova conexão, nela você usa um método para guardar a nova conexão para enviar mensagens.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="k">public</span> <span class="k">function</span> <span class="nf">onOpen</span><span class="p">(</span><span class="nx">ConnectionInterface</span> <span class="nv">$conn</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="c1">// Store the new connection to send messages to later</span>
</span><span class='line'>  <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">clients</span><span class="o">-&gt;</span><span class="na">attach</span><span class="p">(</span><span class="nv">$conn</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">echo</span> <span class="s2">&quot;New connection! (</span><span class="si">{</span><span class="nv">$conn</span><span class="o">-&gt;</span><span class="na">resourceId</span><span class="si">}</span><span class="s2">)</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<h3>onMessage</h3>

<p>Essa função é chamada quando o evento de existe uma nova mensagem, e com ela, você pode encaminhar essas mensagens para todos ou para alguns clientes conectados ao socket</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="k">public</span> <span class="k">function</span> <span class="nf">onMessage</span><span class="p">(</span><span class="nx">ConnectionInterface</span> <span class="nv">$from</span><span class="p">,</span> <span class="nv">$msg</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="nv">$numRecv</span> <span class="o">=</span> <span class="nb">count</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">clients</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>    <span class="k">echo</span> <span class="nb">sprintf</span><span class="p">(</span><span class="s1">&#39;Connection %d sending message &quot;%s&quot; to %d other connection%s&#39;</span> <span class="o">.</span> <span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span>
</span><span class='line'>        <span class="p">,</span> <span class="nv">$from</span><span class="o">-&gt;</span><span class="na">resourceId</span><span class="p">,</span> <span class="nv">$msg</span><span class="p">,</span> <span class="nv">$numRecv</span><span class="p">,</span> <span class="nv">$numRecv</span> <span class="o">==</span> <span class="mi">1</span> <span class="o">?</span> <span class="s1">&#39;&#39;</span> <span class="o">:</span> <span class="s1">&#39;s&#39;</span><span class="p">);</span>
</span><span class='line'>    <span class="nv">$dados</span> <span class="o">=</span> <span class="nb">json_decode</span><span class="p">(</span><span class="nv">$msg</span><span class="p">,</span> <span class="k">true</span><span class="p">);</span>
</span><span class='line'>    <span class="nv">$dados</span><span class="p">[</span><span class="s1">&#39;id&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="nv">$from</span><span class="o">-&gt;</span><span class="na">resourceId</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">foreach</span> <span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">clients</span> <span class="k">as</span> <span class="nv">$client</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>
</span><span class='line'>            <span class="c1">// The sender is not the receiver, send to each client connected</span>
</span><span class='line'>            <span class="nv">$client</span><span class="o">-&gt;</span><span class="na">send</span><span class="p">(</span><span class="nb">json_encode</span><span class="p">(</span><span class="nv">$dados</span><span class="p">));</span>
</span><span class='line'>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<h3>onClose</h3>

<p>Essa função é chamada assim que um um cliente se desconecta do websocket, e a partir dele, você pode atribuir callbacks para esse evento.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="k">public</span> <span class="k">function</span> <span class="nf">onClose</span><span class="p">(</span><span class="nx">ConnectionInterface</span> <span class="nv">$conn</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="c1">// The connection is closed, remove it, as we can no longer send it messages</span>
</span><span class='line'>    <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">clients</span><span class="o">-&gt;</span><span class="na">detach</span><span class="p">(</span><span class="nv">$conn</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">echo</span> <span class="s2">&quot;Connection </span><span class="si">{</span><span class="nv">$conn</span><span class="o">-&gt;</span><span class="na">resourceId</span><span class="si">}</span><span class="s2"> has disconnected</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<h3>onError</h3>

<p>Esse evento é disparado quando ocorre um erro interno no servidor.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="k">public</span> <span class="k">function</span> <span class="nf">onError</span><span class="p">(</span><span class="nx">ConnectionInterface</span> <span class="nv">$conn</span><span class="p">,</span> <span class="nx">\Exception</span> <span class="nv">$e</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">echo</span> <span class="s2">&quot;An error has occurred: </span><span class="si">{</span><span class="nv">$e</span><span class="o">-&gt;</span><span class="na">getMessage</span><span class="p">()</span><span class="si">}</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="nv">$conn</span><span class="o">-&gt;</span><span class="na">close</span><span class="p">();</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Executar</h3>

<p>Para executar o Socket basta você acessar o seu terminal e executar o script que serve como servidor, pois se inicia-lo via browser, o seu socket não funcionará.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="nx">php</span> <span class="o">-</span><span class="nx">q</span> <span class="nx">path</span><span class="o">-</span><span class="nx">to</span><span class="o">-</span><span class="nx">server</span><span class="o">/</span><span class="nx">server</span><span class="o">.</span><span class="nx">php</span>
</span></code></pre></td></tr></table></div></figure>


<p>Veja o Exemplo completo no <a href="https://github.com/gustavobeavis/ws_react_basic">github</a>.</p>

<h2>Javascript</h2>

<p>Uma vez criado o socket, você pode acessa-lo do seu browser, lembrando que para acessa-lo de forma nativa, só browsers modernos suportem a API websocket, do contrário, existem diversas saídas, como flashsocket e javasocket, no qual você pode acessa-lo do seu script.</p>

<p>Assim como no caso do servidor, teremos funções com callbacks para todos os eventos de um socket, que são:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">wsUri</span> <span class="o">=</span> <span class="s2">&quot;ws://localhost:1234&quot;</span><span class="p">;</span>
</span><span class='line'><span class="kd">var</span> <span class="nx">connection</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">WebSocket</span><span class="p">(</span><span class="nx">wsUri</span><span class="p">);</span>
</span><span class='line'><span class="c1">// When the connection is open, send some data to the server</span>
</span><span class='line'><span class="nx">connection</span><span class="p">.</span><span class="nx">onopen</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span><span class='line'>  <span class="nx">connection</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s1">&#39;Ping&#39;</span><span class="p">);</span> <span class="c1">// Send the message &#39;Ping&#39; to the server</span>
</span><span class='line'><span class="p">};</span>
</span><span class='line'>
</span><span class='line'><span class="c1">// Log errors</span>
</span><span class='line'><span class="nx">connection</span><span class="p">.</span><span class="nx">onerror</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;WebSocket Error &#39;</span> <span class="o">+</span> <span class="nx">error</span><span class="p">);</span>
</span><span class='line'><span class="p">};</span>
</span><span class='line'>
</span><span class='line'><span class="c1">// Log messages from the server</span>
</span><span class='line'><span class="nx">connection</span><span class="p">.</span><span class="nx">onmessage</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;Server: &#39;</span> <span class="o">+</span> <span class="nx">e</span><span class="p">.</span><span class="nx">data</span><span class="p">);</span>
</span><span class='line'><span class="p">};</span>
</span></code></pre></td></tr></table></div></figure>


<p>Eu fiz um exemplo completo usando Angular js, que encontra-se no <a href="https://github.com/gustavobeavis/ws_angular">github</a>.</p>

<h2>Vantagens e desvantagens</h2>

<p>A vantagem de usar um websoket é que ao invés de termos muitos clientes fazendo requisições periódicas http ao mesmo endpoint para verificar possíveis mudanças de estado da aplicação, o socket que irá gerenciar as alterações e mandar para o(os) clientes essas atualizações logo que elas ocorrerem, evitando um tráfego desnecessário de requisições http, como consultas de estado sem mudança ou ainda muitos clientes consultando a mesma coisa. Em contra partida, teremos um script executando um loop infinito no servidor, aguardando algum evento para transmitir para os usuários, ou seja, embora você resolva a latência, você terá um processo que irá consumir recursos do servidor durante todo tempo de que você mante-lo rodando, independente se houver ou não novos eventos, solicitações ou usuários ativos.</p>

<p>Além disso, podemos ter situações onde o navegador do cliente não tenha suporte websoket, flash ou java. Nesses casos, não teremos como evitar o uso de long pooling.</p>

<p>O Websoket é o futuro, porém, o PHP não é a melhor saída para esse tipo de recurso, embora funcione bem na maioria dos casos. Eu aconselho o uso de Erlang ou Node JS, por serem linguagens de natureza não blocante e por lidarem melhor com concorrência.</p>

<h2>Aplicações</h2>

<p>Os websockets podem ter muitas aplicações, sobre tudo, em:</p>

<ul>
<li>Chats</li>
<li>Games multi-player online</li>
<li>Sistemas de sincronização mobile/Web</li>
</ul>


<h2>Referências</h2>

<p><a href="http://www.html5rocks.com/pt/tutorials/websockets/basics/">HTML5 Rocks – Apresentando WebSockets – PT</a></p>

<p><a href="Sergio%20Lopes%20%E2%80%93%20SPYD%20e%20HTTP%202.0%20%E2%80%93%20PT">Sergio Lopes – SPYD e HTTP 2.0 – PT</a></p>

<p><a href="http://blog.glaucocustodio.com/2012/09/22/otimizando-performance-com-compactacao-gzip-deflate/">JustCode – Otimizando Performance com Compactação Gzip/Deflate</a></p>

<p><a href="http://www.sanwebe.com/2013/05/chat-using-websocket-php-socket">Sanwebe – mple Chat Using WebSocket and PHP Socket – EN</a></p>

<p><a href="http://socketo.me/">Ratchet – Lib</a></p>

<p><a href="http://socket.io/">socket.io</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Processando Uma Pilha De Imagens Sem Traumas]]></title>
    <link href="http://gustavobeavis.github.io/blog/2014/04/03/processando-uma-pilha-de-imagens-sem-traumas/"/>
    <updated>2014-04-03T23:09:59-03:00</updated>
    <id>http://gustavobeavis.github.io/blog/2014/04/03/processando-uma-pilha-de-imagens-sem-traumas</id>
    <content type="html"><![CDATA[<p><img src="http://gustavobeavis.github.io/../images/destaque_reduz_image.png" alt="imagem" /></p>

<p>Quem nunca precisou processar um número consideravel de imagens para um relatório, não tem idéia da dor de cabeça que isso pode dar. Em um mundo ideal, todo thumb ou imagem tratada, é gerada no momento do upload, porém por diversos fatores, podemos nos deparar com a necessidade de fazer isso sob demanda, e como todos sabemos, isso pode implicar em uma série de problemas, como demora ao gerar essas imagens, e em situações mais graves, podemos ter um estouro de memória, lentidão no servidor, timeout na execução, em fim, tudo que você não quer fazer.</p>

<p>Pensando nisso, vamos desenvolver uma solução que ataca os principais gargalos desse tipo de tarefa, que são a ausência de <strong>threds</strong> em <strong>PHP</strong> e o processo de <strong>IO</strong>.</p>

<h2>Solução</h2>

<p>Iremos desenvolver um serviço capaz de de criar as imagens que ainda não foram criadas, e melhor, paralelamente, e usando um recurso que não usa diretamente a thread do <strong>php</strong></p>

<h3>Checando os arquivos a serem gerados</h3>

<p>Vamos criar um processo capaz de criar thumbs de imagens que ainda não foram criadas, de modo que, antes de começarmos a processar nossa pilha de imagens saberemos o que devemos ou não criar, além disso, ao invés de checar a existência dessas imagens em um loop de file_exists, vamos primeiro listar todos os arquivos da pasta destino e guardar em um array (uma única requisição ao invés de varias requisições em um loop de file_exists), depois disso vamos fazer um diff_contains dos dos arrays de images a serem processadas com as imagens do servidor, ai o array resultante, é o array de imagens que precisamos criar (que não estão no servidor).</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="c1">// Origem</span>
</span><span class='line'><span class="nv">$origin</span> <span class="o">=</span> <span class="nb">scandir</span><span class="p">(</span><span class="s1">&#39;image/origin&#39;</span><span class="p">);</span>
</span><span class='line'><span class="nv">$origin</span> <span class="o">=</span> <span class="nb">array_slice</span><span class="p">(</span><span class="nv">$origin</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="nb">count</span><span class="p">(</span><span class="nv">$origin</span><span class="p">));</span>
</span><span class='line'>
</span><span class='line'><span class="c1">//destino</span>
</span><span class='line'><span class="nv">$destination</span> <span class="o">=</span> <span class="nb">scandir</span><span class="p">(</span><span class="s1">&#39;image/destination&#39;</span><span class="p">);</span>
</span><span class='line'><span class="nv">$destination</span> <span class="o">=</span> <span class="nb">array_slice</span><span class="p">(</span><span class="nv">$destination</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="nb">count</span><span class="p">(</span><span class="nv">$destination</span><span class="p">));</span>
</span><span class='line'>
</span><span class='line'><span class="c1">//Imagens a serem geradas</span>
</span><span class='line'><span class="nv">$terms_list</span> <span class="o">=</span> <span class="nb">array_diff</span><span class="p">(</span><span class="nv">$origin</span><span class="p">,</span> <span class="nv">$destination</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Criando os Thumbs</h3>

<p>Já resolvemos o primeiro problema, que é checar quais imagens devemos criar os thumbs, agora temos dois problemas, na verdade um, só que dividido em duas partes, que é o processo de gerar e salvar as imagens. E como todos nós sabemos, todo processo de IO é custoso, isso sem contar com o custo de processamento que o PHP tem ao tratar essas imagens antes de salva-la. Como não temos threds no PHP, temos que gerar uma fila de execução, o que gera um grande buzy-waiting, de modo que pode até causar um timeout do servidor. Para resolver esse problema, precisamos dividir esse processo em duas partes, a primeira é processar as imagens em paralelo (usando o cURL mult_exec), depois usar a solução mais eficaz para processar as imagens que é usar o <strong>Imagemagick</strong> ao invés do GD.</p>

<blockquote><p><strong>Por que Imagemagick?</strong></p>

<p>O Imagemagick ao contrario do GD executa seus processos fora do PHP, ou seja, ele não vai consumir o processo do PHP para fazer sua mágica, além disso, se compararmos a qualidade da imagem gerada entre um e outro, o Imagemagick consegue ter um nível bem superior ao GD.</p></blockquote>

<p>Vamos criar uma classe capaz de usar ambas as bibliotecas, pois, desse modo, independente de haver ou não o Imagemagick no servidor, essas imagens serão geradas.</p>

<h5>Interface Image</h5>

<p>Vamos primeiramente criar um contrato, para que todas as classes de imagens apliquem os métodos usando o mesmo critério, embora de modo diferente.</p>

<p><strong><em>Image.php</em></strong>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * Interface Image</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'><span class="k">interface</span> <span class="nx">Image</span><span class="p">{</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @param $file</span>
</span><span class='line'><span class="sd">     * @param $anchor</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">function</span> <span class="nf">open</span><span class="p">(</span><span class="nv">$file</span><span class="p">,</span> <span class="nv">$anchor</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @param $width</span>
</span><span class='line'><span class="sd">     * @param $height</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">function</span> <span class="nf">resize</span><span class="p">(</span><span class="nv">$width</span><span class="p">,</span> <span class="nv">$height</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @param $file</span>
</span><span class='line'><span class="sd">     * @param $quality</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">function</span> <span class="nf">save</span><span class="p">(</span><span class="nv">$file</span><span class="p">,</span> <span class="nv">$quality</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<h5>Classe imageGenerateGD</h5>

<p>Feito Isso, vamos criar nossa Classe que usa o GD para criar nossos thumbs.</p>

<p><strong><em>imageGenerateGD.php</em></strong>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
<span class='line-number'>80</span>
<span class='line-number'>81</span>
<span class='line-number'>82</span>
<span class='line-number'>83</span>
<span class='line-number'>84</span>
<span class='line-number'>85</span>
<span class='line-number'>86</span>
<span class='line-number'>87</span>
<span class='line-number'>88</span>
<span class='line-number'>89</span>
<span class='line-number'>90</span>
<span class='line-number'>91</span>
<span class='line-number'>92</span>
<span class='line-number'>93</span>
<span class='line-number'>94</span>
<span class='line-number'>95</span>
<span class='line-number'>96</span>
<span class='line-number'>97</span>
<span class='line-number'>98</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="k">include_once</span> <span class="s2">&quot;Image.php&quot;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * Class imageGenerateGD</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'><span class="k">class</span> <span class="nc">imageGenerateGD</span> <span class="k">implements</span>  <span class="nx">Image</span><span class="p">{</span>
</span><span class='line'>    <span class="k">private</span> <span class="nv">$image</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">__construct</span><span class="p">(){</span>
</span><span class='line'>        <span class="nv">$options</span> <span class="o">=</span> <span class="nb">func_get_args</span><span class="p">();</span>
</span><span class='line'>        <span class="k">if</span><span class="p">(</span><span class="nb">count</span><span class="p">(</span><span class="nv">$options</span><span class="p">)){</span>
</span><span class='line'>            <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">open</span><span class="p">(</span><span class="nv">$options</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @param $file</span>
</span><span class='line'><span class="sd">     * @param string $anchor</span>
</span><span class='line'><span class="sd">     * @return $this</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">function</span> <span class="nf">open</span><span class="p">(</span><span class="nv">$file</span><span class="p">,</span> <span class="nv">$anchor</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span><span class="p">){</span>
</span><span class='line'>        <span class="nv">$imagePath</span> <span class="o">=</span> <span class="nv">$anchor</span><span class="o">.</span><span class="nv">$file</span><span class="p">;</span>
</span><span class='line'>        <span class="k">switch</span> <span class="p">(</span><span class="nb">pathinfo</span><span class="p">(</span><span class="nv">$imagePath</span><span class="p">))</span> <span class="p">{</span>
</span><span class='line'>            <span class="k">case</span> <span class="s1">&#39;gif&#39;</span><span class="o">:</span>
</span><span class='line'>                <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span> <span class="o">=</span> <span class="nx">imagecreatefromgif</span><span class="p">(</span><span class="nv">$imagePath</span><span class="p">);</span>
</span><span class='line'>                <span class="k">break</span><span class="p">;</span>
</span><span class='line'>            <span class="k">case</span> <span class="s1">&#39;png&#39;</span><span class="o">:</span>
</span><span class='line'>                <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span> <span class="o">=</span> <span class="nx">imagecreatefrompng</span><span class="p">(</span><span class="nv">$imagePath</span><span class="p">);</span>
</span><span class='line'>                <span class="k">break</span><span class="p">;</span>
</span><span class='line'>            <span class="k">case</span> <span class="s1">&#39;jpg&#39;</span><span class="o">:</span>
</span><span class='line'>            <span class="k">case</span> <span class="s1">&#39;jpeg&#39;</span><span class="o">:</span>
</span><span class='line'>            <span class="k">case</span> <span class="s1">&#39;pjpeg&#39;</span><span class="o">:</span>
</span><span class='line'>            <span class="k">default</span><span class="o">:</span>
</span><span class='line'>                <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span> <span class="o">=</span> <span class="nx">imagecreatefromjpeg</span><span class="p">(</span><span class="nv">$imagePath</span><span class="p">);</span>
</span><span class='line'>                <span class="k">break</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>        <span class="nx">imagealphablending</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span><span class="p">,</span> <span class="k">true</span><span class="p">);</span>
</span><span class='line'>        <span class="nx">imagesavealpha</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span><span class="p">,</span> <span class="k">true</span><span class="p">);</span>
</span><span class='line'>        <span class="nx">imagecolorallocate</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">return</span> <span class="nv">$this</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @param $width</span>
</span><span class='line'><span class="sd">     * @param $height</span>
</span><span class='line'><span class="sd">     * @return $this</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">function</span> <span class="nf">resize</span><span class="p">(</span><span class="nv">$width</span> <span class="o">=</span> <span class="mi">160</span><span class="p">,</span> <span class="nv">$height</span> <span class="o">=</span> <span class="mi">160</span><span class="p">){</span>
</span><span class='line'>
</span><span class='line'>        <span class="c1">// get the current image dimensions</span>
</span><span class='line'>        <span class="nv">$geo</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span>
</span><span class='line'>            <span class="s1">&#39;width&#39;</span>     <span class="o">=&gt;</span>  <span class="nx">imagesx</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span><span class="p">),</span>
</span><span class='line'>            <span class="s1">&#39;height&#39;</span>    <span class="o">=&gt;</span>  <span class="nx">imagesy</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span><span class="p">)</span>
</span><span class='line'>        <span class="p">);</span>
</span><span class='line'>
</span><span class='line'>        <span class="nv">$original_aspect</span> <span class="o">=</span> <span class="nv">$geo</span><span class="p">[</span><span class="s1">&#39;width&#39;</span><span class="p">]</span> <span class="o">/</span> <span class="nv">$geo</span><span class="p">[</span><span class="s1">&#39;height&#39;</span><span class="p">];</span>
</span><span class='line'>        <span class="nv">$thumb_aspect</span> <span class="o">=</span> <span class="nv">$width</span> <span class="o">/</span> <span class="nv">$height</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span> <span class="nv">$original_aspect</span> <span class="o">&gt;=</span> <span class="nv">$thumb_aspect</span> <span class="p">)</span>
</span><span class='line'>        <span class="p">{</span>
</span><span class='line'>            <span class="c1">// If image is wider than thumbnail (in aspect ratio sense)</span>
</span><span class='line'>            <span class="nv">$new_height</span> <span class="o">=</span> <span class="nv">$height</span><span class="p">;</span>
</span><span class='line'>            <span class="nv">$new_width</span> <span class="o">=</span> <span class="nv">$geo</span><span class="p">[</span><span class="s1">&#39;width&#39;</span><span class="p">]</span> <span class="o">/</span> <span class="p">(</span><span class="nv">$geo</span><span class="p">[</span><span class="s1">&#39;height&#39;</span><span class="p">]</span> <span class="o">/</span> <span class="nv">$height</span><span class="p">);</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>        <span class="k">else</span>
</span><span class='line'>        <span class="p">{</span>
</span><span class='line'>            <span class="c1">// If the thumbnail is wider than the image</span>
</span><span class='line'>            <span class="nv">$new_width</span> <span class="o">=</span> <span class="nv">$width</span><span class="p">;</span>
</span><span class='line'>            <span class="nv">$new_height</span> <span class="o">=</span> <span class="nv">$geo</span><span class="p">[</span><span class="s1">&#39;height&#39;</span><span class="p">]</span> <span class="o">/</span> <span class="p">(</span><span class="nv">$geo</span><span class="p">[</span><span class="s1">&#39;width&#39;</span><span class="p">]</span> <span class="o">/</span> <span class="nv">$width</span><span class="p">);</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="nv">$thumb</span> <span class="o">=</span> <span class="nx">imagecreatetruecolor</span><span class="p">(</span> <span class="nv">$width</span><span class="p">,</span> <span class="nv">$height</span> <span class="p">);</span>
</span><span class='line'>
</span><span class='line'>        <span class="c1">// Resize and crop</span>
</span><span class='line'>        <span class="nx">imagecopyresampled</span><span class="p">(</span><span class="nv">$thumb</span><span class="p">,</span>
</span><span class='line'>            <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span><span class="p">,</span>
</span><span class='line'>            <span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="nv">$new_width</span> <span class="o">-</span> <span class="nv">$width</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">,</span> <span class="c1">// Center the image horizontally</span>
</span><span class='line'>            <span class="mi">0</span> <span class="o">-</span> <span class="p">(</span><span class="nv">$new_height</span> <span class="o">-</span> <span class="nv">$height</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">,</span> <span class="c1">// Center the image vertically</span>
</span><span class='line'>            <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span>
</span><span class='line'>            <span class="nv">$new_width</span><span class="p">,</span> <span class="nv">$new_height</span><span class="p">,</span>
</span><span class='line'>            <span class="nv">$geo</span><span class="p">[</span><span class="s1">&#39;width&#39;</span><span class="p">],</span> <span class="nv">$geo</span><span class="p">[</span><span class="s1">&#39;height&#39;</span><span class="p">]);</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span> <span class="o">=</span> <span class="nv">$thumb</span><span class="p">;</span>
</span><span class='line'>        <span class="k">return</span> <span class="nv">$this</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @param $file</span>
</span><span class='line'><span class="sd">     * @param int $quality</span>
</span><span class='line'><span class="sd">     * @return $this</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">function</span> <span class="nf">save</span><span class="p">(</span><span class="nv">$file</span><span class="p">,</span> <span class="nv">$quality</span> <span class="o">=</span> <span class="mi">90</span><span class="p">){</span>
</span><span class='line'>        <span class="nx">imagejpeg</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span><span class="p">,</span><span class="nv">$file</span><span class="p">,</span> <span class="nb">intval</span><span class="p">(</span><span class="nv">$quality</span><span class="p">));</span>
</span><span class='line'>        <span class="nx">imagedestroy</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span><span class="p">);</span>
</span><span class='line'>        <span class="k">return</span> <span class="nv">$this</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<h5>Classe imageGenerateImagick</h5>

<p>Agora vamos criar nossa classe que usa o Imagemagick para criar os thumbs.</p>

<p><strong><em>imageGenerateImagick.php</em></strong>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="k">include_once</span> <span class="s2">&quot;Image.php&quot;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * Class imageGenerateImagick</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'><span class="k">class</span> <span class="nc">imageGenerateImagick</span> <span class="k">implements</span> <span class="nx">Image</span><span class="p">{</span>
</span><span class='line'>    <span class="k">private</span> <span class="nv">$image</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">__construct</span><span class="p">(){</span>
</span><span class='line'>        <span class="nv">$options</span> <span class="o">=</span> <span class="nb">func_get_args</span><span class="p">();</span>
</span><span class='line'>        <span class="k">if</span><span class="p">(</span><span class="nb">count</span><span class="p">(</span><span class="nv">$options</span><span class="p">)){</span>
</span><span class='line'>            <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Imagick</span><span class="p">(</span><span class="nv">$options</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
</span><span class='line'>        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>            <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Imagick</span><span class="p">();</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @param $file</span>
</span><span class='line'><span class="sd">     * @param $anchor</span>
</span><span class='line'><span class="sd">     * @return imageGenerateImagick</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">function</span> <span class="nf">open</span><span class="p">(</span><span class="nv">$file</span><span class="p">,</span> <span class="nv">$anchor</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span><span class="p">){</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span><span class="o">-&gt;</span><span class="na">readImage</span><span class="p">(</span><span class="nv">$file</span><span class="p">);</span>
</span><span class='line'>        <span class="k">return</span> <span class="nv">$this</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @param int $width</span>
</span><span class='line'><span class="sd">     * @param int $height</span>
</span><span class='line'><span class="sd">     * @return imageGenerateImagick</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">function</span> <span class="nf">resize</span><span class="p">(</span><span class="nv">$width</span> <span class="o">=</span> <span class="mi">160</span><span class="p">,</span> <span class="nv">$height</span> <span class="o">=</span> <span class="mi">90</span><span class="p">){</span>
</span><span class='line'>
</span><span class='line'>        <span class="nv">$geo</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span><span class="o">-&gt;</span><span class="na">getImageGeometry</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>        <span class="c1">// crop the image</span>
</span><span class='line'>        <span class="k">if</span><span class="p">((</span><span class="nv">$geo</span><span class="p">[</span><span class="s1">&#39;width&#39;</span><span class="p">]</span><span class="o">/</span><span class="nv">$width</span><span class="p">)</span> <span class="o">&lt;</span> <span class="p">(</span><span class="nv">$geo</span><span class="p">[</span><span class="s1">&#39;height&#39;</span><span class="p">]</span><span class="o">/</span><span class="nv">$height</span><span class="p">)){</span>
</span><span class='line'>            <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span><span class="o">-&gt;</span><span class="na">cropImage</span><span class="p">(</span><span class="nv">$geo</span><span class="p">[</span><span class="s1">&#39;width&#39;</span><span class="p">],</span> <span class="nx">floor</span><span class="p">(</span><span class="nv">$height</span><span class="o">*</span><span class="nv">$geo</span><span class="p">[</span><span class="s1">&#39;width&#39;</span><span class="p">]</span><span class="o">/</span><span class="nv">$width</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="p">((</span><span class="nv">$geo</span><span class="p">[</span><span class="s1">&#39;height&#39;</span><span class="p">]</span><span class="o">-</span><span class="p">(</span><span class="nv">$height</span><span class="o">*</span><span class="nv">$geo</span><span class="p">[</span><span class="s1">&#39;width&#39;</span><span class="p">]</span><span class="o">/</span><span class="nv">$width</span><span class="p">))</span><span class="o">/</span><span class="mi">2</span><span class="p">));</span>
</span><span class='line'>        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>            <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span><span class="o">-&gt;</span><span class="na">cropImage</span><span class="p">(</span><span class="nb">ceil</span><span class="p">(</span><span class="nv">$width</span><span class="o">*</span><span class="nv">$geo</span><span class="p">[</span><span class="s1">&#39;height&#39;</span><span class="p">]</span><span class="o">/</span><span class="nv">$height</span><span class="p">),</span> <span class="nv">$geo</span><span class="p">[</span><span class="s1">&#39;height&#39;</span><span class="p">],</span> <span class="p">((</span><span class="nv">$geo</span><span class="p">[</span><span class="s1">&#39;width&#39;</span><span class="p">]</span><span class="o">-</span><span class="p">(</span><span class="nv">$width</span><span class="o">*</span><span class="nv">$geo</span><span class="p">[</span><span class="s1">&#39;height&#39;</span><span class="p">]</span><span class="o">/</span><span class="nv">$height</span><span class="p">))</span><span class="o">/</span><span class="mi">2</span><span class="p">),</span> <span class="mi">0</span><span class="p">);</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>        <span class="c1">// thumbnail the image</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span><span class="o">-&gt;</span><span class="na">ThumbnailImage</span><span class="p">(</span><span class="nv">$width</span><span class="p">,</span><span class="nv">$height</span><span class="p">,</span><span class="k">true</span><span class="p">);</span>
</span><span class='line'>        <span class="k">return</span> <span class="nv">$this</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @param $file</span>
</span><span class='line'><span class="sd">     * @param int $quality</span>
</span><span class='line'><span class="sd">     * @return imageGenerateImagick</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">function</span> <span class="nf">save</span><span class="p">(</span><span class="nv">$file</span><span class="p">,</span> <span class="nv">$quality</span> <span class="o">=</span> <span class="mi">80</span><span class="p">){</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span><span class="o">-&gt;</span><span class="na">setImageCompression</span><span class="p">(</span><span class="nx">Imagick</span><span class="o">::</span><span class="na">COMPRESSION_JPEG</span><span class="p">);</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span><span class="o">-&gt;</span><span class="na">setImageCompressionQuality</span><span class="p">(</span><span class="nb">intval</span><span class="p">(</span><span class="nv">$quality</span><span class="p">));</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span><span class="o">-&gt;</span><span class="na">writeImage</span><span class="p">(</span> <span class="nv">$file</span> <span class="p">);</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span><span class="o">-&gt;</span><span class="na">clear</span><span class="p">();</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span><span class="o">-&gt;</span><span class="na">destroy</span><span class="p">();</span>
</span><span class='line'>        <span class="k">return</span> <span class="nv">$this</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<h5>Classe ImageGenerate</h5>

<p>Vamos criar nossa classe que implementa ambas as classes, de GD e imagick, no caso, você irá definir qual recurso ele vai usar, e além disso, ele vai checar se tem e extensão do imagick, de modo que se não houver, o sistema irá utilizar o GD.</p>

<p><strong><em>ImageGenerate.php</em></strong>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="k">include_once</span> <span class="s2">&quot;Image.php&quot;</span><span class="p">;</span>
</span><span class='line'><span class="k">include_once</span> <span class="s2">&quot;ImageGenerateImagick.php&quot;</span><span class="p">;</span>
</span><span class='line'><span class="k">include_once</span> <span class="s2">&quot;imageGenerateGD.php&quot;</span><span class="p">;</span>
</span><span class='line'><span class="k">class</span> <span class="nc">ImageGenerate</span> <span class="k">implements</span> <span class="nx">Image</span> <span class="p">{</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">private</span> <span class="nv">$image</span><span class="p">;</span>
</span><span class='line'>    <span class="k">private</span> <span class="nv">$mode</span><span class="p">;</span>
</span><span class='line'>    <span class="k">const</span> <span class="no">MODE_IMAGICK</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>    <span class="k">const</span> <span class="no">MODE_GD</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">__construct</span><span class="p">(){</span>
</span><span class='line'>        <span class="nv">$options</span> <span class="o">=</span> <span class="nb">func_get_args</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nb">isset</span><span class="p">(</span><span class="nv">$options</span><span class="p">[</span><span class="mi">1</span><span class="p">])){</span>
</span><span class='line'>            <span class="nv">$options</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="nx">self</span><span class="o">::</span><span class="na">MODE_IMAGICK</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">if</span><span class="p">(</span><span class="nv">$options</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="nx">self</span><span class="o">::</span><span class="na">MODE_IMAGICK</span> <span class="o">&amp;&amp;</span> <span class="nb">extension_loaded</span><span class="p">(</span><span class="s1">&#39;imagick&#39;</span><span class="p">)){</span>
</span><span class='line'>            <span class="k">if</span><span class="p">(</span><span class="nb">count</span><span class="p">(</span><span class="nv">$options</span><span class="p">)){</span>
</span><span class='line'>                <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">imageGenerateImagick</span><span class="p">(</span><span class="nv">$options</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
</span><span class='line'>            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>                <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">imageGenerateImagick</span><span class="p">();</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>            <span class="k">if</span><span class="p">(</span><span class="nb">count</span><span class="p">(</span><span class="nv">$options</span><span class="p">)){</span>
</span><span class='line'>                <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">imageGenerateGD</span><span class="p">(</span><span class="nv">$options</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
</span><span class='line'>            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>                <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">imageGenerateGD</span><span class="p">();</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @param mixed $mode</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">setMode</span><span class="p">(</span><span class="nv">$mode</span><span class="p">)</span>
</span><span class='line'>    <span class="p">{</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">mode</span> <span class="o">=</span> <span class="nv">$mode</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @return mixed</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">getMode</span><span class="p">()</span>
</span><span class='line'>    <span class="p">{</span>
</span><span class='line'>        <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">mode</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @param $file</span>
</span><span class='line'><span class="sd">     * @param string $anchor</span>
</span><span class='line'><span class="sd">     * @return imageGenerateGD/imageGenerateImagick</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">function</span> <span class="nf">open</span><span class="p">(</span><span class="nv">$file</span><span class="p">,</span> <span class="nv">$anchor</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span><span class="p">){</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span><span class="o">-&gt;</span><span class="na">open</span><span class="p">(</span><span class="nv">$file</span><span class="p">,</span> <span class="nv">$anchor</span><span class="p">);</span>
</span><span class='line'>        <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @param int $width</span>
</span><span class='line'><span class="sd">     * @param int $height</span>
</span><span class='line'><span class="sd">     * @return imageGenerateGD/imageGenerateImagick</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">function</span> <span class="nf">resize</span><span class="p">(</span><span class="nv">$width</span> <span class="o">=</span> <span class="mi">160</span><span class="p">,</span> <span class="nv">$height</span> <span class="o">=</span> <span class="mi">160</span><span class="p">){</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span><span class="o">-&gt;</span><span class="na">resize</span><span class="p">(</span><span class="mi">160</span><span class="p">,</span><span class="mi">160</span><span class="p">);</span>
</span><span class='line'>        <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @param $file</span>
</span><span class='line'><span class="sd">     * @param int $quality</span>
</span><span class='line'><span class="sd">     * @return imageGenerateGD/imageGenerateImagick</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">function</span> <span class="nf">save</span><span class="p">(</span><span class="nv">$file</span><span class="p">,</span> <span class="nv">$quality</span> <span class="o">=</span> <span class="mi">80</span><span class="p">){</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span><span class="o">-&gt;</span><span class="na">save</span><span class="p">(</span><span class="nv">$file</span><span class="p">,</span><span class="nv">$quality</span><span class="p">);</span>
</span><span class='line'>        <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">image</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Criando o serviço de crop</h3>

<p>Agora que já temos nossas classes de imagem, vamos criar um serviço ou melhor, uma API, que ao receber como parâmetro o nome e caminho da imagem de origem, ela se encarrega de gerar o thumb usando nossa classe.</p>

<p><strong><em>resize.php</em></strong>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="nx">header</span><span class="p">(</span><span class="s1">&#39;Content-Type: application/json&#39;</span><span class="p">);</span>
</span><span class='line'><span class="k">if</span><span class="p">(</span><span class="nv">$_REQUEST</span><span class="p">[</span><span class="s1">&#39;file&#39;</span><span class="p">]){</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">include_once</span> <span class="s2">&quot;../class/ImageGenerate.php&quot;</span><span class="p">;</span>
</span><span class='line'>    <span class="k">if</span><span class="p">(</span><span class="nb">file_exists</span><span class="p">(</span><span class="nv">$_REQUEST</span><span class="p">[</span><span class="s1">&#39;file&#39;</span><span class="p">])){</span>
</span><span class='line'>        <span class="nv">$teste</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">imageGenerate</span><span class="p">(</span><span class="nv">$_REQUEST</span><span class="p">[</span><span class="s1">&#39;file&#39;</span><span class="p">]);</span>
</span><span class='line'>        <span class="nv">$width</span> <span class="o">=</span> <span class="p">(</span><span class="nb">isset</span><span class="p">(</span><span class="nv">$_REQUEST</span><span class="p">[</span><span class="s1">&#39;width&#39;</span><span class="p">]))</span><span class="o">?</span> <span class="nv">$_REQUEST</span><span class="p">[</span><span class="s1">&#39;width&#39;</span><span class="p">]</span> <span class="o">:</span> <span class="mi">160</span><span class="p">;</span>
</span><span class='line'>        <span class="nv">$height</span> <span class="o">=</span> <span class="p">(</span><span class="nb">isset</span><span class="p">(</span><span class="nv">$_REQUEST</span><span class="p">[</span><span class="s1">&#39;height&#39;</span><span class="p">]))</span><span class="o">?</span> <span class="nv">$_REQUEST</span><span class="p">[</span><span class="s1">&#39;height&#39;</span><span class="p">]</span> <span class="o">:</span> <span class="mi">160</span><span class="p">;</span>
</span><span class='line'>        <span class="nv">$teste</span><span class="o">-&gt;</span><span class="na">resize</span><span class="p">(</span><span class="nv">$width</span><span class="p">,</span><span class="nv">$height</span><span class="p">)</span>
</span><span class='line'>              <span class="o">-&gt;</span><span class="na">save</span><span class="p">(</span><span class="s1">&#39;../image/destination/&#39;</span><span class="o">.</span><span class="nb">end</span><span class="p">(</span><span class="nb">explode</span><span class="p">(</span><span class="s2">&quot;/&quot;</span><span class="p">,</span> <span class="nv">$_REQUEST</span><span class="p">[</span><span class="s1">&#39;file&#39;</span><span class="p">])));</span>
</span><span class='line'>        <span class="k">echo</span> <span class="nb">json_encode</span><span class="p">(</span><span class="k">array</span><span class="p">(</span>
</span><span class='line'>            <span class="s1">&#39;status&#39;</span>    <span class="o">=&gt;</span>  <span class="s1">&#39;OK&#39;</span><span class="p">,</span>
</span><span class='line'>            <span class="s1">&#39;msg&#39;</span>       <span class="o">=&gt;</span>   <span class="nx">utf8_encode</span><span class="p">(</span><span class="s1">&#39;Image save on &#39;</span><span class="o">.</span><span class="s1">&#39;image/destination/&#39;</span><span class="o">.</span><span class="nb">end</span><span class="p">(</span><span class="nb">explode</span><span class="p">(</span><span class="s2">&quot;/&quot;</span><span class="p">,</span> <span class="nv">$_REQUEST</span><span class="p">[</span><span class="s1">&#39;file&#39;</span><span class="p">])))</span>
</span><span class='line'>        <span class="p">),</span> <span class="k">true</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">echo</span> <span class="nb">json_encode</span><span class="p">(</span><span class="k">array</span><span class="p">(</span>
</span><span class='line'>            <span class="s1">&#39;status&#39;</span>    <span class="o">=&gt;</span>  <span class="s1">&#39;ERROR&#39;</span><span class="p">,</span>
</span><span class='line'>            <span class="s1">&#39;msg&#39;</span>       <span class="o">=&gt;</span>  <span class="nx">utf8_encode</span><span class="p">(</span><span class="s1">&#39;picture does not exist&#39;</span><span class="p">)</span>
</span><span class='line'>        <span class="p">),</span> <span class="k">true</span><span class="p">);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'><span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">echo</span> <span class="nb">json_encode</span><span class="p">(</span><span class="k">array</span><span class="p">(</span>
</span><span class='line'>        <span class="s1">&#39;status&#39;</span>    <span class="o">=&gt;</span>  <span class="s1">&#39;ERROR&#39;</span><span class="p">,</span>
</span><span class='line'>        <span class="s1">&#39;msg&#39;</span>       <span class="o">=&gt;</span>  <span class="nx">utf8_encode</span><span class="p">(</span><span class="s1">&#39;not sent parameter&#39;</span><span class="p">)</span>
</span><span class='line'>    <span class="p">),</span> <span class="k">true</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Processando nossas imagens em paralelo</h3>

<p>Agora que criamos nossas classes de imagens, e a API que gera as imagens, vamos criar uma página que utiliza um recurso do <strong>cURL</strong>, que é o <strong>curl_multi_exec</strong>, ele permite múltiplas requisições simultâneas a nossa API. No nosso caso, utilizamos uma Classe chamada <strong><a href="https://github.com/takinbo/rolling-curl">RollingCurl</a></strong>, ela permite fazer essas chamadas paralelas, permitindo fazer os processos em lotes definidos, por exemplo, executar lotes de 5 em 5 imagens, após completar um lote, ele chama outro, até o fim do processamento. Fizemos apenas uma alteração, que foi criar um método que armazena todas as respostas em um array.</p>

<blockquote><p><strong>Cuidado</strong>
Requisições paralelas são recursos que devem ser usados com consciência, pois você irá forçar o seu servidor a processar <strong>N</strong> vezes em paralelo um determinado recurso, e se considerarmos que podemos ter <strong>X</strong> pessoas usando esse serviço ao mesmo tempo, podemos até derrubar nosso servidor (Não queremos fazer um auto ataque <strong>DDos</strong>).</p></blockquote>

<p><strong><em>RollingCurl.php</em></strong>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
<span class='line-number'>80</span>
<span class='line-number'>81</span>
<span class='line-number'>82</span>
<span class='line-number'>83</span>
<span class='line-number'>84</span>
<span class='line-number'>85</span>
<span class='line-number'>86</span>
<span class='line-number'>87</span>
<span class='line-number'>88</span>
<span class='line-number'>89</span>
<span class='line-number'>90</span>
<span class='line-number'>91</span>
<span class='line-number'>92</span>
<span class='line-number'>93</span>
<span class='line-number'>94</span>
<span class='line-number'>95</span>
<span class='line-number'>96</span>
<span class='line-number'>97</span>
<span class='line-number'>98</span>
<span class='line-number'>99</span>
<span class='line-number'>100</span>
<span class='line-number'>101</span>
<span class='line-number'>102</span>
<span class='line-number'>103</span>
<span class='line-number'>104</span>
<span class='line-number'>105</span>
<span class='line-number'>106</span>
<span class='line-number'>107</span>
<span class='line-number'>108</span>
<span class='line-number'>109</span>
<span class='line-number'>110</span>
<span class='line-number'>111</span>
<span class='line-number'>112</span>
<span class='line-number'>113</span>
<span class='line-number'>114</span>
<span class='line-number'>115</span>
<span class='line-number'>116</span>
<span class='line-number'>117</span>
<span class='line-number'>118</span>
<span class='line-number'>119</span>
<span class='line-number'>120</span>
<span class='line-number'>121</span>
<span class='line-number'>122</span>
<span class='line-number'>123</span>
<span class='line-number'>124</span>
<span class='line-number'>125</span>
<span class='line-number'>126</span>
<span class='line-number'>127</span>
<span class='line-number'>128</span>
<span class='line-number'>129</span>
<span class='line-number'>130</span>
<span class='line-number'>131</span>
<span class='line-number'>132</span>
<span class='line-number'>133</span>
<span class='line-number'>134</span>
<span class='line-number'>135</span>
<span class='line-number'>136</span>
<span class='line-number'>137</span>
<span class='line-number'>138</span>
<span class='line-number'>139</span>
<span class='line-number'>140</span>
<span class='line-number'>141</span>
<span class='line-number'>142</span>
<span class='line-number'>143</span>
<span class='line-number'>144</span>
<span class='line-number'>145</span>
<span class='line-number'>146</span>
<span class='line-number'>147</span>
<span class='line-number'>148</span>
<span class='line-number'>149</span>
<span class='line-number'>150</span>
<span class='line-number'>151</span>
<span class='line-number'>152</span>
<span class='line-number'>153</span>
<span class='line-number'>154</span>
<span class='line-number'>155</span>
<span class='line-number'>156</span>
<span class='line-number'>157</span>
<span class='line-number'>158</span>
<span class='line-number'>159</span>
<span class='line-number'>160</span>
<span class='line-number'>161</span>
<span class='line-number'>162</span>
<span class='line-number'>163</span>
<span class='line-number'>164</span>
<span class='line-number'>165</span>
<span class='line-number'>166</span>
<span class='line-number'>167</span>
<span class='line-number'>168</span>
<span class='line-number'>169</span>
<span class='line-number'>170</span>
<span class='line-number'>171</span>
<span class='line-number'>172</span>
<span class='line-number'>173</span>
<span class='line-number'>174</span>
<span class='line-number'>175</span>
<span class='line-number'>176</span>
<span class='line-number'>177</span>
<span class='line-number'>178</span>
<span class='line-number'>179</span>
<span class='line-number'>180</span>
<span class='line-number'>181</span>
<span class='line-number'>182</span>
<span class='line-number'>183</span>
<span class='line-number'>184</span>
<span class='line-number'>185</span>
<span class='line-number'>186</span>
<span class='line-number'>187</span>
<span class='line-number'>188</span>
<span class='line-number'>189</span>
<span class='line-number'>190</span>
<span class='line-number'>191</span>
<span class='line-number'>192</span>
<span class='line-number'>193</span>
<span class='line-number'>194</span>
<span class='line-number'>195</span>
<span class='line-number'>196</span>
<span class='line-number'>197</span>
<span class='line-number'>198</span>
<span class='line-number'>199</span>
<span class='line-number'>200</span>
<span class='line-number'>201</span>
<span class='line-number'>202</span>
<span class='line-number'>203</span>
<span class='line-number'>204</span>
<span class='line-number'>205</span>
<span class='line-number'>206</span>
<span class='line-number'>207</span>
<span class='line-number'>208</span>
<span class='line-number'>209</span>
<span class='line-number'>210</span>
<span class='line-number'>211</span>
<span class='line-number'>212</span>
<span class='line-number'>213</span>
<span class='line-number'>214</span>
<span class='line-number'>215</span>
<span class='line-number'>216</span>
<span class='line-number'>217</span>
<span class='line-number'>218</span>
<span class='line-number'>219</span>
<span class='line-number'>220</span>
<span class='line-number'>221</span>
<span class='line-number'>222</span>
<span class='line-number'>223</span>
<span class='line-number'>224</span>
<span class='line-number'>225</span>
<span class='line-number'>226</span>
<span class='line-number'>227</span>
<span class='line-number'>228</span>
<span class='line-number'>229</span>
<span class='line-number'>230</span>
<span class='line-number'>231</span>
<span class='line-number'>232</span>
<span class='line-number'>233</span>
<span class='line-number'>234</span>
<span class='line-number'>235</span>
<span class='line-number'>236</span>
<span class='line-number'>237</span>
<span class='line-number'>238</span>
<span class='line-number'>239</span>
<span class='line-number'>240</span>
<span class='line-number'>241</span>
<span class='line-number'>242</span>
<span class='line-number'>243</span>
<span class='line-number'>244</span>
<span class='line-number'>245</span>
<span class='line-number'>246</span>
<span class='line-number'>247</span>
<span class='line-number'>248</span>
<span class='line-number'>249</span>
<span class='line-number'>250</span>
<span class='line-number'>251</span>
<span class='line-number'>252</span>
<span class='line-number'>253</span>
<span class='line-number'>254</span>
<span class='line-number'>255</span>
<span class='line-number'>256</span>
<span class='line-number'>257</span>
<span class='line-number'>258</span>
<span class='line-number'>259</span>
<span class='line-number'>260</span>
<span class='line-number'>261</span>
<span class='line-number'>262</span>
<span class='line-number'>263</span>
<span class='line-number'>264</span>
<span class='line-number'>265</span>
<span class='line-number'>266</span>
<span class='line-number'>267</span>
<span class='line-number'>268</span>
<span class='line-number'>269</span>
<span class='line-number'>270</span>
<span class='line-number'>271</span>
<span class='line-number'>272</span>
<span class='line-number'>273</span>
<span class='line-number'>274</span>
<span class='line-number'>275</span>
<span class='line-number'>276</span>
<span class='line-number'>277</span>
<span class='line-number'>278</span>
<span class='line-number'>279</span>
<span class='line-number'>280</span>
<span class='line-number'>281</span>
<span class='line-number'>282</span>
<span class='line-number'>283</span>
<span class='line-number'>284</span>
<span class='line-number'>285</span>
<span class='line-number'>286</span>
<span class='line-number'>287</span>
<span class='line-number'>288</span>
<span class='line-number'>289</span>
<span class='line-number'>290</span>
<span class='line-number'>291</span>
<span class='line-number'>292</span>
<span class='line-number'>293</span>
<span class='line-number'>294</span>
<span class='line-number'>295</span>
<span class='line-number'>296</span>
<span class='line-number'>297</span>
<span class='line-number'>298</span>
<span class='line-number'>299</span>
<span class='line-number'>300</span>
<span class='line-number'>301</span>
<span class='line-number'>302</span>
<span class='line-number'>303</span>
<span class='line-number'>304</span>
<span class='line-number'>305</span>
<span class='line-number'>306</span>
<span class='line-number'>307</span>
<span class='line-number'>308</span>
<span class='line-number'>309</span>
<span class='line-number'>310</span>
<span class='line-number'>311</span>
<span class='line-number'>312</span>
<span class='line-number'>313</span>
<span class='line-number'>314</span>
<span class='line-number'>315</span>
<span class='line-number'>316</span>
<span class='line-number'>317</span>
<span class='line-number'>318</span>
<span class='line-number'>319</span>
<span class='line-number'>320</span>
<span class='line-number'>321</span>
<span class='line-number'>322</span>
<span class='line-number'>323</span>
<span class='line-number'>324</span>
<span class='line-number'>325</span>
<span class='line-number'>326</span>
<span class='line-number'>327</span>
<span class='line-number'>328</span>
<span class='line-number'>329</span>
<span class='line-number'>330</span>
<span class='line-number'>331</span>
<span class='line-number'>332</span>
<span class='line-number'>333</span>
<span class='line-number'>334</span>
<span class='line-number'>335</span>
<span class='line-number'>336</span>
<span class='line-number'>337</span>
<span class='line-number'>338</span>
<span class='line-number'>339</span>
<span class='line-number'>340</span>
<span class='line-number'>341</span>
<span class='line-number'>342</span>
<span class='line-number'>343</span>
<span class='line-number'>344</span>
<span class='line-number'>345</span>
<span class='line-number'>346</span>
<span class='line-number'>347</span>
<span class='line-number'>348</span>
<span class='line-number'>349</span>
<span class='line-number'>350</span>
<span class='line-number'>351</span>
<span class='line-number'>352</span>
<span class='line-number'>353</span>
<span class='line-number'>354</span>
<span class='line-number'>355</span>
<span class='line-number'>356</span>
<span class='line-number'>357</span>
<span class='line-number'>358</span>
<span class='line-number'>359</span>
<span class='line-number'>360</span>
<span class='line-number'>361</span>
<span class='line-number'>362</span>
<span class='line-number'>363</span>
<span class='line-number'>364</span>
<span class='line-number'>365</span>
<span class='line-number'>366</span>
<span class='line-number'>367</span>
<span class='line-number'>368</span>
<span class='line-number'>369</span>
<span class='line-number'>370</span>
<span class='line-number'>371</span>
<span class='line-number'>372</span>
<span class='line-number'>373</span>
<span class='line-number'>374</span>
<span class='line-number'>375</span>
<span class='line-number'>376</span>
<span class='line-number'>377</span>
<span class='line-number'>378</span>
<span class='line-number'>379</span>
<span class='line-number'>380</span>
<span class='line-number'>381</span>
<span class='line-number'>382</span>
<span class='line-number'>383</span>
<span class='line-number'>384</span>
<span class='line-number'>385</span>
<span class='line-number'>386</span>
<span class='line-number'>387</span>
<span class='line-number'>388</span>
<span class='line-number'>389</span>
<span class='line-number'>390</span>
<span class='line-number'>391</span>
<span class='line-number'>392</span>
<span class='line-number'>393</span>
<span class='line-number'>394</span>
<span class='line-number'>395</span>
<span class='line-number'>396</span>
<span class='line-number'>397</span>
<span class='line-number'>398</span>
<span class='line-number'>399</span>
<span class='line-number'>400</span>
<span class='line-number'>401</span>
<span class='line-number'>402</span>
<span class='line-number'>403</span>
<span class='line-number'>404</span>
<span class='line-number'>405</span>
<span class='line-number'>406</span>
<span class='line-number'>407</span>
<span class='line-number'>408</span>
<span class='line-number'>409</span>
<span class='line-number'>410</span>
<span class='line-number'>411</span>
<span class='line-number'>412</span>
<span class='line-number'>413</span>
<span class='line-number'>414</span>
<span class='line-number'>415</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="cm">/*</span>
</span><span class='line'><span class="cm">Authored by Josh Fraser (www.joshfraser.com)</span>
</span><span class='line'><span class="cm">Released under Apache License 2.0</span>
</span><span class='line'>
</span><span class='line'><span class="cm">Maintained by Alexander Makarov, http://rmcreative.ru/</span>
</span><span class='line'>
</span><span class='line'><span class="cm">$Id$</span>
</span><span class='line'><span class="cm">*/</span>
</span><span class='line'>
</span><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * Class that represent a single curl request</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'><span class="k">class</span> <span class="nc">RollingCurlRequest</span> <span class="p">{</span>
</span><span class='line'>  <span class="k">public</span> <span class="nv">$url</span> <span class="o">=</span> <span class="k">false</span><span class="p">;</span>
</span><span class='line'>  <span class="k">public</span> <span class="nv">$method</span> <span class="o">=</span> <span class="s1">&#39;GET&#39;</span><span class="p">;</span>
</span><span class='line'>  <span class="k">public</span> <span class="nv">$post_data</span> <span class="o">=</span> <span class="k">null</span><span class="p">;</span>
</span><span class='line'>  <span class="k">public</span> <span class="nv">$headers</span> <span class="o">=</span> <span class="k">null</span><span class="p">;</span>
</span><span class='line'>  <span class="k">public</span> <span class="nv">$options</span> <span class="o">=</span> <span class="k">null</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @param string $url</span>
</span><span class='line'><span class="sd">     * @param string $method</span>
</span><span class='line'><span class="sd">     * @param  $post_data</span>
</span><span class='line'><span class="sd">     * @param  $headers</span>
</span><span class='line'><span class="sd">     * @param  $options</span>
</span><span class='line'><span class="sd">     * @return void</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">function</span> <span class="nf">__construct</span><span class="p">(</span><span class="nv">$url</span><span class="p">,</span> <span class="nv">$method</span> <span class="o">=</span> <span class="s2">&quot;GET&quot;</span><span class="p">,</span> <span class="nv">$post_data</span> <span class="o">=</span> <span class="k">null</span><span class="p">,</span> <span class="nv">$headers</span> <span class="o">=</span> <span class="k">null</span><span class="p">,</span> <span class="nv">$options</span> <span class="o">=</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">url</span> <span class="o">=</span> <span class="nv">$url</span><span class="p">;</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">method</span> <span class="o">=</span> <span class="nv">$method</span><span class="p">;</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">post_data</span> <span class="o">=</span> <span class="nv">$post_data</span><span class="p">;</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">headers</span> <span class="o">=</span> <span class="nv">$headers</span><span class="p">;</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">options</span> <span class="o">=</span> <span class="nv">$options</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @return void</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">__destruct</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>        <span class="nb">unset</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">url</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">method</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">post_data</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">headers</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">options</span><span class="p">);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * RollingCurl custom exception</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'><span class="k">class</span> <span class="nc">RollingCurlException</span> <span class="k">extends</span> <span class="nx">Exception</span> <span class="p">{}</span>
</span><span class='line'>
</span><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * Class that holds a rolling queue of curl requests.</span>
</span><span class='line'><span class="sd"> *</span>
</span><span class='line'><span class="sd"> * @throws RollingCurlException</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'><span class="k">class</span> <span class="nc">RollingCurl</span> <span class="p">{</span>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @var int</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * Window size is the max number of simultaneous connections allowed.</span>
</span><span class='line'><span class="sd">  * </span>
</span><span class='line'><span class="sd">     * REMEMBER TO RESPECT THE SERVERS:</span>
</span><span class='line'><span class="sd">     * Sending too many requests at one time can easily be perceived</span>
</span><span class='line'><span class="sd">     * as a DOS attack. Increase this window_size if you are making requests</span>
</span><span class='line'><span class="sd">     * to multiple servers or have permission from the receving server admins.</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">private</span> <span class="nv">$window_size</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @var float</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * Timeout is the timeout used for curl_multi_select.</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">private</span> <span class="nv">$timeout</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @var string|array</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * Callback function to be applied to each result.</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">private</span> <span class="nv">$callback</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @var array</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * Set your base options that you want to be used with EVERY request.</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">protected</span> <span class="nv">$options</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span>
</span><span class='line'>      <span class="nx">CURLOPT_SSL_VERIFYPEER</span> <span class="o">=&gt;</span> <span class="mi">0</span><span class="p">,</span>
</span><span class='line'>        <span class="nx">CURLOPT_RETURNTRANSFER</span> <span class="o">=&gt;</span> <span class="mi">1</span><span class="p">,</span>
</span><span class='line'>        <span class="nx">CURLOPT_CONNECTTIMEOUT</span> <span class="o">=&gt;</span> <span class="mi">30</span><span class="p">,</span>
</span><span class='line'>        <span class="nx">CURLOPT_TIMEOUT</span> <span class="o">=&gt;</span> <span class="mi">30</span>
</span><span class='line'>  <span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @var array</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">private</span> <span class="nv">$headers</span> <span class="o">=</span> <span class="k">array</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @var Request[]</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * The request queue</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">private</span> <span class="nv">$requests</span> <span class="o">=</span> <span class="k">array</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @var RequestMap[]</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * Maps handles to request indexes</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">private</span> <span class="nv">$requestMap</span> <span class="o">=</span> <span class="k">array</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @var returns[]</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * All returns of requests</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">private</span> <span class="nv">$returns</span> <span class="o">=</span> <span class="k">array</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @param  $callback</span>
</span><span class='line'><span class="sd">     * Callback function to be applied to each result.</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * Can be specified as &#39;my_callback_function&#39;</span>
</span><span class='line'><span class="sd">     * or array($object, &#39;my_callback_method&#39;).</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * Function should take three parameters: $response, $info, $request.</span>
</span><span class='line'><span class="sd">     * $response is response body, $info is additional curl info.</span>
</span><span class='line'><span class="sd">     * $request is the original request</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * @return void</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>  <span class="k">function</span> <span class="nf">__construct</span><span class="p">(</span><span class="nv">$callback</span> <span class="o">=</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">callback</span> <span class="o">=</span> <span class="nv">$callback</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @param string $name</span>
</span><span class='line'><span class="sd">     * @return mixed</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">__get</span><span class="p">(</span><span class="nv">$name</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">return</span> <span class="p">(</span><span class="nb">isset</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="p">{</span><span class="nv">$name</span><span class="p">}))</span> <span class="o">?</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="p">{</span><span class="nv">$name</span><span class="p">}</span> <span class="o">:</span> <span class="k">null</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @param string $name</span>
</span><span class='line'><span class="sd">     * @param mixed $value</span>
</span><span class='line'><span class="sd">     * @return bool</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">__set</span><span class="p">(</span><span class="nv">$name</span><span class="p">,</span> <span class="nv">$value</span><span class="p">){</span>
</span><span class='line'>        <span class="c1">// append the base options &amp; headers</span>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="nv">$name</span> <span class="o">==</span> <span class="s2">&quot;options&quot;</span> <span class="o">||</span> <span class="nv">$name</span> <span class="o">==</span> <span class="s2">&quot;headers&quot;</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="nv">$this</span><span class="o">-&gt;</span><span class="p">{</span><span class="nv">$name</span><span class="p">}</span> <span class="o">=</span> <span class="nv">$value</span> <span class="o">+</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="p">{</span><span class="nv">$name</span><span class="p">};</span>
</span><span class='line'>        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>            <span class="nv">$this</span><span class="o">-&gt;</span><span class="p">{</span><span class="nv">$name</span><span class="p">}</span> <span class="o">=</span> <span class="nv">$value</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>        <span class="k">return</span> <span class="k">true</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * Add a request to the request queue</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * @param Request $request</span>
</span><span class='line'><span class="sd">     * @return bool</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">add</span><span class="p">(</span><span class="nv">$request</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>         <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">[]</span> <span class="o">=</span> <span class="nv">$request</span><span class="p">;</span>
</span><span class='line'>         <span class="k">return</span> <span class="k">true</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @param \returns[] $returns</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">setReturns</span><span class="p">(</span><span class="nv">$returns</span><span class="p">)</span>
</span><span class='line'>    <span class="p">{</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">returns</span> <span class="o">=</span> <span class="nv">$returns</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @return \returns[]</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">getReturns</span><span class="p">()</span>
</span><span class='line'>    <span class="p">{</span>
</span><span class='line'>        <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">returns</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * Create new Request and add it to the request queue</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * @param string $url</span>
</span><span class='line'><span class="sd">     * @param string $method</span>
</span><span class='line'><span class="sd">     * @param  $post_data</span>
</span><span class='line'><span class="sd">     * @param  $headers</span>
</span><span class='line'><span class="sd">     * @param  $options</span>
</span><span class='line'><span class="sd">     * @return bool</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">request</span><span class="p">(</span><span class="nv">$url</span><span class="p">,</span> <span class="nv">$method</span> <span class="o">=</span> <span class="s2">&quot;GET&quot;</span><span class="p">,</span> <span class="nv">$post_data</span> <span class="o">=</span> <span class="k">null</span><span class="p">,</span> <span class="nv">$headers</span> <span class="o">=</span> <span class="k">null</span><span class="p">,</span> <span class="nv">$options</span> <span class="o">=</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>         <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">[]</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">RollingCurlRequest</span><span class="p">(</span><span class="nv">$url</span><span class="p">,</span> <span class="nv">$method</span><span class="p">,</span> <span class="nv">$post_data</span><span class="p">,</span> <span class="nv">$headers</span><span class="p">,</span> <span class="nv">$options</span><span class="p">);</span>
</span><span class='line'>         <span class="k">return</span> <span class="k">true</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * Perform GET request</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * @param string $url</span>
</span><span class='line'><span class="sd">     * @param  $headers</span>
</span><span class='line'><span class="sd">     * @param  $options</span>
</span><span class='line'><span class="sd">     * @return bool</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">get</span><span class="p">(</span><span class="nv">$url</span><span class="p">,</span> <span class="nv">$headers</span> <span class="o">=</span> <span class="k">null</span><span class="p">,</span> <span class="nv">$options</span> <span class="o">=</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">request</span><span class="p">(</span><span class="nv">$url</span><span class="p">,</span> <span class="s2">&quot;GET&quot;</span><span class="p">,</span> <span class="k">null</span><span class="p">,</span> <span class="nv">$headers</span><span class="p">,</span> <span class="nv">$options</span><span class="p">);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * Perform POST request</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * @param string $url</span>
</span><span class='line'><span class="sd">     * @param  $post_data</span>
</span><span class='line'><span class="sd">     * @param  $headers</span>
</span><span class='line'><span class="sd">     * @param  $options</span>
</span><span class='line'><span class="sd">     * @return bool</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">post</span><span class="p">(</span><span class="nv">$url</span><span class="p">,</span> <span class="nv">$post_data</span> <span class="o">=</span> <span class="k">null</span><span class="p">,</span> <span class="nv">$headers</span> <span class="o">=</span> <span class="k">null</span><span class="p">,</span> <span class="nv">$options</span> <span class="o">=</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">request</span><span class="p">(</span><span class="nv">$url</span><span class="p">,</span> <span class="s2">&quot;POST&quot;</span><span class="p">,</span> <span class="nv">$post_data</span><span class="p">,</span> <span class="nv">$headers</span><span class="p">,</span> <span class="nv">$options</span><span class="p">);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * Execute the curl</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * @param int $window_size Max number of simultaneous connections</span>
</span><span class='line'><span class="sd">     * @return string|bool</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">execute</span><span class="p">(</span><span class="nv">$window_size</span> <span class="o">=</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="c1">// rolling curl window must always be greater than 1</span>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="nb">sizeof</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">single_curl</span><span class="p">();</span>
</span><span class='line'>        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>            <span class="c1">// start the rolling curl. window_size is the max number of simultaneous connections</span>
</span><span class='line'>            <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">rolling_curl</span><span class="p">(</span><span class="nv">$window_size</span><span class="p">);</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * Performs a single curl request</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * @access private</span>
</span><span class='line'><span class="sd">     * @return string</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">private</span> <span class="k">function</span> <span class="nf">single_curl</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>        <span class="nv">$ch</span> <span class="o">=</span> <span class="nb">curl_init</span><span class="p">();</span>
</span><span class='line'>        <span class="nv">$request</span> <span class="o">=</span> <span class="nb">array_shift</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">);</span>
</span><span class='line'>        <span class="nv">$options</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">get_options</span><span class="p">(</span><span class="nv">$request</span><span class="p">);</span>
</span><span class='line'>        <span class="nb">curl_setopt_array</span><span class="p">(</span><span class="nv">$ch</span><span class="p">,</span><span class="nv">$options</span><span class="p">);</span>
</span><span class='line'>        <span class="nv">$output</span> <span class="o">=</span> <span class="nb">curl_exec</span><span class="p">(</span><span class="nv">$ch</span><span class="p">);</span>
</span><span class='line'>        <span class="nv">$info</span> <span class="o">=</span> <span class="nb">curl_getinfo</span><span class="p">(</span><span class="nv">$ch</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>        <span class="c1">// it&#39;s not neccesary to set a callback for one-off requests</span>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">callback</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="nv">$callback</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">callback</span><span class="p">;</span>
</span><span class='line'>            <span class="k">if</span> <span class="p">(</span><span class="nb">is_callable</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">callback</span><span class="p">)){</span>
</span><span class='line'>                <span class="nb">call_user_func</span><span class="p">(</span><span class="nv">$callback</span><span class="p">,</span> <span class="nv">$output</span><span class="p">,</span> <span class="nv">$info</span><span class="p">,</span> <span class="nv">$request</span><span class="p">);</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>      <span class="k">else</span>
</span><span class='line'>            <span class="k">return</span> <span class="nv">$output</span><span class="p">;</span>
</span><span class='line'>  <span class="k">return</span> <span class="k">true</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * Performs multiple curl requests</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * @access private</span>
</span><span class='line'><span class="sd">     * @throws RollingCurlException</span>
</span><span class='line'><span class="sd">     * @param int $window_size Max number of simultaneous connections</span>
</span><span class='line'><span class="sd">     * @return bool</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">private</span> <span class="k">function</span> <span class="nf">rolling_curl</span><span class="p">(</span><span class="nv">$window_size</span> <span class="o">=</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="nv">$window_size</span><span class="p">)</span>
</span><span class='line'>            <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">window_size</span> <span class="o">=</span> <span class="nv">$window_size</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>        <span class="c1">// make sure the rolling window isn&#39;t greater than the # of urls</span>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="nb">sizeof</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">)</span> <span class="o">&lt;</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">window_size</span><span class="p">)</span>
</span><span class='line'>            <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">window_size</span> <span class="o">=</span> <span class="nb">sizeof</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">window_size</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="k">throw</span> <span class="k">new</span> <span class="nx">RollingCurlException</span><span class="p">(</span><span class="s2">&quot;Window size must be greater than 1&quot;</span><span class="p">);</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="nv">$master</span> <span class="o">=</span> <span class="nb">curl_multi_init</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>        <span class="c1">// start the first batch of requests</span>
</span><span class='line'>        <span class="k">for</span> <span class="p">(</span><span class="nv">$i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nv">$i</span> <span class="o">&lt;</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">window_size</span><span class="p">;</span> <span class="nv">$i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="nv">$ch</span> <span class="o">=</span> <span class="nb">curl_init</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>            <span class="nv">$options</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">get_options</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">[</span><span class="nv">$i</span><span class="p">]);</span>
</span><span class='line'>
</span><span class='line'>            <span class="nb">curl_setopt_array</span><span class="p">(</span><span class="nv">$ch</span><span class="p">,</span><span class="nv">$options</span><span class="p">);</span>
</span><span class='line'>            <span class="nb">curl_multi_add_handle</span><span class="p">(</span><span class="nv">$master</span><span class="p">,</span> <span class="nv">$ch</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>            <span class="c1">// Add to our request Maps</span>
</span><span class='line'>            <span class="nv">$key</span> <span class="o">=</span> <span class="p">(</span><span class="nx">string</span><span class="p">)</span> <span class="nv">$ch</span><span class="p">;</span>
</span><span class='line'>            <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requestMap</span><span class="p">[</span><span class="nv">$key</span><span class="p">]</span> <span class="o">=</span> <span class="nv">$i</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">do</span> <span class="p">{</span>
</span><span class='line'>            <span class="k">while</span><span class="p">((</span><span class="nv">$execrun</span> <span class="o">=</span> <span class="nb">curl_multi_exec</span><span class="p">(</span><span class="nv">$master</span><span class="p">,</span> <span class="nv">$running</span><span class="p">))</span> <span class="o">==</span> <span class="nx">CURLM_CALL_MULTI_PERFORM</span><span class="p">);</span>
</span><span class='line'>            <span class="k">if</span><span class="p">(</span><span class="nv">$execrun</span> <span class="o">!=</span> <span class="nx">CURLM_OK</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>                <span class="k">break</span><span class="p">;</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="c1">// a request was just completed -- find out which one</span>
</span><span class='line'>            <span class="k">while</span><span class="p">(</span><span class="nv">$done</span> <span class="o">=</span> <span class="nb">curl_multi_info_read</span><span class="p">(</span><span class="nv">$master</span><span class="p">))</span> <span class="p">{</span>
</span><span class='line'>
</span><span class='line'>                <span class="c1">// get the info and content returned on the request</span>
</span><span class='line'>                <span class="nv">$info</span> <span class="o">=</span> <span class="nb">curl_getinfo</span><span class="p">(</span><span class="nv">$done</span><span class="p">[</span><span class="s1">&#39;handle&#39;</span><span class="p">]);</span>
</span><span class='line'>                <span class="nv">$output</span> <span class="o">=</span> <span class="nb">curl_multi_getcontent</span><span class="p">(</span><span class="nv">$done</span><span class="p">[</span><span class="s1">&#39;handle&#39;</span><span class="p">]);</span>
</span><span class='line'>
</span><span class='line'>                <span class="nb">array_push</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">returns</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span>
</span><span class='line'>                    <span class="s1">&#39;return&#39;</span>    <span class="o">=&gt;</span>  <span class="nv">$output</span><span class="p">,</span>
</span><span class='line'>                    <span class="s1">&#39;info&#39;</span>      <span class="o">=&gt;</span>  <span class="nv">$info</span><span class="p">,</span>
</span><span class='line'>                <span class="p">));</span>
</span><span class='line'>
</span><span class='line'>                <span class="c1">// send the return values to the callback function.</span>
</span><span class='line'>                <span class="nv">$callback</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">callback</span><span class="p">;</span>
</span><span class='line'>                <span class="k">if</span> <span class="p">(</span><span class="nb">is_callable</span><span class="p">(</span><span class="nv">$callback</span><span class="p">)){</span>
</span><span class='line'>              <span class="nv">$key</span> <span class="o">=</span> <span class="p">(</span><span class="nx">string</span><span class="p">)</span><span class="nv">$done</span><span class="p">[</span><span class="s1">&#39;handle&#39;</span><span class="p">];</span>
</span><span class='line'>                    <span class="nv">$request</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">[</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requestMap</span><span class="p">[</span><span class="nv">$key</span><span class="p">]];</span>
</span><span class='line'>                    <span class="nb">unset</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requestMap</span><span class="p">[</span><span class="nv">$key</span><span class="p">]);</span>
</span><span class='line'>                    <span class="nb">call_user_func</span><span class="p">(</span><span class="nv">$callback</span><span class="p">,</span> <span class="nv">$output</span><span class="p">,</span> <span class="nv">$info</span><span class="p">,</span> <span class="nv">$request</span><span class="p">);</span>
</span><span class='line'>                <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>                <span class="c1">// start a new request (it&#39;s important to do this before removing the old one)</span>
</span><span class='line'>                <span class="k">if</span> <span class="p">(</span><span class="nv">$i</span> <span class="o">&lt;</span> <span class="nb">sizeof</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="nb">isset</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">[</span><span class="nv">$i</span><span class="p">])</span> <span class="o">&amp;&amp;</span> <span class="nv">$i</span> <span class="o">&lt;</span> <span class="nb">count</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">))</span> <span class="p">{</span>
</span><span class='line'>                    <span class="nv">$ch</span> <span class="o">=</span> <span class="nb">curl_init</span><span class="p">();</span>
</span><span class='line'>                    <span class="nv">$options</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">get_options</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">[</span><span class="nv">$i</span><span class="p">]);</span>
</span><span class='line'>                    <span class="nb">curl_setopt_array</span><span class="p">(</span><span class="nv">$ch</span><span class="p">,</span><span class="nv">$options</span><span class="p">);</span>
</span><span class='line'>                    <span class="nb">curl_multi_add_handle</span><span class="p">(</span><span class="nv">$master</span><span class="p">,</span> <span class="nv">$ch</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>                    <span class="c1">// Add to our request Maps</span>
</span><span class='line'>                    <span class="nv">$key</span> <span class="o">=</span> <span class="p">(</span><span class="nx">string</span><span class="p">)</span> <span class="nv">$ch</span><span class="p">;</span>
</span><span class='line'>                    <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requestMap</span><span class="p">[</span><span class="nv">$key</span><span class="p">]</span> <span class="o">=</span> <span class="nv">$i</span><span class="p">;</span>
</span><span class='line'>                    <span class="nv">$i</span><span class="o">++</span><span class="p">;</span>
</span><span class='line'>                <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>                <span class="c1">// remove the curl handle that just completed</span>
</span><span class='line'>                <span class="nb">curl_multi_remove_handle</span><span class="p">(</span><span class="nv">$master</span><span class="p">,</span> <span class="nv">$done</span><span class="p">[</span><span class="s1">&#39;handle&#39;</span><span class="p">]);</span>
</span><span class='line'>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>            <span class="c1">// Block for data in / output; error handling is done by curl_multi_exec</span>
</span><span class='line'>            <span class="k">if</span> <span class="p">(</span><span class="nv">$running</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>                <span class="nb">curl_multi_select</span><span class="p">(</span><span class="nv">$master</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">timeout</span><span class="p">);</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="p">}</span> <span class="k">while</span> <span class="p">(</span><span class="nv">$running</span><span class="p">);</span>
</span><span class='line'>        <span class="nb">curl_multi_close</span><span class="p">(</span><span class="nv">$master</span><span class="p">);</span>
</span><span class='line'>        <span class="k">return</span> <span class="k">true</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * Helper function to set up a new request by setting the appropriate options</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * @access private</span>
</span><span class='line'><span class="sd">     * @param Request $request</span>
</span><span class='line'><span class="sd">     * @return array</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">private</span> <span class="k">function</span> <span class="nf">get_options</span><span class="p">(</span><span class="nv">$request</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="c1">// options for this entire curl object</span>
</span><span class='line'>        <span class="nv">$options</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">__get</span><span class="p">(</span><span class="s1">&#39;options&#39;</span><span class="p">);</span>
</span><span class='line'>        <span class="c1">// NOTE: The PHP cURL library won&#39;t follow redirects if either safe_mode is on</span>
</span><span class='line'>        <span class="c1">// or open_basedir is defined.</span>
</span><span class='line'>        <span class="c1">// See: https://bugs.php.net/bug.php?id=30609</span>
</span><span class='line'>      <span class="k">if</span> <span class="p">((</span> <span class="nb">ini_get</span><span class="p">(</span><span class="s1">&#39;safe_mode&#39;</span><span class="p">)</span> <span class="o">==</span> <span class="s1">&#39;Off&#39;</span> <span class="o">||</span> <span class="o">!</span><span class="nb">ini_get</span><span class="p">(</span><span class="s1">&#39;safe_mode&#39;</span><span class="p">)</span> <span class="p">)</span>
</span><span class='line'>            <span class="o">&amp;&amp;</span> <span class="nb">ini_get</span><span class="p">(</span><span class="s1">&#39;open_basedir&#39;</span><span class="p">)</span> <span class="o">==</span> <span class="s1">&#39;&#39;</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="nv">$options</span><span class="p">[</span><span class="nx">CURLOPT_FOLLOWLOCATION</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>          <span class="nv">$options</span><span class="p">[</span><span class="nx">CURLOPT_MAXREDIRS</span><span class="p">]</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>        <span class="nv">$headers</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">__get</span><span class="p">(</span><span class="s1">&#39;headers&#39;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>      <span class="c1">// append custom options for this specific request</span>
</span><span class='line'>      <span class="k">if</span> <span class="p">(</span><span class="nv">$request</span><span class="o">-&gt;</span><span class="na">options</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="nv">$options</span> <span class="o">=</span> <span class="nv">$request</span><span class="o">-&gt;</span><span class="na">options</span> <span class="o">+</span> <span class="nv">$options</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>      <span class="c1">// set the request URL</span>
</span><span class='line'>        <span class="nv">$options</span><span class="p">[</span><span class="nx">CURLOPT_URL</span><span class="p">]</span> <span class="o">=</span> <span class="nv">$request</span><span class="o">-&gt;</span><span class="na">url</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>        <span class="c1">// posting data w/ this request?</span>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="nv">$request</span><span class="o">-&gt;</span><span class="na">post_data</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="nv">$options</span><span class="p">[</span><span class="nx">CURLOPT_POST</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>            <span class="nv">$options</span><span class="p">[</span><span class="nx">CURLOPT_POSTFIELDS</span><span class="p">]</span> <span class="o">=</span> <span class="nv">$request</span><span class="o">-&gt;</span><span class="na">post_data</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="nv">$headers</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="nv">$options</span><span class="p">[</span><span class="nx">CURLOPT_HEADER</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'>            <span class="nv">$options</span><span class="p">[</span><span class="nx">CURLOPT_HTTPHEADER</span><span class="p">]</span> <span class="o">=</span> <span class="nv">$headers</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="c1">// Due to a bug in cURL CURLOPT_WRITEFUNCTION must be defined as the last option</span>
</span><span class='line'>        <span class="c1">// Otherwise it doesn&#39;t register. So let&#39;s unset and set it again</span>
</span><span class='line'>        <span class="c1">// See http://stackoverflow.com/questions/15937055/curl-writefunction-not-being-called</span>
</span><span class='line'>        <span class="k">if</span><span class="p">(</span> <span class="o">!</span> <span class="k">empty</span><span class="p">(</span> <span class="nv">$options</span><span class="p">[</span><span class="nx">CURLOPT_WRITEFUNCTION</span><span class="p">])</span> <span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="nv">$writeCallback</span> <span class="o">=</span> <span class="nv">$options</span><span class="p">[</span><span class="nx">CURLOPT_WRITEFUNCTION</span><span class="p">];</span>
</span><span class='line'>            <span class="nb">unset</span><span class="p">(</span> <span class="nv">$options</span><span class="p">[</span><span class="nx">CURLOPT_WRITEFUNCTION</span><span class="p">]</span> <span class="p">);</span>
</span><span class='line'>            <span class="nv">$options</span><span class="p">[</span><span class="nx">CURLOPT_WRITEFUNCTION</span><span class="p">]</span> <span class="o">=</span> <span class="nv">$writeCallback</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">return</span> <span class="nv">$options</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @return void</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">__destruct</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>        <span class="nb">unset</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">window_size</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">callback</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">options</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">headers</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">);</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p><strong><em>RollingCurl.php</em></strong>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
<span class='line-number'>80</span>
<span class='line-number'>81</span>
<span class='line-number'>82</span>
<span class='line-number'>83</span>
<span class='line-number'>84</span>
<span class='line-number'>85</span>
<span class='line-number'>86</span>
<span class='line-number'>87</span>
<span class='line-number'>88</span>
<span class='line-number'>89</span>
<span class='line-number'>90</span>
<span class='line-number'>91</span>
<span class='line-number'>92</span>
<span class='line-number'>93</span>
<span class='line-number'>94</span>
<span class='line-number'>95</span>
<span class='line-number'>96</span>
<span class='line-number'>97</span>
<span class='line-number'>98</span>
<span class='line-number'>99</span>
<span class='line-number'>100</span>
<span class='line-number'>101</span>
<span class='line-number'>102</span>
<span class='line-number'>103</span>
<span class='line-number'>104</span>
<span class='line-number'>105</span>
<span class='line-number'>106</span>
<span class='line-number'>107</span>
<span class='line-number'>108</span>
<span class='line-number'>109</span>
<span class='line-number'>110</span>
<span class='line-number'>111</span>
<span class='line-number'>112</span>
<span class='line-number'>113</span>
<span class='line-number'>114</span>
<span class='line-number'>115</span>
<span class='line-number'>116</span>
<span class='line-number'>117</span>
<span class='line-number'>118</span>
<span class='line-number'>119</span>
<span class='line-number'>120</span>
<span class='line-number'>121</span>
<span class='line-number'>122</span>
<span class='line-number'>123</span>
<span class='line-number'>124</span>
<span class='line-number'>125</span>
<span class='line-number'>126</span>
<span class='line-number'>127</span>
<span class='line-number'>128</span>
<span class='line-number'>129</span>
<span class='line-number'>130</span>
<span class='line-number'>131</span>
<span class='line-number'>132</span>
<span class='line-number'>133</span>
<span class='line-number'>134</span>
<span class='line-number'>135</span>
<span class='line-number'>136</span>
<span class='line-number'>137</span>
<span class='line-number'>138</span>
<span class='line-number'>139</span>
<span class='line-number'>140</span>
<span class='line-number'>141</span>
<span class='line-number'>142</span>
<span class='line-number'>143</span>
<span class='line-number'>144</span>
<span class='line-number'>145</span>
<span class='line-number'>146</span>
<span class='line-number'>147</span>
<span class='line-number'>148</span>
<span class='line-number'>149</span>
<span class='line-number'>150</span>
<span class='line-number'>151</span>
<span class='line-number'>152</span>
<span class='line-number'>153</span>
<span class='line-number'>154</span>
<span class='line-number'>155</span>
<span class='line-number'>156</span>
<span class='line-number'>157</span>
<span class='line-number'>158</span>
<span class='line-number'>159</span>
<span class='line-number'>160</span>
<span class='line-number'>161</span>
<span class='line-number'>162</span>
<span class='line-number'>163</span>
<span class='line-number'>164</span>
<span class='line-number'>165</span>
<span class='line-number'>166</span>
<span class='line-number'>167</span>
<span class='line-number'>168</span>
<span class='line-number'>169</span>
<span class='line-number'>170</span>
<span class='line-number'>171</span>
<span class='line-number'>172</span>
<span class='line-number'>173</span>
<span class='line-number'>174</span>
<span class='line-number'>175</span>
<span class='line-number'>176</span>
<span class='line-number'>177</span>
<span class='line-number'>178</span>
<span class='line-number'>179</span>
<span class='line-number'>180</span>
<span class='line-number'>181</span>
<span class='line-number'>182</span>
<span class='line-number'>183</span>
<span class='line-number'>184</span>
<span class='line-number'>185</span>
<span class='line-number'>186</span>
<span class='line-number'>187</span>
<span class='line-number'>188</span>
<span class='line-number'>189</span>
<span class='line-number'>190</span>
<span class='line-number'>191</span>
<span class='line-number'>192</span>
<span class='line-number'>193</span>
<span class='line-number'>194</span>
<span class='line-number'>195</span>
<span class='line-number'>196</span>
<span class='line-number'>197</span>
<span class='line-number'>198</span>
<span class='line-number'>199</span>
<span class='line-number'>200</span>
<span class='line-number'>201</span>
<span class='line-number'>202</span>
<span class='line-number'>203</span>
<span class='line-number'>204</span>
<span class='line-number'>205</span>
<span class='line-number'>206</span>
<span class='line-number'>207</span>
<span class='line-number'>208</span>
<span class='line-number'>209</span>
<span class='line-number'>210</span>
<span class='line-number'>211</span>
<span class='line-number'>212</span>
<span class='line-number'>213</span>
<span class='line-number'>214</span>
<span class='line-number'>215</span>
<span class='line-number'>216</span>
<span class='line-number'>217</span>
<span class='line-number'>218</span>
<span class='line-number'>219</span>
<span class='line-number'>220</span>
<span class='line-number'>221</span>
<span class='line-number'>222</span>
<span class='line-number'>223</span>
<span class='line-number'>224</span>
<span class='line-number'>225</span>
<span class='line-number'>226</span>
<span class='line-number'>227</span>
<span class='line-number'>228</span>
<span class='line-number'>229</span>
<span class='line-number'>230</span>
<span class='line-number'>231</span>
<span class='line-number'>232</span>
<span class='line-number'>233</span>
<span class='line-number'>234</span>
<span class='line-number'>235</span>
<span class='line-number'>236</span>
<span class='line-number'>237</span>
<span class='line-number'>238</span>
<span class='line-number'>239</span>
<span class='line-number'>240</span>
<span class='line-number'>241</span>
<span class='line-number'>242</span>
<span class='line-number'>243</span>
<span class='line-number'>244</span>
<span class='line-number'>245</span>
<span class='line-number'>246</span>
<span class='line-number'>247</span>
<span class='line-number'>248</span>
<span class='line-number'>249</span>
<span class='line-number'>250</span>
<span class='line-number'>251</span>
<span class='line-number'>252</span>
<span class='line-number'>253</span>
<span class='line-number'>254</span>
<span class='line-number'>255</span>
<span class='line-number'>256</span>
<span class='line-number'>257</span>
<span class='line-number'>258</span>
<span class='line-number'>259</span>
<span class='line-number'>260</span>
<span class='line-number'>261</span>
<span class='line-number'>262</span>
<span class='line-number'>263</span>
<span class='line-number'>264</span>
<span class='line-number'>265</span>
<span class='line-number'>266</span>
<span class='line-number'>267</span>
<span class='line-number'>268</span>
<span class='line-number'>269</span>
<span class='line-number'>270</span>
<span class='line-number'>271</span>
<span class='line-number'>272</span>
<span class='line-number'>273</span>
<span class='line-number'>274</span>
<span class='line-number'>275</span>
<span class='line-number'>276</span>
<span class='line-number'>277</span>
<span class='line-number'>278</span>
<span class='line-number'>279</span>
<span class='line-number'>280</span>
<span class='line-number'>281</span>
<span class='line-number'>282</span>
<span class='line-number'>283</span>
<span class='line-number'>284</span>
<span class='line-number'>285</span>
<span class='line-number'>286</span>
<span class='line-number'>287</span>
<span class='line-number'>288</span>
<span class='line-number'>289</span>
<span class='line-number'>290</span>
<span class='line-number'>291</span>
<span class='line-number'>292</span>
<span class='line-number'>293</span>
<span class='line-number'>294</span>
<span class='line-number'>295</span>
<span class='line-number'>296</span>
<span class='line-number'>297</span>
<span class='line-number'>298</span>
<span class='line-number'>299</span>
<span class='line-number'>300</span>
<span class='line-number'>301</span>
<span class='line-number'>302</span>
<span class='line-number'>303</span>
<span class='line-number'>304</span>
<span class='line-number'>305</span>
<span class='line-number'>306</span>
<span class='line-number'>307</span>
<span class='line-number'>308</span>
<span class='line-number'>309</span>
<span class='line-number'>310</span>
<span class='line-number'>311</span>
<span class='line-number'>312</span>
<span class='line-number'>313</span>
<span class='line-number'>314</span>
<span class='line-number'>315</span>
<span class='line-number'>316</span>
<span class='line-number'>317</span>
<span class='line-number'>318</span>
<span class='line-number'>319</span>
<span class='line-number'>320</span>
<span class='line-number'>321</span>
<span class='line-number'>322</span>
<span class='line-number'>323</span>
<span class='line-number'>324</span>
<span class='line-number'>325</span>
<span class='line-number'>326</span>
<span class='line-number'>327</span>
<span class='line-number'>328</span>
<span class='line-number'>329</span>
<span class='line-number'>330</span>
<span class='line-number'>331</span>
<span class='line-number'>332</span>
<span class='line-number'>333</span>
<span class='line-number'>334</span>
<span class='line-number'>335</span>
<span class='line-number'>336</span>
<span class='line-number'>337</span>
<span class='line-number'>338</span>
<span class='line-number'>339</span>
<span class='line-number'>340</span>
<span class='line-number'>341</span>
<span class='line-number'>342</span>
<span class='line-number'>343</span>
<span class='line-number'>344</span>
<span class='line-number'>345</span>
<span class='line-number'>346</span>
<span class='line-number'>347</span>
<span class='line-number'>348</span>
<span class='line-number'>349</span>
<span class='line-number'>350</span>
<span class='line-number'>351</span>
<span class='line-number'>352</span>
<span class='line-number'>353</span>
<span class='line-number'>354</span>
<span class='line-number'>355</span>
<span class='line-number'>356</span>
<span class='line-number'>357</span>
<span class='line-number'>358</span>
<span class='line-number'>359</span>
<span class='line-number'>360</span>
<span class='line-number'>361</span>
<span class='line-number'>362</span>
<span class='line-number'>363</span>
<span class='line-number'>364</span>
<span class='line-number'>365</span>
<span class='line-number'>366</span>
<span class='line-number'>367</span>
<span class='line-number'>368</span>
<span class='line-number'>369</span>
<span class='line-number'>370</span>
<span class='line-number'>371</span>
<span class='line-number'>372</span>
<span class='line-number'>373</span>
<span class='line-number'>374</span>
<span class='line-number'>375</span>
<span class='line-number'>376</span>
<span class='line-number'>377</span>
<span class='line-number'>378</span>
<span class='line-number'>379</span>
<span class='line-number'>380</span>
<span class='line-number'>381</span>
<span class='line-number'>382</span>
<span class='line-number'>383</span>
<span class='line-number'>384</span>
<span class='line-number'>385</span>
<span class='line-number'>386</span>
<span class='line-number'>387</span>
<span class='line-number'>388</span>
<span class='line-number'>389</span>
<span class='line-number'>390</span>
<span class='line-number'>391</span>
<span class='line-number'>392</span>
<span class='line-number'>393</span>
<span class='line-number'>394</span>
<span class='line-number'>395</span>
<span class='line-number'>396</span>
<span class='line-number'>397</span>
<span class='line-number'>398</span>
<span class='line-number'>399</span>
<span class='line-number'>400</span>
<span class='line-number'>401</span>
<span class='line-number'>402</span>
<span class='line-number'>403</span>
<span class='line-number'>404</span>
<span class='line-number'>405</span>
<span class='line-number'>406</span>
<span class='line-number'>407</span>
<span class='line-number'>408</span>
<span class='line-number'>409</span>
<span class='line-number'>410</span>
<span class='line-number'>411</span>
<span class='line-number'>412</span>
<span class='line-number'>413</span>
<span class='line-number'>414</span>
<span class='line-number'>415</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="cm">/*</span>
</span><span class='line'><span class="cm">Authored by Josh Fraser (www.joshfraser.com)</span>
</span><span class='line'><span class="cm">Released under Apache License 2.0</span>
</span><span class='line'>
</span><span class='line'><span class="cm">Maintained by Alexander Makarov, http://rmcreative.ru/</span>
</span><span class='line'>
</span><span class='line'><span class="cm">$Id$</span>
</span><span class='line'><span class="cm">*/</span>
</span><span class='line'>
</span><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * Class that represent a single curl request</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'><span class="k">class</span> <span class="nc">RollingCurlRequest</span> <span class="p">{</span>
</span><span class='line'>  <span class="k">public</span> <span class="nv">$url</span> <span class="o">=</span> <span class="k">false</span><span class="p">;</span>
</span><span class='line'>  <span class="k">public</span> <span class="nv">$method</span> <span class="o">=</span> <span class="s1">&#39;GET&#39;</span><span class="p">;</span>
</span><span class='line'>  <span class="k">public</span> <span class="nv">$post_data</span> <span class="o">=</span> <span class="k">null</span><span class="p">;</span>
</span><span class='line'>  <span class="k">public</span> <span class="nv">$headers</span> <span class="o">=</span> <span class="k">null</span><span class="p">;</span>
</span><span class='line'>  <span class="k">public</span> <span class="nv">$options</span> <span class="o">=</span> <span class="k">null</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @param string $url</span>
</span><span class='line'><span class="sd">     * @param string $method</span>
</span><span class='line'><span class="sd">     * @param  $post_data</span>
</span><span class='line'><span class="sd">     * @param  $headers</span>
</span><span class='line'><span class="sd">     * @param  $options</span>
</span><span class='line'><span class="sd">     * @return void</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">function</span> <span class="nf">__construct</span><span class="p">(</span><span class="nv">$url</span><span class="p">,</span> <span class="nv">$method</span> <span class="o">=</span> <span class="s2">&quot;GET&quot;</span><span class="p">,</span> <span class="nv">$post_data</span> <span class="o">=</span> <span class="k">null</span><span class="p">,</span> <span class="nv">$headers</span> <span class="o">=</span> <span class="k">null</span><span class="p">,</span> <span class="nv">$options</span> <span class="o">=</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">url</span> <span class="o">=</span> <span class="nv">$url</span><span class="p">;</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">method</span> <span class="o">=</span> <span class="nv">$method</span><span class="p">;</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">post_data</span> <span class="o">=</span> <span class="nv">$post_data</span><span class="p">;</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">headers</span> <span class="o">=</span> <span class="nv">$headers</span><span class="p">;</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">options</span> <span class="o">=</span> <span class="nv">$options</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @return void</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">__destruct</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>        <span class="nb">unset</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">url</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">method</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">post_data</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">headers</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">options</span><span class="p">);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * RollingCurl custom exception</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'><span class="k">class</span> <span class="nc">RollingCurlException</span> <span class="k">extends</span> <span class="nx">Exception</span> <span class="p">{}</span>
</span><span class='line'>
</span><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * Class that holds a rolling queue of curl requests.</span>
</span><span class='line'><span class="sd"> *</span>
</span><span class='line'><span class="sd"> * @throws RollingCurlException</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'><span class="k">class</span> <span class="nc">RollingCurl</span> <span class="p">{</span>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @var int</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * Window size is the max number of simultaneous connections allowed.</span>
</span><span class='line'><span class="sd">  * </span>
</span><span class='line'><span class="sd">     * REMEMBER TO RESPECT THE SERVERS:</span>
</span><span class='line'><span class="sd">     * Sending too many requests at one time can easily be perceived</span>
</span><span class='line'><span class="sd">     * as a DOS attack. Increase this window_size if you are making requests</span>
</span><span class='line'><span class="sd">     * to multiple servers or have permission from the receving server admins.</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">private</span> <span class="nv">$window_size</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @var float</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * Timeout is the timeout used for curl_multi_select.</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">private</span> <span class="nv">$timeout</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @var string|array</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * Callback function to be applied to each result.</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">private</span> <span class="nv">$callback</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @var array</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * Set your base options that you want to be used with EVERY request.</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">protected</span> <span class="nv">$options</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span>
</span><span class='line'>      <span class="nx">CURLOPT_SSL_VERIFYPEER</span> <span class="o">=&gt;</span> <span class="mi">0</span><span class="p">,</span>
</span><span class='line'>        <span class="nx">CURLOPT_RETURNTRANSFER</span> <span class="o">=&gt;</span> <span class="mi">1</span><span class="p">,</span>
</span><span class='line'>        <span class="nx">CURLOPT_CONNECTTIMEOUT</span> <span class="o">=&gt;</span> <span class="mi">30</span><span class="p">,</span>
</span><span class='line'>        <span class="nx">CURLOPT_TIMEOUT</span> <span class="o">=&gt;</span> <span class="mi">30</span>
</span><span class='line'>  <span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @var array</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">private</span> <span class="nv">$headers</span> <span class="o">=</span> <span class="k">array</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @var Request[]</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * The request queue</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">private</span> <span class="nv">$requests</span> <span class="o">=</span> <span class="k">array</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @var RequestMap[]</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * Maps handles to request indexes</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">private</span> <span class="nv">$requestMap</span> <span class="o">=</span> <span class="k">array</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @var returns[]</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * All returns of requests</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">private</span> <span class="nv">$returns</span> <span class="o">=</span> <span class="k">array</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @param  $callback</span>
</span><span class='line'><span class="sd">     * Callback function to be applied to each result.</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * Can be specified as &#39;my_callback_function&#39;</span>
</span><span class='line'><span class="sd">     * or array($object, &#39;my_callback_method&#39;).</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * Function should take three parameters: $response, $info, $request.</span>
</span><span class='line'><span class="sd">     * $response is response body, $info is additional curl info.</span>
</span><span class='line'><span class="sd">     * $request is the original request</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * @return void</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>  <span class="k">function</span> <span class="nf">__construct</span><span class="p">(</span><span class="nv">$callback</span> <span class="o">=</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">callback</span> <span class="o">=</span> <span class="nv">$callback</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @param string $name</span>
</span><span class='line'><span class="sd">     * @return mixed</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">__get</span><span class="p">(</span><span class="nv">$name</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">return</span> <span class="p">(</span><span class="nb">isset</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="p">{</span><span class="nv">$name</span><span class="p">}))</span> <span class="o">?</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="p">{</span><span class="nv">$name</span><span class="p">}</span> <span class="o">:</span> <span class="k">null</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @param string $name</span>
</span><span class='line'><span class="sd">     * @param mixed $value</span>
</span><span class='line'><span class="sd">     * @return bool</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">__set</span><span class="p">(</span><span class="nv">$name</span><span class="p">,</span> <span class="nv">$value</span><span class="p">){</span>
</span><span class='line'>        <span class="c1">// append the base options &amp; headers</span>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="nv">$name</span> <span class="o">==</span> <span class="s2">&quot;options&quot;</span> <span class="o">||</span> <span class="nv">$name</span> <span class="o">==</span> <span class="s2">&quot;headers&quot;</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="nv">$this</span><span class="o">-&gt;</span><span class="p">{</span><span class="nv">$name</span><span class="p">}</span> <span class="o">=</span> <span class="nv">$value</span> <span class="o">+</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="p">{</span><span class="nv">$name</span><span class="p">};</span>
</span><span class='line'>        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>            <span class="nv">$this</span><span class="o">-&gt;</span><span class="p">{</span><span class="nv">$name</span><span class="p">}</span> <span class="o">=</span> <span class="nv">$value</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>        <span class="k">return</span> <span class="k">true</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * Add a request to the request queue</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * @param Request $request</span>
</span><span class='line'><span class="sd">     * @return bool</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">add</span><span class="p">(</span><span class="nv">$request</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>         <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">[]</span> <span class="o">=</span> <span class="nv">$request</span><span class="p">;</span>
</span><span class='line'>         <span class="k">return</span> <span class="k">true</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @param \returns[] $returns</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">setReturns</span><span class="p">(</span><span class="nv">$returns</span><span class="p">)</span>
</span><span class='line'>    <span class="p">{</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">returns</span> <span class="o">=</span> <span class="nv">$returns</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @return \returns[]</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">getReturns</span><span class="p">()</span>
</span><span class='line'>    <span class="p">{</span>
</span><span class='line'>        <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">returns</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * Create new Request and add it to the request queue</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * @param string $url</span>
</span><span class='line'><span class="sd">     * @param string $method</span>
</span><span class='line'><span class="sd">     * @param  $post_data</span>
</span><span class='line'><span class="sd">     * @param  $headers</span>
</span><span class='line'><span class="sd">     * @param  $options</span>
</span><span class='line'><span class="sd">     * @return bool</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">request</span><span class="p">(</span><span class="nv">$url</span><span class="p">,</span> <span class="nv">$method</span> <span class="o">=</span> <span class="s2">&quot;GET&quot;</span><span class="p">,</span> <span class="nv">$post_data</span> <span class="o">=</span> <span class="k">null</span><span class="p">,</span> <span class="nv">$headers</span> <span class="o">=</span> <span class="k">null</span><span class="p">,</span> <span class="nv">$options</span> <span class="o">=</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>         <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">[]</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">RollingCurlRequest</span><span class="p">(</span><span class="nv">$url</span><span class="p">,</span> <span class="nv">$method</span><span class="p">,</span> <span class="nv">$post_data</span><span class="p">,</span> <span class="nv">$headers</span><span class="p">,</span> <span class="nv">$options</span><span class="p">);</span>
</span><span class='line'>         <span class="k">return</span> <span class="k">true</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * Perform GET request</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * @param string $url</span>
</span><span class='line'><span class="sd">     * @param  $headers</span>
</span><span class='line'><span class="sd">     * @param  $options</span>
</span><span class='line'><span class="sd">     * @return bool</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">get</span><span class="p">(</span><span class="nv">$url</span><span class="p">,</span> <span class="nv">$headers</span> <span class="o">=</span> <span class="k">null</span><span class="p">,</span> <span class="nv">$options</span> <span class="o">=</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">request</span><span class="p">(</span><span class="nv">$url</span><span class="p">,</span> <span class="s2">&quot;GET&quot;</span><span class="p">,</span> <span class="k">null</span><span class="p">,</span> <span class="nv">$headers</span><span class="p">,</span> <span class="nv">$options</span><span class="p">);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * Perform POST request</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * @param string $url</span>
</span><span class='line'><span class="sd">     * @param  $post_data</span>
</span><span class='line'><span class="sd">     * @param  $headers</span>
</span><span class='line'><span class="sd">     * @param  $options</span>
</span><span class='line'><span class="sd">     * @return bool</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">post</span><span class="p">(</span><span class="nv">$url</span><span class="p">,</span> <span class="nv">$post_data</span> <span class="o">=</span> <span class="k">null</span><span class="p">,</span> <span class="nv">$headers</span> <span class="o">=</span> <span class="k">null</span><span class="p">,</span> <span class="nv">$options</span> <span class="o">=</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">request</span><span class="p">(</span><span class="nv">$url</span><span class="p">,</span> <span class="s2">&quot;POST&quot;</span><span class="p">,</span> <span class="nv">$post_data</span><span class="p">,</span> <span class="nv">$headers</span><span class="p">,</span> <span class="nv">$options</span><span class="p">);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * Execute the curl</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * @param int $window_size Max number of simultaneous connections</span>
</span><span class='line'><span class="sd">     * @return string|bool</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">execute</span><span class="p">(</span><span class="nv">$window_size</span> <span class="o">=</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="c1">// rolling curl window must always be greater than 1</span>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="nb">sizeof</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">single_curl</span><span class="p">();</span>
</span><span class='line'>        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>            <span class="c1">// start the rolling curl. window_size is the max number of simultaneous connections</span>
</span><span class='line'>            <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">rolling_curl</span><span class="p">(</span><span class="nv">$window_size</span><span class="p">);</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * Performs a single curl request</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * @access private</span>
</span><span class='line'><span class="sd">     * @return string</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">private</span> <span class="k">function</span> <span class="nf">single_curl</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>        <span class="nv">$ch</span> <span class="o">=</span> <span class="nb">curl_init</span><span class="p">();</span>
</span><span class='line'>        <span class="nv">$request</span> <span class="o">=</span> <span class="nb">array_shift</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">);</span>
</span><span class='line'>        <span class="nv">$options</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">get_options</span><span class="p">(</span><span class="nv">$request</span><span class="p">);</span>
</span><span class='line'>        <span class="nb">curl_setopt_array</span><span class="p">(</span><span class="nv">$ch</span><span class="p">,</span><span class="nv">$options</span><span class="p">);</span>
</span><span class='line'>        <span class="nv">$output</span> <span class="o">=</span> <span class="nb">curl_exec</span><span class="p">(</span><span class="nv">$ch</span><span class="p">);</span>
</span><span class='line'>        <span class="nv">$info</span> <span class="o">=</span> <span class="nb">curl_getinfo</span><span class="p">(</span><span class="nv">$ch</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>        <span class="c1">// it&#39;s not neccesary to set a callback for one-off requests</span>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">callback</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="nv">$callback</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">callback</span><span class="p">;</span>
</span><span class='line'>            <span class="k">if</span> <span class="p">(</span><span class="nb">is_callable</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">callback</span><span class="p">)){</span>
</span><span class='line'>                <span class="nb">call_user_func</span><span class="p">(</span><span class="nv">$callback</span><span class="p">,</span> <span class="nv">$output</span><span class="p">,</span> <span class="nv">$info</span><span class="p">,</span> <span class="nv">$request</span><span class="p">);</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>      <span class="k">else</span>
</span><span class='line'>            <span class="k">return</span> <span class="nv">$output</span><span class="p">;</span>
</span><span class='line'>  <span class="k">return</span> <span class="k">true</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * Performs multiple curl requests</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * @access private</span>
</span><span class='line'><span class="sd">     * @throws RollingCurlException</span>
</span><span class='line'><span class="sd">     * @param int $window_size Max number of simultaneous connections</span>
</span><span class='line'><span class="sd">     * @return bool</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">private</span> <span class="k">function</span> <span class="nf">rolling_curl</span><span class="p">(</span><span class="nv">$window_size</span> <span class="o">=</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="nv">$window_size</span><span class="p">)</span>
</span><span class='line'>            <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">window_size</span> <span class="o">=</span> <span class="nv">$window_size</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>        <span class="c1">// make sure the rolling window isn&#39;t greater than the # of urls</span>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="nb">sizeof</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">)</span> <span class="o">&lt;</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">window_size</span><span class="p">)</span>
</span><span class='line'>            <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">window_size</span> <span class="o">=</span> <span class="nb">sizeof</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">window_size</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="k">throw</span> <span class="k">new</span> <span class="nx">RollingCurlException</span><span class="p">(</span><span class="s2">&quot;Window size must be greater than 1&quot;</span><span class="p">);</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="nv">$master</span> <span class="o">=</span> <span class="nb">curl_multi_init</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>        <span class="c1">// start the first batch of requests</span>
</span><span class='line'>        <span class="k">for</span> <span class="p">(</span><span class="nv">$i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nv">$i</span> <span class="o">&lt;</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">window_size</span><span class="p">;</span> <span class="nv">$i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="nv">$ch</span> <span class="o">=</span> <span class="nb">curl_init</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>            <span class="nv">$options</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">get_options</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">[</span><span class="nv">$i</span><span class="p">]);</span>
</span><span class='line'>
</span><span class='line'>            <span class="nb">curl_setopt_array</span><span class="p">(</span><span class="nv">$ch</span><span class="p">,</span><span class="nv">$options</span><span class="p">);</span>
</span><span class='line'>            <span class="nb">curl_multi_add_handle</span><span class="p">(</span><span class="nv">$master</span><span class="p">,</span> <span class="nv">$ch</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>            <span class="c1">// Add to our request Maps</span>
</span><span class='line'>            <span class="nv">$key</span> <span class="o">=</span> <span class="p">(</span><span class="nx">string</span><span class="p">)</span> <span class="nv">$ch</span><span class="p">;</span>
</span><span class='line'>            <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requestMap</span><span class="p">[</span><span class="nv">$key</span><span class="p">]</span> <span class="o">=</span> <span class="nv">$i</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">do</span> <span class="p">{</span>
</span><span class='line'>            <span class="k">while</span><span class="p">((</span><span class="nv">$execrun</span> <span class="o">=</span> <span class="nb">curl_multi_exec</span><span class="p">(</span><span class="nv">$master</span><span class="p">,</span> <span class="nv">$running</span><span class="p">))</span> <span class="o">==</span> <span class="nx">CURLM_CALL_MULTI_PERFORM</span><span class="p">);</span>
</span><span class='line'>            <span class="k">if</span><span class="p">(</span><span class="nv">$execrun</span> <span class="o">!=</span> <span class="nx">CURLM_OK</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>                <span class="k">break</span><span class="p">;</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="c1">// a request was just completed -- find out which one</span>
</span><span class='line'>            <span class="k">while</span><span class="p">(</span><span class="nv">$done</span> <span class="o">=</span> <span class="nb">curl_multi_info_read</span><span class="p">(</span><span class="nv">$master</span><span class="p">))</span> <span class="p">{</span>
</span><span class='line'>
</span><span class='line'>                <span class="c1">// get the info and content returned on the request</span>
</span><span class='line'>                <span class="nv">$info</span> <span class="o">=</span> <span class="nb">curl_getinfo</span><span class="p">(</span><span class="nv">$done</span><span class="p">[</span><span class="s1">&#39;handle&#39;</span><span class="p">]);</span>
</span><span class='line'>                <span class="nv">$output</span> <span class="o">=</span> <span class="nb">curl_multi_getcontent</span><span class="p">(</span><span class="nv">$done</span><span class="p">[</span><span class="s1">&#39;handle&#39;</span><span class="p">]);</span>
</span><span class='line'>
</span><span class='line'>                <span class="nb">array_push</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">returns</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span>
</span><span class='line'>                    <span class="s1">&#39;return&#39;</span>    <span class="o">=&gt;</span>  <span class="nv">$output</span><span class="p">,</span>
</span><span class='line'>                    <span class="s1">&#39;info&#39;</span>      <span class="o">=&gt;</span>  <span class="nv">$info</span><span class="p">,</span>
</span><span class='line'>                <span class="p">));</span>
</span><span class='line'>
</span><span class='line'>                <span class="c1">// send the return values to the callback function.</span>
</span><span class='line'>                <span class="nv">$callback</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">callback</span><span class="p">;</span>
</span><span class='line'>                <span class="k">if</span> <span class="p">(</span><span class="nb">is_callable</span><span class="p">(</span><span class="nv">$callback</span><span class="p">)){</span>
</span><span class='line'>              <span class="nv">$key</span> <span class="o">=</span> <span class="p">(</span><span class="nx">string</span><span class="p">)</span><span class="nv">$done</span><span class="p">[</span><span class="s1">&#39;handle&#39;</span><span class="p">];</span>
</span><span class='line'>                    <span class="nv">$request</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">[</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requestMap</span><span class="p">[</span><span class="nv">$key</span><span class="p">]];</span>
</span><span class='line'>                    <span class="nb">unset</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requestMap</span><span class="p">[</span><span class="nv">$key</span><span class="p">]);</span>
</span><span class='line'>                    <span class="nb">call_user_func</span><span class="p">(</span><span class="nv">$callback</span><span class="p">,</span> <span class="nv">$output</span><span class="p">,</span> <span class="nv">$info</span><span class="p">,</span> <span class="nv">$request</span><span class="p">);</span>
</span><span class='line'>                <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>                <span class="c1">// start a new request (it&#39;s important to do this before removing the old one)</span>
</span><span class='line'>                <span class="k">if</span> <span class="p">(</span><span class="nv">$i</span> <span class="o">&lt;</span> <span class="nb">sizeof</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="nb">isset</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">[</span><span class="nv">$i</span><span class="p">])</span> <span class="o">&amp;&amp;</span> <span class="nv">$i</span> <span class="o">&lt;</span> <span class="nb">count</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">))</span> <span class="p">{</span>
</span><span class='line'>                    <span class="nv">$ch</span> <span class="o">=</span> <span class="nb">curl_init</span><span class="p">();</span>
</span><span class='line'>                    <span class="nv">$options</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">get_options</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">[</span><span class="nv">$i</span><span class="p">]);</span>
</span><span class='line'>                    <span class="nb">curl_setopt_array</span><span class="p">(</span><span class="nv">$ch</span><span class="p">,</span><span class="nv">$options</span><span class="p">);</span>
</span><span class='line'>                    <span class="nb">curl_multi_add_handle</span><span class="p">(</span><span class="nv">$master</span><span class="p">,</span> <span class="nv">$ch</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>                    <span class="c1">// Add to our request Maps</span>
</span><span class='line'>                    <span class="nv">$key</span> <span class="o">=</span> <span class="p">(</span><span class="nx">string</span><span class="p">)</span> <span class="nv">$ch</span><span class="p">;</span>
</span><span class='line'>                    <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requestMap</span><span class="p">[</span><span class="nv">$key</span><span class="p">]</span> <span class="o">=</span> <span class="nv">$i</span><span class="p">;</span>
</span><span class='line'>                    <span class="nv">$i</span><span class="o">++</span><span class="p">;</span>
</span><span class='line'>                <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>                <span class="c1">// remove the curl handle that just completed</span>
</span><span class='line'>                <span class="nb">curl_multi_remove_handle</span><span class="p">(</span><span class="nv">$master</span><span class="p">,</span> <span class="nv">$done</span><span class="p">[</span><span class="s1">&#39;handle&#39;</span><span class="p">]);</span>
</span><span class='line'>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>            <span class="c1">// Block for data in / output; error handling is done by curl_multi_exec</span>
</span><span class='line'>            <span class="k">if</span> <span class="p">(</span><span class="nv">$running</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>                <span class="nb">curl_multi_select</span><span class="p">(</span><span class="nv">$master</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">timeout</span><span class="p">);</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="p">}</span> <span class="k">while</span> <span class="p">(</span><span class="nv">$running</span><span class="p">);</span>
</span><span class='line'>        <span class="nb">curl_multi_close</span><span class="p">(</span><span class="nv">$master</span><span class="p">);</span>
</span><span class='line'>        <span class="k">return</span> <span class="k">true</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * Helper function to set up a new request by setting the appropriate options</span>
</span><span class='line'><span class="sd">     *</span>
</span><span class='line'><span class="sd">     * @access private</span>
</span><span class='line'><span class="sd">     * @param Request $request</span>
</span><span class='line'><span class="sd">     * @return array</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">private</span> <span class="k">function</span> <span class="nf">get_options</span><span class="p">(</span><span class="nv">$request</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="c1">// options for this entire curl object</span>
</span><span class='line'>        <span class="nv">$options</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">__get</span><span class="p">(</span><span class="s1">&#39;options&#39;</span><span class="p">);</span>
</span><span class='line'>        <span class="c1">// NOTE: The PHP cURL library won&#39;t follow redirects if either safe_mode is on</span>
</span><span class='line'>        <span class="c1">// or open_basedir is defined.</span>
</span><span class='line'>        <span class="c1">// See: https://bugs.php.net/bug.php?id=30609</span>
</span><span class='line'>      <span class="k">if</span> <span class="p">((</span> <span class="nb">ini_get</span><span class="p">(</span><span class="s1">&#39;safe_mode&#39;</span><span class="p">)</span> <span class="o">==</span> <span class="s1">&#39;Off&#39;</span> <span class="o">||</span> <span class="o">!</span><span class="nb">ini_get</span><span class="p">(</span><span class="s1">&#39;safe_mode&#39;</span><span class="p">)</span> <span class="p">)</span>
</span><span class='line'>            <span class="o">&amp;&amp;</span> <span class="nb">ini_get</span><span class="p">(</span><span class="s1">&#39;open_basedir&#39;</span><span class="p">)</span> <span class="o">==</span> <span class="s1">&#39;&#39;</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="nv">$options</span><span class="p">[</span><span class="nx">CURLOPT_FOLLOWLOCATION</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>          <span class="nv">$options</span><span class="p">[</span><span class="nx">CURLOPT_MAXREDIRS</span><span class="p">]</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>        <span class="nv">$headers</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">__get</span><span class="p">(</span><span class="s1">&#39;headers&#39;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>      <span class="c1">// append custom options for this specific request</span>
</span><span class='line'>      <span class="k">if</span> <span class="p">(</span><span class="nv">$request</span><span class="o">-&gt;</span><span class="na">options</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="nv">$options</span> <span class="o">=</span> <span class="nv">$request</span><span class="o">-&gt;</span><span class="na">options</span> <span class="o">+</span> <span class="nv">$options</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>      <span class="c1">// set the request URL</span>
</span><span class='line'>        <span class="nv">$options</span><span class="p">[</span><span class="nx">CURLOPT_URL</span><span class="p">]</span> <span class="o">=</span> <span class="nv">$request</span><span class="o">-&gt;</span><span class="na">url</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>        <span class="c1">// posting data w/ this request?</span>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="nv">$request</span><span class="o">-&gt;</span><span class="na">post_data</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="nv">$options</span><span class="p">[</span><span class="nx">CURLOPT_POST</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>            <span class="nv">$options</span><span class="p">[</span><span class="nx">CURLOPT_POSTFIELDS</span><span class="p">]</span> <span class="o">=</span> <span class="nv">$request</span><span class="o">-&gt;</span><span class="na">post_data</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="nv">$headers</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="nv">$options</span><span class="p">[</span><span class="nx">CURLOPT_HEADER</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'>            <span class="nv">$options</span><span class="p">[</span><span class="nx">CURLOPT_HTTPHEADER</span><span class="p">]</span> <span class="o">=</span> <span class="nv">$headers</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="c1">// Due to a bug in cURL CURLOPT_WRITEFUNCTION must be defined as the last option</span>
</span><span class='line'>        <span class="c1">// Otherwise it doesn&#39;t register. So let&#39;s unset and set it again</span>
</span><span class='line'>        <span class="c1">// See http://stackoverflow.com/questions/15937055/curl-writefunction-not-being-called</span>
</span><span class='line'>        <span class="k">if</span><span class="p">(</span> <span class="o">!</span> <span class="k">empty</span><span class="p">(</span> <span class="nv">$options</span><span class="p">[</span><span class="nx">CURLOPT_WRITEFUNCTION</span><span class="p">])</span> <span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="nv">$writeCallback</span> <span class="o">=</span> <span class="nv">$options</span><span class="p">[</span><span class="nx">CURLOPT_WRITEFUNCTION</span><span class="p">];</span>
</span><span class='line'>            <span class="nb">unset</span><span class="p">(</span> <span class="nv">$options</span><span class="p">[</span><span class="nx">CURLOPT_WRITEFUNCTION</span><span class="p">]</span> <span class="p">);</span>
</span><span class='line'>            <span class="nv">$options</span><span class="p">[</span><span class="nx">CURLOPT_WRITEFUNCTION</span><span class="p">]</span> <span class="o">=</span> <span class="nv">$writeCallback</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">return</span> <span class="nv">$options</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="sd">/**</span>
</span><span class='line'><span class="sd">     * @return void</span>
</span><span class='line'><span class="sd">     */</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">__destruct</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>        <span class="nb">unset</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">window_size</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">callback</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">options</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">headers</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">);</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p><strong><em>RollingCurlGroup.php</em></strong>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
<span class='line-number'>80</span>
<span class='line-number'>81</span>
<span class='line-number'>82</span>
<span class='line-number'>83</span>
<span class='line-number'>84</span>
<span class='line-number'>85</span>
<span class='line-number'>86</span>
<span class='line-number'>87</span>
<span class='line-number'>88</span>
<span class='line-number'>89</span>
<span class='line-number'>90</span>
<span class='line-number'>91</span>
<span class='line-number'>92</span>
<span class='line-number'>93</span>
<span class='line-number'>94</span>
<span class='line-number'>95</span>
<span class='line-number'>96</span>
<span class='line-number'>97</span>
<span class='line-number'>98</span>
<span class='line-number'>99</span>
<span class='line-number'>100</span>
<span class='line-number'>101</span>
<span class='line-number'>102</span>
<span class='line-number'>103</span>
<span class='line-number'>104</span>
<span class='line-number'>105</span>
<span class='line-number'>106</span>
<span class='line-number'>107</span>
<span class='line-number'>108</span>
<span class='line-number'>109</span>
<span class='line-number'>110</span>
<span class='line-number'>111</span>
<span class='line-number'>112</span>
<span class='line-number'>113</span>
<span class='line-number'>114</span>
<span class='line-number'>115</span>
<span class='line-number'>116</span>
<span class='line-number'>117</span>
<span class='line-number'>118</span>
<span class='line-number'>119</span>
<span class='line-number'>120</span>
<span class='line-number'>121</span>
<span class='line-number'>122</span>
<span class='line-number'>123</span>
<span class='line-number'>124</span>
<span class='line-number'>125</span>
<span class='line-number'>126</span>
<span class='line-number'>127</span>
<span class='line-number'>128</span>
<span class='line-number'>129</span>
<span class='line-number'>130</span>
<span class='line-number'>131</span>
<span class='line-number'>132</span>
<span class='line-number'>133</span>
<span class='line-number'>134</span>
<span class='line-number'>135</span>
<span class='line-number'>136</span>
<span class='line-number'>137</span>
<span class='line-number'>138</span>
<span class='line-number'>139</span>
<span class='line-number'>140</span>
<span class='line-number'>141</span>
<span class='line-number'>142</span>
<span class='line-number'>143</span>
<span class='line-number'>144</span>
<span class='line-number'>145</span>
<span class='line-number'>146</span>
<span class='line-number'>147</span>
<span class='line-number'>148</span>
<span class='line-number'>149</span>
<span class='line-number'>150</span>
<span class='line-number'>151</span>
<span class='line-number'>152</span>
<span class='line-number'>153</span>
<span class='line-number'>154</span>
<span class='line-number'>155</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="cm">/*</span>
</span><span class='line'>
</span><span class='line'><span class="cm">  Authored by Fabian Franz (www.lionsad.de)</span>
</span><span class='line'><span class="cm">  Released under Apache License 2.0</span>
</span><span class='line'>
</span><span class='line'><span class="cm">$Id$</span>
</span><span class='line'><span class="cm">*/</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">RollingCurlGroupException</span> <span class="k">extends</span> <span class="nx">Exception</span> <span class="p">{}</span>
</span><span class='line'>
</span><span class='line'><span class="k">abstract</span> <span class="k">class</span> <span class="nc">RollingCurlGroupRequest</span> <span class="k">extends</span> <span class="nx">RollingCurlRequest</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'>        <span class="k">private</span> <span class="nv">$group</span> <span class="o">=</span> <span class="k">null</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>  <span class="sd">/**</span>
</span><span class='line'><span class="sd">  * Set group for this request</span>
</span><span class='line'><span class="sd">  *</span>
</span><span class='line'><span class="sd">  * @param group The group to be set</span>
</span><span class='line'><span class="sd">  */</span>
</span><span class='line'>        <span class="k">function</span> <span class="nf">setGroup</span><span class="p">(</span><span class="nv">$group</span><span class="p">)</span>
</span><span class='line'>        <span class="p">{</span>
</span><span class='line'>                <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="p">(</span><span class="nv">$group</span> <span class="nx">instanceof</span> <span class="nx">RollingCurlGroup</span><span class="p">))</span>
</span><span class='line'>                        <span class="k">throw</span> <span class="k">new</span> <span class="nx">RollingCurlGroupException</span><span class="p">(</span><span class="s2">&quot;setGroup: group needs to be of instance RollingCurlGroup&quot;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>                <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">group</span> <span class="o">=</span> <span class="nv">$group</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="sd">/**</span>
</span><span class='line'><span class="sd">  * Process the request</span>
</span><span class='line'><span class="sd">  *</span>
</span><span class='line'><span class="sd">  *</span>
</span><span class='line'><span class="sd">  */</span>
</span><span class='line'>        <span class="k">function</span> <span class="nf">process</span><span class="p">(</span><span class="nv">$output</span><span class="p">,</span> <span class="nv">$info</span><span class="p">)</span>
</span><span class='line'>        <span class="p">{</span>
</span><span class='line'>                <span class="k">if</span> <span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">group</span><span class="p">)</span>
</span><span class='line'>                        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">group</span><span class="o">-&gt;</span><span class="na">process</span><span class="p">(</span><span class="nv">$output</span><span class="p">,</span> <span class="nv">$info</span><span class="p">,</span> <span class="nv">$this</span><span class="p">);</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="sd">/**</span>
</span><span class='line'><span class="sd">  * @return void</span>
</span><span class='line'><span class="sd">  */</span>
</span><span class='line'>  <span class="k">public</span> <span class="k">function</span> <span class="nf">__destruct</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>      <span class="nb">unset</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">group</span><span class="p">);</span>
</span><span class='line'>      <span class="k">parent</span><span class="o">::</span><span class="na">__destruct</span><span class="p">();</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">RollingCurlGroup</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'>        <span class="k">protected</span> <span class="nv">$name</span><span class="p">;</span>
</span><span class='line'>        <span class="k">protected</span> <span class="nv">$num_requests</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'>        <span class="k">protected</span> <span class="nv">$finished_requests</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'>        <span class="k">private</span> <span class="nv">$requests</span> <span class="o">=</span> <span class="k">array</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">function</span> <span class="nf">__construct</span><span class="p">(</span><span class="nv">$name</span><span class="p">)</span>
</span><span class='line'>        <span class="p">{</span>
</span><span class='line'>                <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">name</span> <span class="o">=</span> <span class="nv">$name</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="sd">/**</span>
</span><span class='line'><span class="sd">  * @return void</span>
</span><span class='line'><span class="sd">  */</span>
</span><span class='line'>  <span class="k">public</span> <span class="k">function</span> <span class="nf">__destruct</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>      <span class="nb">unset</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">name</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">num_requests</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">finished_requests</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">);</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>        <span class="k">function</span> <span class="nf">add</span><span class="p">(</span><span class="nv">$request</span><span class="p">)</span>
</span><span class='line'>        <span class="p">{</span>
</span><span class='line'>                <span class="k">if</span> <span class="p">(</span><span class="nv">$request</span> <span class="nx">instanceof</span> <span class="nx">RollingCurlGroupRequest</span><span class="p">)</span>
</span><span class='line'>                <span class="p">{</span>
</span><span class='line'>                        <span class="nv">$request</span><span class="o">-&gt;</span><span class="na">setGroup</span><span class="p">(</span><span class="nv">$this</span><span class="p">);</span>
</span><span class='line'>                        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">num_requests</span><span class="o">++</span><span class="p">;</span>
</span><span class='line'>                        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">[]</span> <span class="o">=</span> <span class="nv">$request</span><span class="p">;</span>
</span><span class='line'>                <span class="p">}</span>
</span><span class='line'>      <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nb">is_array</span><span class="p">(</span><span class="nv">$request</span><span class="p">))</span>
</span><span class='line'>                <span class="p">{</span>
</span><span class='line'>          <span class="k">foreach</span> <span class="p">(</span><span class="nv">$request</span> <span class="k">as</span> <span class="nv">$req</span><span class="p">)</span>
</span><span class='line'>              <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">add</span><span class="p">(</span><span class="nv">$req</span><span class="p">);</span>
</span><span class='line'>      <span class="p">}</span>
</span><span class='line'>                <span class="k">else</span>
</span><span class='line'>                        <span class="k">throw</span> <span class="k">new</span> <span class="nx">RollingCurlGroupException</span><span class="p">(</span><span class="s2">&quot;add: Request needs to be of instance RollingCurlGroupRequest&quot;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>      <span class="k">return</span> <span class="k">true</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">function</span> <span class="nf">addToRC</span><span class="p">(</span><span class="nv">$rc</span><span class="p">)</span>
</span><span class='line'>        <span class="p">{</span>
</span><span class='line'>      <span class="nv">$ret</span> <span class="o">=</span> <span class="k">true</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>                <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="p">(</span><span class="nv">$rc</span> <span class="nx">instanceof</span> <span class="nx">RollingCurl</span><span class="p">))</span>
</span><span class='line'>                        <span class="k">throw</span> <span class="k">new</span> <span class="nx">RollingCurlGroupException</span><span class="p">(</span><span class="s2">&quot;addToRC: RC needs to be of instance RollingCurl&quot;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>                <span class="k">while</span> <span class="p">(</span><span class="nb">count</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span>
</span><span class='line'>      <span class="p">{</span>
</span><span class='line'>          <span class="nv">$ret1</span> <span class="o">=</span> <span class="nv">$rc</span><span class="o">-&gt;</span><span class="na">add</span><span class="p">(</span><span class="nb">array_shift</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">));</span>
</span><span class='line'>          <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nv">$ret1</span><span class="p">)</span>
</span><span class='line'>              <span class="nv">$ret</span> <span class="o">=</span> <span class="k">false</span><span class="p">;</span>
</span><span class='line'>      <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>      <span class="k">return</span> <span class="nv">$ret</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">function</span> <span class="nf">process</span><span class="p">(</span><span class="nv">$output</span><span class="p">,</span> <span class="nv">$info</span><span class="p">,</span> <span class="nv">$request</span><span class="p">)</span>
</span><span class='line'>        <span class="p">{</span>
</span><span class='line'>                <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">finished_requests</span><span class="o">++</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>                <span class="k">if</span> <span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">finished_requests</span> <span class="o">&gt;=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">num_requests</span><span class="p">)</span>
</span><span class='line'>                        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">finished</span><span class="p">();</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">function</span> <span class="nf">finished</span><span class="p">()</span>
</span><span class='line'>        <span class="p">{</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">GroupRollingCurl</span> <span class="k">extends</span> <span class="nx">RollingCurl</span> <span class="p">{</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">private</span> <span class="nv">$group_callback</span> <span class="o">=</span> <span class="k">null</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">protected</span> <span class="k">function</span> <span class="nf">process</span><span class="p">(</span><span class="nv">$output</span><span class="p">,</span> <span class="nv">$info</span><span class="p">,</span> <span class="nv">$request</span><span class="p">)</span>
</span><span class='line'>  <span class="p">{</span>
</span><span class='line'>      <span class="k">if</span><span class="p">(</span> <span class="nv">$request</span> <span class="nx">instanceof</span> <span class="nx">RollingCurlGroupRequest</span><span class="p">)</span>
</span><span class='line'>          <span class="nv">$request</span><span class="o">-&gt;</span><span class="na">process</span><span class="p">(</span><span class="nv">$output</span><span class="p">,</span> <span class="nv">$info</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>      <span class="k">if</span> <span class="p">(</span><span class="nb">is_callable</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">group_callback</span><span class="p">))</span>
</span><span class='line'>          <span class="nb">call_user_func</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">group_callback</span><span class="p">,</span> <span class="nv">$output</span><span class="p">,</span> <span class="nv">$info</span><span class="p">,</span> <span class="nv">$request</span><span class="p">);</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">function</span> <span class="nf">__construct</span><span class="p">(</span><span class="nv">$callback</span> <span class="o">=</span> <span class="k">null</span><span class="p">)</span>
</span><span class='line'>  <span class="p">{</span>
</span><span class='line'>      <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">group_callback</span> <span class="o">=</span> <span class="nv">$callback</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>      <span class="k">parent</span><span class="o">::</span><span class="na">__construct</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="o">&amp;</span><span class="nv">$this</span><span class="p">,</span> <span class="s2">&quot;process&quot;</span><span class="p">));</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">public</span> <span class="k">function</span> <span class="nf">add</span><span class="p">(</span><span class="nv">$request</span><span class="p">)</span>
</span><span class='line'>  <span class="p">{</span>
</span><span class='line'>      <span class="k">if</span> <span class="p">(</span><span class="nv">$request</span> <span class="nx">instanceof</span> <span class="nx">RollingCurlGroup</span><span class="p">)</span>
</span><span class='line'>          <span class="k">return</span> <span class="nv">$request</span><span class="o">-&gt;</span><span class="na">addToRC</span><span class="p">(</span><span class="nv">$this</span><span class="p">);</span>
</span><span class='line'>      <span class="k">else</span>
</span><span class='line'>          <span class="k">return</span> <span class="k">parent</span><span class="o">::</span><span class="na">add</span><span class="p">(</span><span class="nv">$request</span><span class="p">);</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">public</span> <span class="k">function</span> <span class="nf">execute</span><span class="p">(</span><span class="nv">$window_size</span> <span class="o">=</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>
</span><span class='line'>      <span class="k">if</span> <span class="p">(</span><span class="nb">count</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">requests</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
</span><span class='line'>          <span class="k">return</span> <span class="k">false</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>      <span class="k">return</span> <span class="k">parent</span><span class="o">::</span><span class="na">execute</span><span class="p">(</span><span class="nv">$window_size</span><span class="p">);</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Fazendo a Mágica</h3>

<p>Agora que temos tudo, vamos criar uma página que faz esse processo para nós, no nosso caso, vamos transferir imagens de uma pasta para outra, mas poderíamos simplesmente chamar isso de um banco de dados, ou outro lugar.</p>

<p><strong><em>index.php</em></strong>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="k">require_once</span> <span class="s2">&quot;class/RollingCurl.php&quot;</span><span class="p">;</span>
</span><span class='line'><span class="nb">define</span> <span class="p">(</span><span class="s1">&#39;URLPREFIX&#39;</span><span class="p">,</span> <span class="s1">&#39;http://127.0.0.1/processaImagem/services/resize.php&#39;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="nv">$origin</span> <span class="o">=</span> <span class="nb">scandir</span><span class="p">(</span><span class="s1">&#39;image/origin&#39;</span><span class="p">);</span>
</span><span class='line'><span class="nv">$origin</span> <span class="o">=</span> <span class="nb">array_slice</span><span class="p">(</span><span class="nv">$origin</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="nb">count</span><span class="p">(</span><span class="nv">$origin</span><span class="p">));</span>
</span><span class='line'>
</span><span class='line'><span class="nv">$destination</span> <span class="o">=</span> <span class="nb">scandir</span><span class="p">(</span><span class="s1">&#39;image/destination&#39;</span><span class="p">);</span>
</span><span class='line'><span class="nv">$destination</span> <span class="o">=</span> <span class="nb">array_slice</span><span class="p">(</span><span class="nv">$destination</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="nb">count</span><span class="p">(</span><span class="nv">$destination</span><span class="p">));</span>
</span><span class='line'><span class="nv">$terms_list</span> <span class="o">=</span> <span class="nb">array_diff</span><span class="p">(</span><span class="nv">$origin</span><span class="p">,</span> <span class="nv">$destination</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="nv">$rc</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">RollingCurl</span><span class="p">();</span>
</span><span class='line'><span class="nv">$rc</span><span class="o">-&gt;</span><span class="na">window_size</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span> <span class="c1">// limit requests per batch</span>
</span><span class='line'><span class="k">foreach</span> <span class="p">(</span><span class="nv">$terms_list</span> <span class="k">as</span> <span class="nv">$terms</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="nv">$search_url</span> <span class="o">=</span> <span class="nx">URLPREFIX</span><span class="o">.</span><span class="s1">&#39;?file=&#39;</span><span class="o">.</span><span class="nb">urlencode</span><span class="p">(</span><span class="s2">&quot;../image/origin/&quot;</span><span class="o">.</span><span class="nv">$terms</span><span class="p">);</span>
</span><span class='line'>    <span class="nv">$request</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">RollingCurlRequest</span><span class="p">(</span><span class="nv">$search_url</span><span class="p">);</span>
</span><span class='line'>    <span class="nv">$rc</span><span class="o">-&gt;</span><span class="na">add</span><span class="p">(</span><span class="nv">$request</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="k">if</span><span class="p">(</span><span class="nv">$rc</span><span class="o">-&gt;</span><span class="na">execute</span><span class="p">()){</span>
</span><span class='line'>    <span class="k">foreach</span><span class="p">(</span><span class="nv">$rc</span><span class="o">-&gt;</span><span class="na">getReturns</span><span class="p">()</span> <span class="k">as</span> <span class="nv">$key</span> <span class="o">=&gt;</span> <span class="nv">$value</span><span class="p">){</span>
</span><span class='line'>        <span class="k">echo</span> <span class="nv">$value</span><span class="p">[</span><span class="s1">&#39;return&#39;</span><span class="p">]</span><span class="o">.</span> <span class="s1">&#39;&lt;br&gt;&#39;</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<h2>Notas finais</h2>

<p>As vezes nos deparamos com algumas limitações técnicas ou da propria linguagem, e pra resolvermos esses problemas, precisamos pensar fora da caxa. Existem diversas formas para realizarmos esse tipo de tarefa, mas dentro de uma limitação que tive, essa foi sem dúvida a melhor solução.
Solução no github <strong><a href="https://github.com/gustavobeavis/serviceResize">serviceResize</a></strong></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Hello World]]></title>
    <link href="http://gustavobeavis.github.io/blog/2014/02/03/hello-world/"/>
    <updated>2014-02-03T06:59:51-02:00</updated>
    <id>http://gustavobeavis.github.io/blog/2014/02/03/hello-world</id>
    <content type="html"><![CDATA[<p>Depois de alguns meses de tentativas e erros na configuração e instalação do octopress, finalmente comecei esse projeto de compartilhar um pouco do que aprendi e aprendo sobre desenvolvimento de sistemas, projetos, metodologias etestes.</p>

<p>Aqui vocês irão ver um pouco de tudo acerca de desenvolvimento de sistemas, principalmente sobre desenvolvimento web.</p>

<p>Aqui vocês não encontrarão nenhuna verdade absoluta, pois como dizia o slogan do Arquivo-X, &ldquo;A verdade está lá fora&rdquo;, portanto testem, estudem e tirem suas próprias conclusões.</p>

<p>Estou aberto a dúvidas, sugestões e críticas!</p>
]]></content>
  </entry>
  
</feed>
