Changeset 1064 for trunk/admin/include


Ignore:
Timestamp:
Mar 5, 2006, 12:31:46 AM (18 years ago)
Author:
plg
Message:

new feature: source/destination links between categories. Will we keep this
feature? Code is complicated and very few people will understand how it
works...

modification: #images.storage_category_id replaced by
#image_category.is_storage

improvement: many code refactoring to improve readibility

improvement: virtual category creation code was moved to a dedicated
function in order to be called from admin/cat_list.php and
admin/cat_modify.php (create a new destination category)

Location:
trunk/admin/include
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/admin/include/functions.php

    r1060 r1064  
     1
    12<?php
    23// +-----------------------------------------------------------------------+
     
    153154  // destruction of all the related elements
    154155  $query = '
    155 SELECT id
    156   FROM '.IMAGES_TABLE.'
    157   WHERE storage_category_id IN (
    158 '.wordwrap(implode(', ', $ids), 80, "\n").')
     156SELECT image_id
     157  FROM '.IMAGE_CATEGORY_TABLE.'
     158  WHERE is_storage = \'true\'
     159    AND category_id IN ('.
     160    wordwrap(
     161      implode(', ', $ids),
     162      80,
     163      "\n"
     164      ).
     165    ')
    159166;';
    160167  $result = pwg_query($query);
     
    162169  while ($row = mysql_fetch_array($result))
    163170  {
    164     array_push($element_ids, $row['id']);
     171    array_push($element_ids, $row['image_id']);
    165172  }
    166173  delete_elements($element_ids);
     
    181188;';
    182189  pwg_query($query);
     190 
    183191  $query = '
    184192DELETE FROM '.GROUP_ACCESS_TABLE.'
     
    187195;';
    188196  pwg_query($query);
     197
     198  // source/destination links deletion
     199  $query = '
     200SELECT destination, source
     201  FROM '.CATEGORIES_LINK_TABLE.'
     202  WHERE source IN ('.implode(',', $ids).')
     203    OR destination IN ('.implode(',', $ids).')
     204;';
     205  $result = pwg_query($query);
     206
     207  $sources_of = array();
     208 
     209  while ($row = mysql_fetch_array($result))
     210  {
     211    if (!isset($sources_of[ $row['destination'] ]))
     212    {
     213      $sources_of[ $row['destination'] ] = array();
     214    }
     215
     216    array_push(
     217      $sources_of[ $row['destination'] ],
     218      $row['source']
     219      );
     220  }
     221
     222  foreach ($sources_of as $destination => $sources)
     223  {
     224    delete_sources($destination, $sources);
     225  }
     226
     227  update_category();
    189228
    190229  // destruction of the category
     
    396435       COUNT(image_id) AS nb_images,
    397436       MAX(date_available) AS date_last
    398   FROM '.IMAGES_TABLE.' INNER JOIN '.IMAGE_CATEGORY_TABLE.' ON id = image_id
     437  FROM '.IMAGES_TABLE.'
     438    INNER JOIN '.IMAGE_CATEGORY_TABLE.' ON id = image_id
    399439  WHERE category_id IN ('.wordwrap(implode(', ', $cat_ids), 80, "\n").')
    400440  GROUP BY category_id
     
    403443  $datas = array();
    404444  $query_ids = array();
    405   while ( $row = mysql_fetch_array( $result ) )
     445  while ($row = mysql_fetch_array($result))
    406446  {
    407447    array_push($query_ids, $row['category_id']);
    408     array_push($datas, array('id' => $row['category_id'],
    409                              'date_last' => $row['date_last'],
    410                              'nb_images' => $row['nb_images']));
     448   
     449    array_push(
     450      $datas,
     451      array(
     452        'id'        => $row['category_id'],
     453        'date_last' => $row['date_last'],
     454        'nb_images' => $row['nb_images']
     455        )
     456      );
    411457  }
    412458  // if all links between a category and elements have disappeared, no line
     
    414460  foreach (array_diff($cat_ids, $query_ids) as $id)
    415461  {
    416     array_push($datas, array('id' => $id, 'nb_images' => 0));
    417   }
    418 
    419   $fields = array('primary' => array('id'),
    420                   'update'  => array('date_last', 'nb_images'));
    421   mass_updates(CATEGORIES_TABLE, $fields, $datas);
     462    array_push(
     463      $datas,
     464      array(
     465        'id'        => $id,
     466        'nb_images' => 0,
     467        )
     468      );
     469  }
     470
     471  mass_updates(
     472    CATEGORIES_TABLE,
     473    array(
     474      'primary' => array('id'),
     475      'update'  => array('date_last', 'nb_images')
     476      ),
     477    $datas
     478    );
    422479
    423480  // representative pictures
     
    12921349function update_path()
    12931350{
    1294   $query = '
    1295 SELECT DISTINCT(storage_category_id)
    1296   FROM '.IMAGES_TABLE.'
    1297 ;';
    1298   $cat_ids = array_from_query($query, 'storage_category_id');
    1299   $fulldirs = get_fulldirs($cat_ids);
    1300 
    1301   foreach ($cat_ids as $cat_id)
     1351  $images_of = array();
     1352 
     1353  $query = '
     1354SELECT category_id, image_id
     1355  FROM '.IMAGE_CATEGORY_TABLE.'
     1356  WHERE is_storage = \'true\'
     1357;';
     1358  $result = pwg_query($query);
     1359  while ($row = mysql_fetch_array($result))
     1360  {
     1361    if (!isset($images_of[ $row['category_id'] ]))
     1362    {
     1363      $images_of[ $row['category_id'] ] = array();
     1364    }
     1365
     1366    array_push(
     1367      $images_of[ $row['category_id'] ],
     1368      $row['image_id']
     1369      );
     1370  }
     1371 
     1372  $fulldirs = get_fulldirs(
     1373    array_keys($images_of)
     1374    );
     1375
     1376  foreach ($images_of as $cat_id => $image_ids)
    13021377  {
    13031378    $query = '
    13041379UPDATE '.IMAGES_TABLE.'
    13051380  SET path = CONCAT(\''.$fulldirs[$cat_id].'\',\'/\',file)
    1306   WHERE storage_category_id = '.$cat_id.'
     1381  WHERE id IN ('.
     1382      wordwrap(
     1383        implode(', ', $image_ids),
     1384        80,
     1385        "\n").
     1386      ')
    13071387;';
    13081388    pwg_query($query);
     
    15231603    );
    15241604}
     1605
     1606/**
     1607 * Returns all destinations of a list of source categories. This function
     1608 * solves transitivity.
     1609 *
     1610 * @param mixed array of category ids, empty for all categories
     1611 */
     1612function get_destinations($categories = 'all')
     1613{
     1614  $query = '
     1615SELECT source, destination
     1616  FROM '.CATEGORIES_LINK_TABLE.'
     1617';
     1618  $result = pwg_query($query);
     1619
     1620  $destinations_of = array();
     1621 
     1622  while ($row = mysql_fetch_array($result))
     1623  {
     1624    if (!isset($destinations_of[ $row['source'] ]))
     1625    {
     1626      $destinations_of[ $row['source'] ] = array();
     1627    }
     1628
     1629    array_push(
     1630      $destinations_of[ $row['source'] ],
     1631      $row['destination']
     1632      );
     1633  }
     1634
     1635  // transitivity resolution: if " => " means "source of", if A=>B=>C
     1636  // implies A=>B and A=>C. So A has 2 destinations: B and C.
     1637  do
     1638  {
     1639    // let's suppose we only need a single turn
     1640    $need_new_turn = false;
     1641   
     1642    foreach ($destinations_of as $source => $destinations)
     1643    {
     1644      foreach ($destinations as $destination)
     1645      {
     1646        // does the current destination has destinations itself?
     1647        if (isset($destinations_of[$destination]))
     1648        {
     1649          // are there destinations of current destination not already among
     1650          // destinations of the current source? (advise: take a piece of
     1651          // paper and draw a schema). The source itself must not be counted
     1652          // as a destination, thus avoiding cyclic links.
     1653          $missing_destinations = array_diff(
     1654            $destinations_of[$destination],
     1655            $destinations,
     1656            array($source) // no cyclic link
     1657            );
     1658         
     1659          if (count($missing_destinations) > 0)
     1660          {
     1661            $destinations_of[$source] = array_unique(
     1662              array_merge(
     1663                $destinations,
     1664                $missing_destinations
     1665                )
     1666              );
     1667
     1668            // a category has a least one new destination, we have to check
     1669            // one more time that it doesn't generate more destinations
     1670            $need_new_turn = true;
     1671          }
     1672        }
     1673      }
     1674    }
     1675  } while ($need_new_turn);
     1676
     1677  if (is_array($categories))
     1678  {
     1679    $filtered_destinations_of = array();
     1680
     1681    // Even if there is no destinations for the requested categories, we
     1682    // return empty arrays
     1683    foreach ($categories as $category)
     1684    {
     1685      $filtered_destinations_of[$category] = array();
     1686    }
     1687   
     1688    foreach ($destinations_of as $source => $destinations)
     1689    {
     1690      if (in_array($source, $categories))
     1691      {
     1692        $filtered_destinations_of[$source] = $destinations;
     1693      }
     1694    }
     1695
     1696    return $filtered_destinations_of;
     1697  }
     1698  else
     1699  {
     1700    return $destinations_of;
     1701  }
     1702}
     1703
     1704/**
     1705 * Returns all sources of a list of destination categories. This function
     1706 * solves transitivity.
     1707 *
     1708 * @param mixed array of category ids, empty for all categories
     1709 */
     1710function get_sources($categories = 'all')
     1711{
     1712  $destinations_of = get_destinations();
     1713
     1714  $sources_of = array();
     1715 
     1716  foreach ($destinations_of as $source => $destinations)
     1717  {
     1718    foreach ($destinations as $destination)
     1719    {
     1720      if (!isset($sources_of[$destination]))
     1721      {
     1722        $sources_of[$destination] = array();
     1723      }
     1724
     1725      array_push($sources_of[$destination], $source);
     1726    }
     1727  }
     1728 
     1729  // eventually, filter
     1730  if (is_array($categories))
     1731  {
     1732    $filtered_sources_of = array();
     1733
     1734    // Even if there is no sources for the requested categories, we return
     1735    // empty arrays
     1736    foreach ($categories as $category)
     1737    {
     1738      $filtered_sources_of[$category] = array();
     1739    }
     1740   
     1741    foreach ($sources_of as $destination => $sources)
     1742    {
     1743      if (in_array($destination, $categories))
     1744      {
     1745        $filtered_sources_of[$destination] = $sources;
     1746      }
     1747    }
     1748
     1749    return $filtered_sources_of;
     1750  }
     1751  else
     1752  {
     1753    return $sources_of;
     1754  }
     1755}
     1756
     1757/**
     1758 * Checks categories links are respected for a given list of destinations.
     1759 *
     1760 * Checking categories links means that each destination must be associated
     1761 * to the images of its sources.
     1762 *
     1763 * @param mixed source category ids
     1764 */
     1765function check_links($destinations = 'all')
     1766{
     1767  $sources_of = get_sources($destinations);
     1768
     1769  if (empty($sources_of))
     1770  {
     1771    return true;
     1772  }
     1773
     1774  // we need to search images of all sources and destinations
     1775  $images_of = array();
     1776
     1777  foreach ($sources_of as $destination => $sources)
     1778  {
     1779    $images_of[$destination] = array();
     1780
     1781    foreach ($sources as $source)
     1782    {
     1783      $images_of[$source] = array();
     1784    }
     1785  }
     1786 
     1787  $query = '
     1788SELECT image_id, category_id
     1789  FROM '.IMAGE_CATEGORY_TABLE.'
     1790  WHERE category_id IN ('.
     1791    implode(',', array_keys($images_of)).
     1792    ')
     1793;';
     1794  $result = pwg_query($query);
     1795
     1796  while ($row = mysql_fetch_array($result))
     1797  {
     1798    array_push(
     1799      $images_of[ $row['category_id'] ],
     1800      $row['image_id']
     1801      );
     1802  }
     1803
     1804  $inserts = array();
     1805 
     1806  foreach ($sources_of as $destination => $sources)
     1807  {
     1808    // merge all images from the sources of this destination
     1809    $sources_images = array();
     1810   
     1811    foreach ($sources as $source)
     1812    {
     1813      $sources_images = array_merge(
     1814        $sources_images,
     1815        $images_of[$source]
     1816        );
     1817    }
     1818
     1819    $sources_images = array_unique($sources_images);
     1820
     1821    // are there images among the sources that are not linked to the
     1822    // destination?
     1823    $missing_images = array_diff(
     1824      $sources_images,
     1825      $images_of[$destination]
     1826      );
     1827
     1828    // if we find missing images (missing links in reality), we prepare the
     1829    // final mass_inserts
     1830    if (count($missing_images) > 0)
     1831    {
     1832      foreach ($missing_images as $missing_image)
     1833      {
     1834        array_push(
     1835          $inserts,
     1836          array(
     1837            'category_id' => $destination,
     1838            'image_id'    => $missing_image,
     1839            )
     1840          );
     1841      }
     1842    }
     1843  }
     1844
     1845  if (count($inserts) > 0)
     1846  {
     1847    mass_inserts(
     1848      IMAGE_CATEGORY_TABLE,
     1849      array_keys($inserts[0]),
     1850      $inserts
     1851      );
     1852  }
     1853}
     1854
     1855/**
     1856 * Based on categories links, delete image_category links on destinations.
     1857 *
     1858 * The rule is the following: if an image belong to the category and to the
     1859 * source, we suppose it comes from the source. If the source/destination
     1860 * link is broken, we delete the image/category link if the only origin of
     1861 * the link was the broken categories link.
     1862 *
     1863 * Example: "=>" means "source of". Between brackets the associated images.
     1864 *
     1865 * A (1,2,9) => \
     1866 *               |=> C (1,2,3,4,5,9) => D (1,2,3,4,5,6,9)
     1867 * B (3,4,9) => /
     1868 *
     1869 * In category C, we suppose (1,2) come from A, (3,4) from B, 9 from A or B
     1870 * and 5 was manually added. In category D, 6 was added manually.
     1871 *
     1872 * If we break A=>C, C and D loose (1,2) but not 9 because it can come from
     1873 * B. If we break C=>D, D loose (3,4,5,9) but not 6 because it was
     1874 * associated manually to 9.
     1875 *
     1876 * Warning: only virtual links can be removed, physical links are protected.
     1877 *
     1878 * @param int destination
     1879 * @param array sources
     1880 */
     1881function delete_sources($destination, $sources)
     1882{
     1883  // if no sources to unlink, we stop with OK status
     1884  if (count($sources) == 0)
     1885  {
     1886    return true;
     1887  }
     1888
     1889  $query = '
     1890DELETE
     1891  FROM '.CATEGORIES_LINK_TABLE.'
     1892  WHERE destination = '.$destination.'
     1893    AND source IN ('.implode(',', $sources).')
     1894;';
     1895  pwg_query($query);
     1896 
     1897  // The strategy is the following:
     1898  //
     1899  // * first we brutally delete the image/category associations on
     1900  // destinations categories for all images belonging to sources.
     1901  //
     1902  // * then we check_links on destinations to rebuild missing image/category
     1903  // associations.
     1904
     1905  // what are the images associated to the sources to unlink
     1906  $query = '
     1907SELECT image_id
     1908  FROM '.IMAGE_CATEGORY_TABLE.'
     1909  WHERE category_id IN ('.
     1910    implode(',', $sources).
     1911    ')
     1912;';
     1913  $sources_images = array_unique(
     1914    array_from_query($query, 'image_id')
     1915    );
     1916
     1917  if (count($sources_images) == 0)
     1918  {
     1919    return true;
     1920  }
     1921
     1922  // retrieve all direct and indirect destinations of the current
     1923  // destination
     1924  $destinations_of = get_destinations(array($destination));
     1925
     1926  $destinations = array_merge(
     1927    array($destination),
     1928    $destinations_of[$destination]
     1929    );
     1930 
     1931  // unlink sources images from destinations
     1932  $query = '
     1933DELETE
     1934  FROM '.IMAGE_CATEGORY_TABLE.'
     1935  WHERE category_id IN ('.implode(',', $destinations).')
     1936    AND image_id IN ('.implode(',', $sources_images).')
     1937    AND is_storage = \'false\'
     1938;';
     1939  pwg_query($query);
     1940
     1941  // if the representative thumbnail of destinations was a picture from
     1942  // $sources_images, we request a new random representant
     1943  $query = '
     1944SELECT id, representative_picture_id
     1945  FROM '.CATEGORIES_TABLE.'
     1946  WHERE id IN ('.implode(',', $destinations).')
     1947;';
     1948  $result = pwg_query($query);
     1949
     1950  $request_random = array();
     1951 
     1952  while ($row = mysql_fetch_array($result))
     1953  {
     1954    if (isset($row['representative_picture_id']))
     1955    {
     1956      if (in_array($row['representative_picture_id'], $sources_images))
     1957      {
     1958        array_push($request_random, $row['id']);
     1959      }
     1960    }
     1961  }
     1962
     1963  set_random_representant($request_random);
     1964
     1965  // eventually, we check_links to rebuild missing associations
     1966  check_links($destinations);
     1967
     1968  return true;
     1969}
     1970
     1971/**
     1972 * create a virtual category
     1973 *
     1974 * @param string category name
     1975 * @param int parent category id
     1976 * @return array with ('info' and 'id') or ('error') key
     1977 */
     1978function create_virtual_category($category_name, $parent_id=null)
     1979{
     1980  global $conf;
     1981 
     1982  // is the given category name only containing blank spaces ?
     1983  if (preg_match('/^\s*$/', $category_name))
     1984  {
     1985    return array('error' => l10n('cat_error_name'));
     1986  }
     1987       
     1988  $parent_id = !empty($parent_id) ? $parent_id : 'NULL';
     1989
     1990  $query = '
     1991SELECT MAX(rank)
     1992  FROM '.CATEGORIES_TABLE.'
     1993  WHERE id_uppercat '.(is_numeric($parent_id) ? '= '.$parent_id : 'IS NULL').'
     1994;';
     1995  list($current_rank) = mysql_fetch_array(pwg_query($query));
     1996 
     1997  $insert = array(
     1998    'name' => $category_name,
     1999    'rank' => ++$current_rank,
     2000    'commentable' => $conf['newcat_default_commentable'],
     2001    'uploadable' => 'false',
     2002    );
     2003   
     2004  if ($parent_id != 'NULL')
     2005  {
     2006    $query = '
     2007SELECT id, uppercats, global_rank, visible, status
     2008  FROM '.CATEGORIES_TABLE.'
     2009  WHERE id = '.$parent_id.'
     2010;';
     2011    $parent = mysql_fetch_array(pwg_query($query));
     2012
     2013    $insert{'id_uppercat'} = $parent{'id'};
     2014    $insert{'global_rank'} = $parent{'global_rank'}.'.'.$insert{'rank'};
     2015   
     2016    // at creation, must a category be visible or not ? Warning : if the
     2017    // parent category is invisible, the category is automatically create
     2018    // invisible. (invisible = locked)
     2019    if ('false' == $parent['visible'])
     2020    {
     2021      $insert{'visible'} = 'false';
     2022    }
     2023    else
     2024    {
     2025      $insert{'visible'} = $conf['newcat_default_visible'];
     2026    }
     2027   
     2028    // at creation, must a category be public or private ? Warning : if the
     2029    // parent category is private, the category is automatically create
     2030    // private.
     2031    if ('private' == $parent['status'])
     2032    {
     2033      $insert{'status'} = 'private';
     2034    }
     2035    else
     2036    {
     2037      $insert{'status'} = $conf['newcat_default_status'];
     2038    }
     2039  }
     2040  else
     2041  {
     2042    $insert{'visible'} = $conf['newcat_default_visible'];
     2043    $insert{'status'} = $conf['newcat_default_status'];
     2044    $insert{'global_rank'} = $insert{'rank'};
     2045  }
     2046
     2047  // we have then to add the virtual category
     2048  mass_inserts(
     2049    CATEGORIES_TABLE,
     2050    array(
     2051      'site_id', 'name', 'id_uppercat', 'rank', 'commentable',
     2052      'uploadable', 'visible', 'status', 'global_rank',
     2053      ),
     2054    array($insert)
     2055    );
     2056
     2057  $inserted_id = mysql_insert_id();
     2058
     2059  $query = '
     2060UPDATE
     2061  '.CATEGORIES_TABLE.'
     2062  SET uppercats = \''.
     2063    (isset($parent) ? $parent{'uppercats'}.',' : '').
     2064    $inserted_id.
     2065    '\'
     2066  WHERE id = '.$inserted_id.'
     2067;';
     2068  pwg_query($query);
     2069 
     2070  return array(
     2071    'info' => l10n('cat_virtual_added'),
     2072    'id'   => $inserted_id,
     2073    );
     2074}
    15252075?>
  • trunk/admin/include/functions_metadata.php

    r1029 r1064  
    225225SELECT id, path
    226226  FROM '.IMAGES_TABLE.'
    227   WHERE storage_category_id IN ('.implode(',', $cat_ids).')';
     227    INNER JOIN '.IMAGE_CATEGORY_TABLE.' ON image_id = id
     228  WHERE is_storage = \'true\'
     229    AND category_id IN ('.implode(',', $cat_ids).')';
    228230  if ($only_new)
    229231  {
Note: See TracChangeset for help on using the changeset viewer.