Класс для загрузки файлов на сервер

Пример как использовать:
if (!empty($_FILES)) {
$tempFile = $_FILES['Filedata']['tmp_name'];
$targetPath = '/public/galery/';
$upload = new Upload(str_replace('//', '/', $targetPath));

if ($upload->uploads($_FILES['Filedata'])) {
$fileInfo = $upload->getFilesInfo();
$fileInfo["nameTranslit"];// новое имя файла, можно записать в БД
}
}

Ну и собственно сам класс
class Upload {

    private $dir = "/";
    private $name;
    private $FILES;
    private $allowedType = array("jpg", "gif", "bmp", "jpeg", "png", "pps","doc","docx","xls","pdf","txt","rar","zip");
    private $errors;
    private $errorsMessage = array(1 => "Размер загружаемого файла превышает допустимый размер.",
        2 => "Размер загружаемого файла превышает допустимый размер.",
        3 => "Файл был загружен лишь частично.",
        4 => "Файл не был загружен.",
        6 => "Файл не был загружен.",
        7 => "Файл не был загружен.",
        8 => "Файл не был загружен.");

    function __construct($dir="/") {
        $this->dir = $dir;
    }

    /**
     * устанавливаем дирректорию загрузки файла
     */
    function setDir() {
        $this->dir = $dir;
    }

    /**
     * Устанавлиаем доступные расширения
     * @param <type> $type
     */
    function setAllowedType($type) {
        if (is_array($type)) {
            $this->allowedType = $type;
        } else {
            $this->allowedType = explode(",", $type);
        }
    }

    /**
     * загрузка файла
     * @param $tmpName
     * @param $name
     * @param $replacement
     */
    private function upload($tmpName, $name) {
        $name = $this->substitute(self::translit($name));

        if ($this->typeChecking($name))
            if (move_uploaded_file($tmpName, $this->dir . $name)) {
                return $name;
            } else {
                return false;
            }
        return false;
    }

    function uploads($FILES) {
        $this->FILES = $FILES;

        if (!is_array($this->FILES['name'])) {
            return $this->uploadsOneFile();
        } else {
            return $this->uploadsManyFiles();
        }
    }

    /**
     * загрузка одного файла
     */
    function uploadsOneFile() {

        if ($this->FILES['error'] != 0) {
            $this->errors[] = $this->errorsMessage[$this->FILES['error']];
            return false;
        }

        $result = $this->upload($this->FILES['tmp_name'], $this->FILES['name']);
        if ($result != false) {
            $this->FILES['nameTranslit'] = $result;
            return true;
        }
        return false;
    }

    /**
     * загрузка нескольких файлов
     */
    function uploadsManyFiles() {
        $coutFiles = count($this->FILES['name']);
        for ($i = 0; $i < $coutFiles; $i++) {
            if ($this->FILES['error'][$i] == 0) {
                $result = $this->upload($this->FILES['tmp_name'][$i], $this->FILES['name'][$i]);

                if ($result != false) {
                    $this->FILES['nameTranslit'][$i] = $result;
                } else {
                    $this->errors[] = $this->FILES['name'];
                }
            } else {
                $this->errors[] = $this->errorsMessage[$this->FILES['error']];
            }
        }

        return true;
    }

    /**
     * проверяем, разрешен ли данный файл к загрузке
     */
    function typeChecking($fileName) {
        preg_match("#([\w()-_]+)\.([\w]{1,4})$#i", $fileName, $arrayNameFiles);
        $nameEnd = strtolower($arrayNameFiles[2]);
        if (in_array($nameEnd, $this->allowedType)) {
            return true;
        } else {
            $this->errors[] = "Файлы с расширением (<b>{$fileName}</b>) не разрешенны к загрузке.";
        }
        return false;
    }

    /**
     * ищет в каталоге файлы с таким же названием дописывает номер(равный количеству файлов с таким названием) в конец
     * @param $name
     */
    function substitute($name) {

        $files = scandir($this->dir);
        unset($files[0]);
        unset($files[1]);

        $i = 0;
        $newName = $name;

        preg_match("#([\w()-_]+)\.([\w]{1,4})#i", $name, $arrayNameFiles);
        $nameStart = $arrayNameFiles[1];
        $nameEnd = $arrayNameFiles[2];

        while (in_array($newName, $files)) {
            $newName = "{$nameStart}({$i}).{$nameEnd}";
            $i++;
        }
        return $newName;
    }

    /**
     * возвращаем информацию о файле
     */
    function getFilesInfo() {
        return $this->FILES;
    }

    /**
     * возвращаем ошибки
     */
    public function errors() {
        return $this->errors;
    }

    /**
     * переводим текст в транслит
     * @param $text
     */
    public static function translit($text) {
        $rus = array("а", "б", "в",
            "г", "ґ", "д", "е", "ё", "ж",
            "з", "и", "й", "к", "л", "м",
            "н", "о", "п", "р", "с", "т",
            "у", "ф", "х", "ц", "ч", "ш",
            "щ", "ы", "э", "ю", "я", "ь",
            "ъ", "і", "ї", "є", "А", "Б",
            "В", "Г", "ґ", "Д", "Е", "Ё",
            "Ж", "З", "И", "Й", "К", "Л",
            "М", "Н", "О", "П", "Р", "С",
            "Т", "У", "Ф", "Х", "Ц", "Ч",
            "Ш", "Щ", "Ы", "Э", "Ю", "Я",
            "Ь", "Ъ", "І", "Ї", "Є", " ");
        $lat = array("a", "b", "v",
            "g", "g", "d", "e", "e", "zh", "z", "i",
            "j", "k", "l", "m", "n", "o", "p", "r",
            "s", "t", "u", "f", "h", "c", "ch", "sh",
            "sh'", "y", "e", "yu", "ya", "_", "_", "i",
            "i", "e", "A", "B", "V", "G", "G", "D",
            "E", "E", "ZH", "Z", "I", "J", "K", "L",
            "M", "N", "O", "P", "R", "S", "T", "U",
            "F", "H", "C", "CH", "SH", "SH'", "Y", "E",
            "YU", "YA", "_", "_", "I", "I", "E", "_");
        $text = str_replace($rus, $lat, $text);
        return(preg_replace("#[^a-z0-9._-]#i", "", $text));
    }

}

HTML карта сайта на WordPress

Существует достаточно много плагинов, которые строят карту сайта HTML. Но, может быть, вы хотите добавить какие-то специфические особенности для карты вашего сайта. Например, включить или исключить определенные типы заметок и страниц, показать таксономию, и так далее. Поэтому будет полезно создать шаблон карты сайта в своей теме и использовать его.

В действительности, очень полезно использовать карту сайта HTML как часть темы. В таком случае карту сайта можно использовать и на странице WordPress для ошибки 404. Чтобы сделать карту сайта HTML частью темы надо создать папку partials в папке вашей темы. В папке partials создаем создаем файл с именем sitemap.php.

Копируем в него следующий код и правим его в соответствии со структурой своего сайта:
<h2 id="authors">Authors</h2>
<ul>
<?php 
wp_list_authors( 
  array(
    'exclude_admin' => false,
  )
); 
?>
</ul>
 
<h2 id="pages">Страницы</h2>
<ul>
<?php
// Страницы, которые надо исключить из карты сайта добавляем к exclude здесь
wp_list_pages( 
  array(
    'exclude' => '',
    'title_li' => '',
  )
);
?>
</ul>
 
<h2 id="posts">Заметки</h2>
<ul>
<?php
// Категории, которые надо исключить, добавляем к exclude здесь
$cats = get_categories('exclude=');
foreach ($cats as $cat) {
  echo "<li><h3>".$cat->cat_name."</h3>";
  echo "<ul>";
  query_posts('posts_per_page=-1&cat='.$cat->cat_ID);
  while(have_posts()) {
    the_post();
    $category = get_the_category();
    // Ссылку на заметку выводим только один раз, даже если она указана в нескольких категориях
    if ($category[0]->cat_ID == $cat->cat_ID) {
      echo '<li><a href="'.get_permalink().'">'.get_the_title().'</a></li>';
    }
  }
  echo "</ul>";
  echo "</li>";
}
?>
</ul>

Теперь там, где нужно вывести HTML карту сайта в теме WordPress вставляем следующий код:
<?php get_template_part('/partials/sitemap'); ?>



Чтобы сделать шаблон для карты сайта нужно скопировать файл page.php и переименовать копию в page-sitemap.php. Затем открываем его и ниже вызова функции the_content(); добавляем упомянутый ранее вызов get_template_part(). Теперь переходим в начало файла и после открывающего тега <?php (но перед вызовом get_header()), добавляем комментарий:
/*
Template Name: Карта сайта HTML
*/

Конвертация Movable Type 2 wordpress

Заходим в наш MT, в админку.
Копируем все что нада.
В вордпресе импортируем.
Но, не все просто ;)

Первое. Это проблема с конвертором. Весь текст в одну строку получается. Чтобы от этого избавиться вот:
Открываем установленный плагин. (не важно, даже самый обновленный официальный косячил)
wp-content/plugins/movabletype-importer/movabletype-importer.php
Ищем:
\n

Заменяем на:
\n \n


Еще. Символы не меняются. Были "-", стали "_". В названиях записей.
Это исправляется вот так:
SQL #
UPDATE `wp_posts` SET `post_name` = REPLACE(`post_name`, '-', '_');

thx keXek за это.

Еще возможно, понадобится людям почитать про markdown, кто его юзал.
оригинальный синтаксис daringfireball.net/projects/markdown/syntax
вот перевод если трудно вникать markdown.pp.ru/

Полезности по редиректам.
.htaccess
redirect.php in your WP root directory
<?php
require('wp-config.php');
header('Content-type: text/plain');
?>
<MTEntries lastn="999999">
Redirect Permanent /archives/<$MTEntryID$>.html http://www.example.org/archives/<$MTArchiveDate format="%Y/%m/%d"$>/
   <?php echo sanitize_title("<$MTEntryTitle$>"); ?>
</MTEntries>


If your entry IDs in MovableType are padded with zeroes (0), then change the line above to
Redirect Permanent /archives/<$MTEntryID pad="1"$>.html http://www.example.org/archives/<$MTArchiveDate format="%Y/%m/%d"$>/
   <?php echo sanitize_title("<$MTEntryTitle$>"); ?>


Also, if your used the «dirify» option, for example, when in MT, if you had:
  • Archive Type: Individual,
  • Archive File Template: .php,
    quotes in title etc,
  • Use:
    Redirect Permanent /archives/<MTEntryTitle dirify="1">.php 
     http://www.example.com/index.php?s=<$MTEntryTitle encode_url="1"$>
    or if the extension for the pages were ".html", instead of the ".php" above, use:
    Redirect Permanent /archives/<$MTEntryID$>.html 
     http://www.example.com/index.php?s=<$MTEntryTitle encode_url="1"$>
    .htaccess and mod_rewrite
    RewriteEngine on
    RewriteRule archives/0*(\d+).html /uri/to/blog/index.php?p=$1
    RewriteRule index.rdf /uri/to/blog/index.php?feed=rdf
    RewriteRule index.rss /uri/to/blog/index.php?feed=rss
    RewriteRule index.xml /uri/to/blog/index.php?feed=rss2

Загрузка файлов с помощью SWFUpload и PHP

Индексная
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
 
<head>
    <title>SWFUpload</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
    <h1>SWFUpload</h1>
    <div id="uploadButton"></div>
    <div id="status"></div>
    <div id="images"></div>
    <script type="text/javascript" src="js/jquery-1.4.2.min.js"></script>
    <script type="text/javascript" src="js/swfupload.js"></script>
    <script type="text/javascript" src="js/plugins/swfupload.queue.js"></script>
    <script type="text/javascript" src="js/main.js"></script>
</body>
</html>

uploadButton – предназначен для размещения кнопки загрузчика.
status – здесь мы будем выводить сообщения о процессе загрузки.
images – в этом блоке будут показаны загруженные картинки.

В конце страницы подключены 4 js файла.
  • Первый – библиотека jquery (ее использовать необязательно).
  • Второй – swfupload.js. Это основной скрипт библиотеки SWFUpload. Именно он создает кнопку загрузки.
  • Третий – plugins/swfupload.queue.js. Тоже входит в состав библиотеки. Позволяет загружать несколько файлов одновременно.
  • Четвертый – main.js. Здесь находится код настройки библиотеки и обработчики событий. Его мы сейчас и рассмотрим.
Настраиваем SWFUpload
Для того, чтобы подключить библиотеку, нужно создать объект SWFUpload и передать ему хеш с настройками.
Делается это следующим образом (код из файла main.js).
var swfu = new SWFUpload(
    {
        upload_url : "upload.php",
        flash_url : "swfupload.swf",
        button_placeholder_id : "uploadButton",
       
        file_size_limit : "2 MB",
        file_types : "*.jpg; *.png; *.jpeg; *.gif",
        file_types_description : "Images",
        file_upload_limit : "0",
        debug: false,
 
        button_image_url: "button.png",
        button_width : 100,
        button_height : 30,
        button_text_left_padding: 15,
        button_text_top_padding: 2,
        button_text : "<span class=\"uploadBtn\">Обзор…</span>",
        button_text_style : ".uploadBtn { font-size: 18px; font-family: Arial; background-color: #FF0000; }",
       
        file_dialog_complete_handler : fileDialogComplete,
        upload_success_handler : uploadSuccess,
        upload_complete_handler : uploadComplete,
        upload_start_handler : uploadStart,
        upload_progress_handler : uploadProgress
    }
);

В параметре upload_url мы указываем адрес php скрипта, который принимает файлы.

С помощью параметров flash_url и button_placeholder_id указываем адрес флеш ролика, который создаёт кнопку загрузки и id элемента на странице, в котором эта кнопка будет размещена.

Затем идет несколько параметров, устанавливающих ограничения на загрузку файлов. Здесь указаны допустимые разрешения файлов, их максимальный размер и количество файлов, которые можно загрузить за один раз (0 – любое количество).

После этого указываем параметры, настраивающие внешний вид кнопки загрузки. Эта часть обязательная, т.к. по-умолчанию кнопка имеет размер 1х1 пиксель, и пользоваться ей будет невозможно.

Т.к. кнопка представляет собой флеш ролик, оформить её напрямую с помощью CSS не получится, но с помощью этих параметров вы можете указать фоновую картинку, шрифт и положения текста.

Оставшиеся параметры устанавливают обработчики событий. Рассмотрим их подробнее.
function uploadSuccess(file, serverData) {
    $('#images').append($(serverData));
}
 
function uploadComplete(file) {
    $('#status').append($('<p>Загрузка ' + file.name + ' завершена</p>'));
}
 
function uploadStart(file) {
    $('#status').append($('<p>Начата загрузка файла ' + file.name + '</p>'));
    return true;
}
 
function uploadProgress(file, bytesLoaded, bytesTotal) {
    $('#status').append($('<p>Загружено ' + Math.round(bytesLoaded/bytesTotal*100) + '% файла ' + file.name + '</p>'));
}
 
function fileDialogComplete(numFilesSelected, numFilesQueued) {
    $('#status').html($('<p>Выбрано ' + numFilesSelected + ' файл(ов), начинаем загрузку</p>'));
    this.startUpload();
}

upload.php
<?php
 
$uploadDir = 'uploads/'; //папка для хранения файлов
 
$allowedExt = array('jpg', 'jpeg', 'png', 'gif');
$maxFileSize = 2 * 1024 * 1024; //1 MB
 
//если получен файл
if (isset($_FILES)) {
    //проверяем размер и тип файла
    $ext = end(explode('.', strtolower($_FILES['Filedata']['name'])));
    if (!in_array($ext, $allowedExt)) {
        return;
    }
    if ($maxFileSize < $_FILES['Filedata']['size']) {
        return;
    }
    if (is_uploaded_file($_FILES['Filedata']['tmp_name'])) {
        $fileName = $uploadDir.$_FILES['Filedata']['name'];
        //если файл с таким именем уже существует…
        if (file_exists($fileName)) {
            //…добавляем текущее время к имени файла
            $nameParts = explode('.', $_FILES['Filedata']['name']);
            $nameParts[count($nameParts)-2] .= time();
            $fileName = $uploadDir.implode('.', $nameParts);
        }
        move_uploaded_file($_FILES['Filedata']['tmp_name'], $fileName);
        echo '<img src="'.$fileName.'" alt="'.$fileName.'" />';
    }
}

AJAX загрузка файлов на сервер

Создадим папку там, где у нас установлен CodeIgniter, папка будет именоватся uploads, так же выставим ей права доступа 777. Затем создадим отображение в папке с видами, назвав файл upload.php:
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>AJAX загрузка файлов на сервер.</title>
    <script src="jquery.js"></script>
    <script src="jquery.ocupload-1.1.2.packed.js"></script>
    <script language="javascript">
    $(document).ready(function() {
      $('#upload').upload({
        name: 'userfile',
        method: 'post',
        enctype: 'multipart/form-data',
        action: 'upload/do_upload',
        onSubmit: function() {
          $('#result').text('Uploading...');
        },
        onComplete: function(data) {
          $('#result').text(data);
        }
    });
    });
    </script>
  </head>
  <body>
  <a id="upload" style="font-family: Verdana; color: #000" href="#">Выберите файл</a>
  <span id="result"></span>
  </body>
</html>

jQuery и One Click Upload, должны быть уже на вашем сервере. Файл отображения должен загружатся из основного контролёра например так:
function index() {
    $this->load->view('upload');
  }

Имя основного контролёра задаётся в конфиге routes.php, в строке $route['default_controller'].
После этого в папке с контролёрами создадим файл c таким же именем как и в папке с отображениями – upload.php:
<?php
class Upload extends Controller {
  
  function __construct() {
    parent::Controller();
    $this->load->helper(array('form', 'url'));
  }
  
  function index() {}

  function do_upload() {
    $config['upload_path'] = './uploads/';
    $config['allowed_types'] = 'gif|jpg|png';
    $config['max_size']  = '100';
    $config['max_width']  = '1280';
    $config['max_height']  = '1024';
    $config['remove_spaces']  = TRUE;
    $this->load->library('upload', $config);
    if (!$this->upload->do_upload()) {
      echo $this->upload->display_errors();
    }else {
      $data = $this->upload->data();
      echo "File name: $data[file_name]. File size: $data[file_size]";
    }
  }
  
}
?>

Код обоих фалов достаточно прост, о дополнительних настройках плагина и библиотеки, читайте на соответствующих ресурсах. Отмечу лишь, что в jQuery скрипте:
$(document).ready(function() {
  $('#upload').upload({
    name: 'userfile',
    method: 'post',
    enctype: 'multipart/form-data',
    action: 'upload/do_upload',
    onSubmit: function() {
      $('#result').text('Uploading...');
    },
    onComplete: function(data) {
      $('#result').text(data);
    }
  });
});

значение поля «name» можно установить своё, например «some_field», передав её в контролёре в качестве параметра функции do_upload:
$this->upload->do_upload('some_field')

Пример загрузки файлов на сервер (upload) на языке php

Код формы (upload.html)
<html>
<head>
  <title>Загрузка файлов на сервер</title>
</head>
<body>
      <h2><p><b> Форма для загрузки файлов </b></p></h2>
      <form action="upload.php" method="post" enctype="multipart/form-data">
      <input type="file" name="filename">
 
      <input type="submit" value="Загрузить">
      </form>
</body>
</html>

Код скрипта обработки формы (upload.php)
<html>
<head>
  <title>Результат загрузки файла</title>
</head>
<body>
<?php
   if($_FILES["filename"]["size"] > 1024*3*1024)
   {
     echo ("Размер файла превышает три мегабайта");
     exit;
   }
   if(copy($_FILES["filename"]["tmp_name"],
     "c:/temp/".$_FILES["filename"]["name"]))
   {
     echo("Файл успешно загружен 
");
     echo("Характеристики файла: 
");
     echo("Имя файла: ");
     echo($_FILES["filename"]["name"]);
     echo("
Размер файла: ");
     echo($_FILES["filename"]["size"]);
     echo("
Каталог для загрузки: ");
     echo($_FILES["filename"]["tmp_name"]);
     echo("
Тип файла: ");
     echo($_FILES["filename"]["type"]);
   } else {
      echo("Ошибка загрузки файла");
   }
?>

</body>
</html>

В некоторых случаях требуется ограничить размер файла, который может быть загружен на сервер. К примеру, чтобы разрешить загрузку на сервер только файлов с размером не более 3 Мбайт, в приведенном скрипте содержится код:
if($_FILES["filename"]["size"] > 1024*3*1024)
{
  echo("Размер файла превышает три мегабайта");
  exit;
}

Вставка фотогалерей PICASA с помощью jQuery

Скачать можно тута.
Посмотреть пример 1
Посмотреть пример 2
Посмотреть пример 3
Посмотреть пример 4

Первым делом как всегда необходимо подключить все внешние таблицы стилей и скрипты:
<script type="text/javascript" src="jquery-1.3.2.js"></script>
<link rel="stylesheet" href="css/slimbox2.css" type="text/css" media="screen" />
<script type="text/javascript" src="slimbox2.js"></script>
<script type="text/javascript" src="jquery.EmbedPicasaGallery.js"></script>


Первым делом идет фреймворк, далее таблица стилей лайтбокса, потом скрипт лайтбокса и скрипт нашей галереи.
После этого необходимо инициализировать нашу галерею (то есть придать ей настройки).
Это детальная настройка, которая по сути не особо нужна.
<script type="text/javascript">
  jQuery(document).ready(function() {
  jQuery("#images").EmbedPicasaGallery('СЮДА ПИШИТЕ ВАШ ЛОГИН в ГУГЛ',{
      matcher:            /./,         
      size:               '72',        // thumbnail size (32, 48, 64, 72, 144, 160)
      msg_loading_list :  'Loading album list from PicasaWeb',
      msg_back :          'Back',
      authkey :           'optional-picasa-authkey',
      albumid :           'go-directly-to-this-album-ignore-matcher'
      album_title_tag:    '<h2/>'
      thumb_id_prefix:    'pThumb_',
      loading_animation: 'css/loading.gif',
      thumb_finalizer:    function(){var $a = jQuery(this); ... use this to do something to the anchor AFTER slimbox got there },
      thumb_tuner:        function($div,entry,i){ ... $div - слой с миниатюрой, с информацией о фотке ...}
      link_mapper: function(el){  // see http://code.google.com/p/slimbox/wiki/jQueryAPI#The_linkMapper_function
            return [
                     el.href,
                     '<a href="'+el.href+'">'+el.title+'</a>'
                   ]
            }
   });
  });
</script>

Первое на что необходимо обратить внимание — жирный текст — сюда необходимо вписать Ваш логин в GOOGLE PICASA (и соответственно во всех других сервисах GOOGLE). Скрипт будет брать фотографии именно с этого аккаунта.

Теперь пойдем по списку:
  • matcher — важная настройка, так как она указывает на то, какие альбомы показывать, а какие нет. Оставьте /./ для отображения всех альбомов. Или допустим у Вас есть 10 альбомов с названием «Лучшие фото ...» (вместо ..., например, месяцы — Января, Февраля и т.д.), тогда можете вставить /Лучшие фото/ и только эти альбомы будут отображены. То есть скрипт ищет сходство в названии альбомов.
  • size — тут все понятно. Это размер миниатюр доступны — 32, 48, 64, 72, 144, 160
  • msg_loading_list — сообщение при загрузке списка альбомов
  • msb_back — надпись на кнопке «Назад»
  • authkey — опциональная настройка ключа авторизации в PICASA (можно не трогать)
  • albumid — тут можно указать id альбома без всяких названий в первой найстройке.

Минимумом настроек:
<script type="text/javascript">
jQuery(document).ready(function() {
jQuery("#images").EmbedPicasaGallery('404666ru',{ 
loading_animation: 'css/loading.gif',
matcher: /123456/
});
})
</script>


Выводить галерею необходимо так:
<div id="images"></div>

Класс прописывается тут — jQuery("#images")

Эффект при наведении с помощью jQuery

Посмотреть пример можно тут.
Скачать можно тут.

Для HTML структуры мы создадим элемент div с классом и id “hs_container”. Внутри мы разместим разные поля для изображений с разными картинками. У первой картинки будет класс “hs_visible”, который позволит ей отображаться поверх остальных.
<div id="hs_container" class="hs_container">
<div class="hs_area hs_area1">
<img class="hs_visible" src="images/area1/1.jpg" alt=""/>
<img src="images/area1/2.jpg" alt=""/>
<img src="images/area1/3.jpg" alt=""/>
</div>
<div class="hs_area hs_area2">
<img class="hs_visible" src="images/area2/1.jpg" alt=""/>
<img src="images/area2/2.jpg" alt=""/>
<img src="images/area2/3.jpg" alt=""/>
</div>
<div class="hs_area hs_area3">
<img class="hs_visible" src="images/area3/1.jpg" alt=""/>
<img src="images/area3/2.jpg" alt=""/>
<img src="images/area3/3.jpg" alt=""/>
</div>
<div class="hs_area hs_area4">
<img sclass="hs_visible" src="images/area4/1.jpg" alt=""/>
<img src="images/area4/2.jpg" alt=""/>
<img src="images/area4/3.jpg" alt=""/>
</div>
<div class="hs_area hs_area5">
<img class="hs_visible" src="images/area5/1.jpg" alt=""/>
<img src="images/area5/2.jpg" alt=""/>
<img src="images/area5/3.jpg" alt=""/>
</div>
</div>


CSS
В нашей таблице стилей мы определим площади и их уровни. Поскольку они будут абсолютно позиционированы, мы также присвоим им координаты (позицию). Начнем с главного контейнера:
.hs_container{
  position:relative;
  width:902px;
  height:471px;
  overflow:hidden;
  clear:both;
  border:2px solid #fff;
  cursor:pointer;
  -moz-box-shadow:1px 1px 3px #222;
  -webkit-box-shadow:1px 1px 3px #222;
  box-shadow:1px 1px 3px #222;
  }

Важно обязатльно указать overflow:hidden, так как мы не хотим чтобы выезжающие изображения показывались вне данного контейнера.

Каждая отдельная площадь будет также иметь overflow:hidden и абсолютное позиционирование:
.hs_container .hs_area{
  position:absolute;
  overflow:hidden;
  }

Мы позиционируем изображения внутри нашей площади и делаем их видимыми:
.hs_area img{
  position:absolute;
  top:0px;
  left:0px;
  display:none;
  }

Первое изображение будет видимым и поэтому мы ему придаем класс:
.hs_area img.hs_visible{
  display:block;
  z-index:9999;
  }

А теперь мы определим границы и позиции каждого поля:
.hs_area1{
  border-right:2px solid #fff;
  }
  .hs_area4, .hs_area5{
  border-top:2px solid #fff;
  }
  .hs_area4{
  border-right:2px solid #fff;
  }
  .hs_area3{
  border-top:2px solid #fff;
  }
  .hs_area1{
  width:449px;
  height:334px;
  top:0px;
  left:0px;
  }
  .hs_area2{
  width:451px;
  height:165px;
  top:0px;
  left:451px;
  }
  .hs_area3{
  width:451px;
  height:167px;
  top:165px;
  left:451px;
  }
  .hs_area4{
  width:192px;
  height:135px;
  top:334px;
  left:0px;
  }
  .hs_area5{
  width:708px;
  height:135px;
  top:334px;
  left:194px;
  }


JavaScript
Для эффекта смены слайдов мы будем использовать классный плагин jQuery Easing Plugin. Не забудьте его подключить вверху страницы.
Для начала давайте определим некоторые переменные.
//пользовательская анимация
  //смена слайдов
  var animations		= ['right','left','top','bottom','rightFade','leftFade','topFade','bottomFade'];
  var total_anim		= animations.length;
  //смените опции ниже на любую возможную из плагина easing 
  var easeType		= 'swing';
  //скорость смены
  var animSpeed		= 450;
  //кеширование
  var $hs_container	= $('#hs_container');
  var $hs_areas		= $hs_container.find('.hs_area');

Когда мы мышкой наводим на определенную площадь с изображением происходит одна из анимаций из нашего массива выше, и появляется следующая картинка. Мы будем использовать метку «over» для того, чтобы знать можем ли мы применять анимацию на определенной площади, так как мы не хотим ситуации, когда несколько анимаций будут происходит одновременно.

У нас будет сюжет для каждой анимации и мы четко определим ее поведение.
//для начала загрузить все изображения
  $hs_images          = $hs_container.find('img');
  var total_images    = $hs_images.length;
  var cnt             = 0;
  $hs_images.each(function(){
  var $this = $(this);
  $('<img>').load(function(){
  ++cnt;
  if(cnt == total_images){
  $hs_areas.each(function(){
  var $area 		= $(this);
  //Когда мышка переходит границу площади мы анимируем
  //изображение (случайная анимация из массива),
  //так, чтобы появилась следующая картинка.
  //"over" метка которая указывает на то, можем ли мы анимировать
  //площадь или нет
  $area.data('over',true).bind('mouseenter',function(){
  if($area.data('over')){
  $area.data('over',false);
  //Сколько изображений в этой площади?
  var total		= $area.children().length;
  //видимые изображения
  var $current 	= $area.find('img:visible');
  //индекс видимых изображений
  var idx_current = $current.index();
  //следующее изображение для показа
  var $next		= (idx_current == total-1) ? $area.children(':first') : $current.next();
  //показать следующее (пока еще не видимое)
  $next.show();
  //выбрать случайную анимацию
  var anim		= animations[Math.floor(Math.random()*total_anim)];
  switch(anim){
  //выезд справа
  case 'right':
  $current.animate({
  'left':$current.width()+'px'
  },
  animSpeed,
  easeType,
  function(){
  $current.hide().css({
  'z-index'	: '1',
  'left'		: '0px'
  });
  $next.css('z-index','9999');
  $area.data('over',true);
  });
  break;
  //теперь слева
  case 'left':
  $current.animate({
  'left':-$current.width()+'px'
  },
  animSpeed,
  easeType,
  function(){
  $current.hide().css({
  'z-index'	: '1',
  'left'		: '0px'
  });
  $next.css('z-index','9999');
  $area.data('over',true);
  });
  break;
  //...сверху
  case 'top':
  $current.animate({
  'top':-$current.height()+'px'
  },
  animSpeed,
  easeType,
  function(){
  $current.hide().css({
  'z-index'	: '1',
  'top'		: '0px'
  });
  $next.css('z-index','9999');
  $area.data('over',true);
  });
  break;
  //... снизу
  case 'bottom':
  $current.animate({
  'top':$current.height()+'px'
  },
  animSpeed,
  easeType,
  function(){
  $current.hide().css({
  'z-index'	: '1',
  'top'		: '0px'
  });
  $next.css('z-index','9999');
  $area.data('over',true);
  });
  break;
  //справа и расстворение
  case 'rightFade':
  $current.animate({
  'left':$current.width()+'px',
  'opacity':'0'
  },
  animSpeed,
  easeType,
  function(){
  $current.hide().css({
  'z-index'	: '1',
  'left'		: '0px',
  'opacity'	: '1'
  });
  $next.css('z-index','9999');
  $area.data('over',true);
  });
  break;
  //слева и расстворение
  case 'leftFade':
  $current.animate({
  'left':-$current.width()+'px','opacity':'0'
  },
  animSpeed,
  easeType,
  function(){
  $current.hide().css({
  'z-index'	: '1',
  'left'		: '0px',
  'opacity'	: '1'
  });
  $next.css('z-index','9999');
  $area.data('over',true);
  });
  break;
  //сверху и расстворение
  case 'topFade':
  $current.animate({
  'top':-$current.height()+'px',
  'opacity':'0'
  },
  animSpeed,
  easeType,
  function(){
  $current.hide().css({
  'z-index'	: '1',
  'top'		: '0px',
  'opacity'	: '1'
  });
  $next.css('z-index','9999');
  $area.data('over',true);
  });
  break;
  //снизу и расстворение
  case 'bottomFade':
  $current.animate({
  'top':$current.height()+'px',
  'opacity':'0'
  },
  animSpeed,
  easeType,
  function(){
  $current.hide().css({
  'z-index'	: '1',
  'top'		: '0px',
  'opacity'	: '1'
  });
  $next.css('z-index','9999');
  $area.data('over',true);
  });
  break;
  default:
  $current.animate({
  'left':-$current.width()+'px'
  },
  animSpeed,
  easeType,
  function(){
  $current.hide().css({
  'z-index'	: '1',
  'left'		: '0px'
  });
  $next.css('z-index','9999');
  $area.data('over',true);
  });
  break;
  }
  }
  });
  });
  //При нажатии в любом месте происходит смена на всех площадях
 
  $hs_container.bind('click',function(){
  $hs_areas.trigger('mouseenter');
  });
  }
  }).attr('src',$this.attr('src'));
  }); 

авто-рейтинг блогов в livestreet

Заметил, что за блог редко, кто голосует. Голосуют в основном за топики. Всем похуй и все такое.
Итак, чтобы сделать рейтинг блогов зависимым от оценок постов, опубликованных в этих блогах.
в Rating.class.php
Берем функцию
public function VoteTopic(UserEntity_User $oUser, TopicEntity_Topic $oTopic, $iValue)

которая обрабатывает голосование за посты
заменяем это:
/**
* Сохраняем силу и рейтинг
*/
$oUserTopic=$this->User_GetUserById($oTopic->getUserId());
$iSkillNew=$oUserTopic->getSkill()+$iValue*$iDelta;
$iSkillNew=($iSkillNew<0)? 0: $iSkillNew;
$oUserTopic->setSkill($iSkillNew);
$oUserTopic->setRating($oUserTopic->getRating()+$iValue*$iDelta/2.73);
$this->User_Update($oUserTopic);
return $iDeltaRating;

На это:
/**
* Сохраняем силу и рейтинг
*/
$oUserTopic=$this->User_GetUserById($oTopic->getUserId());
$iSkillNew=$oUserTopic->getSkill()+$iValue*$iDelta;
$iSkillNew=($iSkillNew<0)? 0: $iSkillNew;
$oUserTopic->setSkill($iSkillNew);
$oUserTopic->setRating($oUserTopic->getRating()+$iValue*$iDelta/2.73);
$this->User_Update($oUserTopic);

$oBlog=$this->Blog_GetBlogById($oTopic->getBlogId());
$oBlog->setRating($oBlog->getRating()+$iValue*$iDelta/2.73);
$this->Blog_UpdateBlog($oBlog);

return $iDeltaRating;

То есть добавляем в блог то же значение рейтинга, которое добавляется автору поста в репутацию. Работает и с персональными блогами.