title: Calculating when all rooms are busy
body: <p>Let's say we have two bookable rooms - <em>Room 1</em> and <em>Room 2</em>. The rooms arn't visible during booking, but are automatically distributed when the user books a room. We want to calculate which times both are booked at the same time. In other words - what time is no room available.</p>
  
  <p>The problem is when we add a third room - <em>Room 3</em> - it won't work anymore, as it only compares two rooms. How do I adjust (or completely replace) the logic so the number of rooms can be variable?</p>
  
  <p><strong>Input:</strong></p>
  
  <pre><code>&lt;?php
  $busy_rooms = array (
    'room_1' =&gt; 
    array (
      0 =&gt; 
      array (
        'from' =&gt; 
        DateTime::__set_state(array(
           'date' =&gt; '2017-10-02 11:00:00.000000',
           'timezone_type' =&gt; 1,
           'timezone' =&gt; '+02:00',
        )),
        'to' =&gt; 
        DateTime::__set_state(array(
           'date' =&gt; '2017-10-02 12:00:00.000000',
           'timezone_type' =&gt; 1,
           'timezone' =&gt; '+02:00',
        )),
      ),
    ),
    'room_2' =&gt; 
    array (
      0 =&gt; 
      array (
        'from' =&gt; 
        DateTime::__set_state(array(
           'date' =&gt; '2017-10-02 09:00:00.000000',
           'timezone_type' =&gt; 1,
           'timezone' =&gt; '+02:00',
        )),
        'to' =&gt; 
        DateTime::__set_state(array(
           'date' =&gt; '2017-10-02 16:00:00.000000',
           'timezone_type' =&gt; 1,
           'timezone' =&gt; '+02:00',
        )),
      )
    )
  );
  </code></pre>
  
  <p>In the example above, no room is available between 11:00-12:00 that particular day. The current logic seems to handle this correctly.</p>
  
  <p><strong>Current logic:</strong></p>
  
  <pre><code>&lt;?php
  $busy_times = array()
  
  foreach($busy_rooms as $a_id =&gt; $a_busy_times) {
      foreach($busy_rooms as $b_id =&gt; $b_busy_times) {
  
          // Never compare a room with itself
          if($b_id === $a_id) continue;
  
          foreach($a_busy_times as $a_busy) {
              foreach($b_busy_times as $b_busy) {
  
                  // B within A
                  //    |--B--|
                  // |-----A-----|
                  if($b_busy['from'] &gt;= $a_busy['from'] &amp;&amp; $b_busy['to'] &lt;= $a_busy['to']) {
                      $busy_times[] = array(
                          'from' =&gt; clone $b_busy['from'],
                          'to' =&gt; clone $b_busy['to']
                      );
                  }
  
                  // B-from within A, B-to after A
                  //    |--B--|
                  // |--A--|
                  elseif($b_busy['from'] &gt;= $a_busy['from'] &amp;&amp; $b_busy['to'] &gt;= $a_busy['to'] &amp;&amp; $b_busy['from'] &lt;= $a_busy['to']) {
                      $busy_times[] = array(
                          'from' =&gt; clone $b_busy['from'],
                          'to' =&gt; clone $a_busy['to']
                      );
                  }
  
                  // B-from before A, B-to within A
                  // |--B--|
                  //    |--A--|
                  elseif($b_busy['from'] &lt;= $a_busy['from'] &amp;&amp; $b_busy['to'] &lt;= $a_busy['to'] &amp;&amp; $b_busy['to'] &gt;= $a_busy['from']) {
                      $busy_times[] = array(
                          'from' =&gt; clone $b_busy['from'],
                          'to' =&gt; clone $a_busy['to']
                      );
                  }
              }
          }
      }
  }
  </code></pre>
  
  <p><strong>Output</strong> (contents of <code>$busy_times</code>):</p>
  
  <pre><code>&lt;?php
  array (
    array (
      'from' =&gt; 
      DateTime::__set_state(array(
         'date' =&gt; '2017-10-02 11:00:00.000000',
         'timezone_type' =&gt; 1,
         'timezone' =&gt; '+02:00',
      )),
      'to' =&gt; 
      DateTime::__set_state(array(
         'date' =&gt; '2017-10-02 12:00:00.000000',
         'timezone_type' =&gt; 1,
         'timezone' =&gt; '+02:00',
      )),
    )
  );
  </code></pre>