Sites Dinâmicos

Sites dinâmicos são sites gerenciáveis por sistemas de CMS (Content Management System), através de uma plataforma online, que é acessada por login e senha, é possível manipular todo o conteúdo gerenciável do Mais »

Modelagem 3D

Se sua empresa precisa de ilustrações em 3D, venha falar com a Toca Digital e conheça o nosso trabalho. A modelagem 3D (modelagem tridimensional)  é o processo de desenvolvimento de uma representação Mais »

Ganhe tempo na construção de seu site

  Não perca seu tempo com empresas que vão deixar você na mão, montamos seu site com os melhores recursos da internet, ferramentas de gereciamento de conteúdo e de controle estatístico. Com Mais »

 

Como construir um sistema de busca a partir de páginas indexadas com o Zend_Search_Lucene

Estou começando a me acostumar a trabalhar com um Zend Framework v. 1.12 (ZF1), apesar dele já estar na versão 2, eu adotei essa versão por ter um colega de trabalho que já está mais habituado a trabalhar com ele, e está me ajudando a conhecê-lo melhor, além disso estou mais familiarizado a trabalhar com MVC  (Model View Controller), a ter que encarar, até então para mim, esta novidade do tal MVP  (Model View Presenter).

E nesta altura do campeonato, eis que me apareceu uma de suas facilidades, quanto a construção de um Search Engine. Como eu não pretendia utilizar banco de dados para fazer requisições de busca, eu resolvi utilizar algo que possa fazer uma busca básica em páginas estáticas. Daí me veio a questão de como eu poderia fazer isso, e pesquisando a fundo, descobri que existem alguns meios, você pode tanto usar SOLR ( http://lucene.apache.org/solr/ ) como o Zend_Search_Lucene, que já vem embutido na biblioteca do ZF1. Se quiser se aventurar na documentação, acesse por aqui: http://framework.zend.com/manual/1.12/en/zend.search.lucene.html.

Como eu já perdi horas quebrando a cabeça, nesta indexação resolvi publicar aqui minhas soluções, depois de ter  lido, relido, acessado vários fóruns, tirado várias dúvidas e ainda as tenho…, mas enfim, segue aqui até onde eu consegui avançar:

Primeiramente o Model de Indexação:

<?php
class Application_Model_IndexarPaginas {

    private $public_dir_indice = null;
    public $senhaToken;

    /**
     * @uses : O construtor apenas irá definir a senha que será tratada com um rash para que você possa indexar a página via URL de forma segura (se isso existe????).
     */
    public function __construct() {
        $this->public_dir_indice = preg_replace('/application/', '', realpath(APPLICATION_PATH)) . 'public' . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'indice';
        $this->public_dir_indice = is_dir($this->public_dir_indice) ? $this->public_dir_indice : false;

        $this->senhaToken = 'suasenha123'; //(Rash será em MD5) : bf8258ed5359f080693cd11365543ac3
        //composite pattern
    }
    /**
     * @return type array
     * @uses : use este método para iniciar o sistema de indexação de páginas
     */
    public function indexarTodas() {
        // (esse processo é obrigatório, antes de qualquer outro processo deste mesmo modelo: IndexarPaginas)
        return $this->indexarPaginas('insertall');
    }
/**
 *
 * @param type array $content
 * @return type array
 * @uses : use este método para incluir apenas uma página
 * na sua lista pré-existente (execute o método acima antes de utilizar este a baixo)
 * observe: $content se trata de uma lista array dos campos que serão gravados na indexação
 */
    public function indexarUmaPagina(array $content) {
        return $this->indexarPaginas('insert', $content);
    }

    /**
     *
     * @param type string $string
     * @return type string
     * @uses : use para remover acentos
     */
    private function removeAcentuacao($string) {
        $acentos = array("À", "Á", "Â", "Ã", "Ä", "Å", "à", "á", "â", "ã", "ä", "å", "Ò", "Ó", "Ô", "Õ", "Ö", "Ø", "ò", "ó", "ô", "õ", "ö", "ø", "È", "É", "Ê", "Ë", "è", "é", "ê", "ë", "Ç", "ç", "Ì", "Í", "Î", "Ï", "ì", "í", "î", "ï", "Ù", "Ú", "Û", "Ü", "ù", "ú", "û", "ü", "ÿ", "Ñ", "ñ", "á", "à", "â", "ã", "é", "è", "ê", "í", "ì", "î", "ó", "ò", "ô", "õ", "ú", "ù", "ü", "û", "ç", "º", "ª", " ");
        $sem_acentos = array("a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "o", "o", "o", "o", "o", "o", "o", "o", "o", "o", "o", "o", "e", "e", "e", "e", "e", "e", "e", "e", "c", "c", "i", "i", "i", "i", "i", "i", "i", "i", "u", "u", "u", "u", "u", "u", "u", "u", "y", "n", "n", "a", "a", "a", "a", "e", "e", "e", "i", "i", "i", "o", "o", "o", "o", "u", "u", "u", "u", "c", "o", "a", " ");
        $string = str_replace($acentos, $sem_acentos, $string);
        return strtolower($string);
    }

    /**
     *
     * @param type string $string
     * @param type string $slug
     * @return type string $string
     * @uses : permite eliminar acentos, e separar espaços, traços, ou qualquer coisa para a variável $slug
     */
    public function slugUrl($string, $slug = ' ') {
        $string = $this->removeAcentuacao($string);
        $string = strtolower($string);
        if ($slug) {
            $string = preg_replace('/[^a-z0-9]/i', $slug, $string);
            $string = preg_replace('/' . $slug . '{2,}/i', $slug, $string);
            $string = trim($string, $slug);
        }
        return $string;
    }

    /**
     * @param type string $param = sua senha
     * @return boolean
     * @uses : use este método para validar a senha no formulário
     */
    public function checkToken($param) {
        if (md5($param) == md5($this->senhaToken)) {
            return true;
        } else
            return false;
    }

    /**
     *
     * @param type (string || int) $id
     * @return array
     * @uses : o Zend_lucene não é muito inteligente na questão de deletar ou atualizar registros,
     * então, toda vez que vc for apagar ou atualizar um registro, você terá que reindexar tudo de novo...
     * No caso abaixo, ele está deletando um registro a partir da ID do conteúdo que você tem indexado.
     */
    public function deletarIndice($id) {
        $parseQuery = "articleId:$id";
        $query = Zend_Search_Lucene_Search_QueryParser::parse($parseQuery);
        $index = Zend_Search_Lucene::open($this->public_dir_indice);
        Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding('utf-8');
        Zend_Search_Lucene_Analysis_Analyzer::setDefault(new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8_CaseInsensitive());
        $results = $index->find($query);

        $msg = array();
        $titulo = '';
        $url = '';
        $count = 0;
        foreach ($results as $result) {

            $doc = new Zend_Search_Lucene_Document();
            $idDeleted = $result->articleId;
            $index->delete($idDeleted);
            $doc->addField(Zend_Search_Lucene_Field::text('url', $result->url, 'utf-8'));
            $doc->addField(Zend_Search_Lucene_Field::keyword('articleId', $result->articleId, 'utf-8'));
            $doc->addField(Zend_Search_Lucene_Field::text('postedDateTime', $result->postedDateTime, 'utf-8'));
            $doc->addField(Zend_Search_Lucene_Field::keyword('permission', '0'));
            $doc->addField(Zend_Search_Lucene_Field::text('title', $result->title, 'utf-8'));
            $doc->addField(Zend_Search_Lucene_Field::text('title_accent', $result->title_accent, 'utf-8'));
            $doc->addField(Zend_Search_Lucene_Field::text('contents', $result->contents, 'utf-8'));
            $doc->addField(Zend_Search_Lucene_Field::text('category', $result->category, 'utf-8'));
            $count++;
            $index->addDocument($doc);
        }

        $idDeleted = $result->articleId;
        $titulo = $result->title;
        $url = $result->url;
        $index->commit();
        if ($index->isDeleted($idDeleted)) {
            $msg["msg"] = "Página excluída com sucesso!";
            $msg["id"] = $idDeleted;
            $msg["success"] = true;
        }

        return $msg;
    }

    /**
     *
     * @param array $articlesData
     * @return array $msg
     * @uses : este método é que fará a mágica da criação dos índices
     *
     */
    public function criarConteudoIndice(array $articlesData) {

        $msg = array();
        $count = 0;
        if (is_array($articlesData) && count($articlesData)) {
            $index = Zend_Search_Lucene::create($this->public_dir_indice);
            Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding('utf-8');
            Zend_Search_Lucene_Analysis_Analyzer::setDefault(new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8_CaseInsensitive());

            foreach ($articlesData as $articleData) {
                $doc = new Zend_Search_Lucene_Document();
                $doc->addField(Zend_Search_Lucene_Field::text('url', $articleData["url"], 'utf-8'));
                $doc->addField(Zend_Search_Lucene_Field::keyword('articleId', $articleData["articleId"], 'utf-8'));
                $doc->addField(Zend_Search_Lucene_Field::text('postedDateTime', $articleData["postedDateTime"], 'utf-8'));
                $doc->addField(Zend_Search_Lucene_Field::keyword('permission', '1'));
                $doc->addField(Zend_Search_Lucene_Field::text('title', $articleData["title"], 'utf-8'));
                $doc->addField(Zend_Search_Lucene_Field::text('title_accent', $articleData["title_accent"], 'utf-8'));
                $doc->addField(Zend_Search_Lucene_Field::text('contents', $articleData["contents"], 'utf-8'));
                $doc->addField(Zend_Search_Lucene_Field::text('category', $articleData["category"], 'utf-8'));

                $msg[$count]["saida"] = "Página adicionada: " . $articleData["articleId"] . " - " . $articleData["title"] . " - URL: " . $articleData["url"];
                $count++;
                $index->addDocument($doc);
            }

            $index->commit();
            $index->optimize();
            return $msg;
        }
    }

    public function atualizarConteudoIndice($params, $acao = 'update') {
        $data = $this->searchContent($params['id'], "articleId", null);

        $data_pub = ($params['data'] != '') ? $params['data'] : date('Y-m-d H:i:s');
        $articlesData = $data['data'];
        //$total = $data['total'];

        $articleDataNovo = array(
            'url' => $params['url'],
            'articleId' => $params['articleId'],
            'postedDateTime' => $data_pub,
            'title' => $params['title'],
            'contents' => $params['contents'],
            'category' => $params['category']
        );

        if (is_array($articlesData) && count($articlesData)) {

            $index = Zend_Search_Lucene::open($this->public_dir_indice);
            Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding('utf-8');
            Zend_Search_Lucene_Analysis_Analyzer::setDefault(new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8_CaseInsensitive());
            $count = 0;
            $msg = array();
            foreach ($articlesData as $articleData) {

                $doc = new Zend_Search_Lucene_Document();
                if ($acao == 'update' && $articleData->articleId == $params['id']) {
                    $index->delete($articleData->articleId);

                    $doc->addField(Zend_Search_Lucene_Field::text('url', $articleDataNovo["url"], 'utf-8'));
                    $doc->addField(Zend_Search_Lucene_Field::keyword('articleId', $articleDataNovo["articleId"], 'utf-8'));
                    $doc->addField(Zend_Search_Lucene_Field::text('postedDateTime', $articleDataNovo["postedDateTime"], 'utf-8'));
                    $doc->addField(Zend_Search_Lucene_Field::keyword('permission', '1'));
                    $doc->addField(Zend_Search_Lucene_Field::text('title', $this->removeAcentuacao($articleDataNovo["title"]), 'utf-8'));
                    $doc->addField(Zend_Search_Lucene_Field::text('title_accent', $articleDataNovo["title"], 'utf-8'));
                    $doc->addField(Zend_Search_Lucene_Field::text('contents', $articleDataNovo["contents"], 'utf-8'));
                    $doc->addField(Zend_Search_Lucene_Field::text('category', $articleDataNovo["category"], 'utf-8'));
                } else {
                    $doc->addField(Zend_Search_Lucene_Field::text('url', $articleData->url, 'utf-8'));
                    $doc->addField(Zend_Search_Lucene_Field::keyword('articleId', $articleData->articleId, 'utf-8'));
                    $doc->addField(Zend_Search_Lucene_Field::text('postedDateTime', $articleData->postedDateTime, 'utf-8'));
                    $doc->addField(Zend_Search_Lucene_Field::keyword('permission', $articleData->permission));
                    $doc->addField(Zend_Search_Lucene_Field::text('title', $articleData->title, 'utf-8'));
                    $doc->addField(Zend_Search_Lucene_Field::text('title_accent', $articleData->title_accent, 'utf-8'));
                    $doc->addField(Zend_Search_Lucene_Field::text('contents', $articleData->contents, 'utf-8'));
                    $doc->addField(Zend_Search_Lucene_Field::text('category', $articleData->category, 'utf-8'));
                }

                $action = ($acao == 'update') ? "Página atualizada: " : "Página adicionada: ";
                $titulo = ($acao == 'update') ? $articleDataNovo["title"] : $articleData->title;
                $url = ($acao == 'update') ? $articleDataNovo["url"] : $articleData->url;
                $msg[$count]['saida'] = $action . $params['id'] . " - " . $titulo . " - URL: " . $url . "
\n";
                $index->addDocument($doc);
                $count++;
            }
            $index->commit();
            $index->optimize();
            return $msg;
        }
    }

    /**
     *
     * @param type string $acao = (insertall || insert || update )
     * @param array $contentUpdate = será a lista que você deseja atualizar
     * @return type
     * @see : observe que há um modelo externo instanciado no método abaixo,
     * este modelo é responsável por trazer a lista de todas as suas páginas
     * isso será usado quando a ação for para indexar todas as sua páginas
     * @uses : use este método para indexar as páginas
     */
    public function indexarPaginas($acao = 'insertall', array $contentUpdate = null) {

        $model = new Application_Model_Paginas();

        $arrayArtigos = $model->getContent();
        if ($acao == 'insertall' && count($arrayArtigos)) {
            //aqui você cria tada a lista que será indexada
            $getMsg = $this->criarConteudoIndice($arrayArtigos);
            return $getMsg;
        } else if (($acao == 'insert' || $acao == 'update') && count($contentUpdate)) {
            //tanto no caso de inserir somente 1 registro novo como atualizar um existente,
            //você deverá tratar tudo como um método de atualização, pois você terá
            //que reindexar tudo somando esses itens novos e modificando os existentes
            $getMsg = $this->atualizarConteudoIndice($contentUpdate, $acao);
            return $getMsg;
        }
    }

    /**
     *
     * @param type string $termo
     * @param type string $campo
     * @return type array
     * @uses : este é o método que irá construir a busca a partir dos índices já criados no servidor
     * observe que o termo = null, ele é definido por padrão, justamente porque a busca nula, trará tudo que estiver com a permissao = 1.
     * Se vc quiser pode passar no parâmetro a letra "a" nos campos, aí ele irá desprezar a codição de permissão,
     * quase não existe palavra sem a letra a... por isso, provavelmente você conseguirá trazer tudo.
     *
     */
    public function searchContent($termo = null, $campo = null) {

        try {
            $parse_search = '';
            if ($termo == 'a') {
                $termo = "($termo)";
                $parse_search = $termo;
            } else if ($termo == null) {
                $parse_search = "permission:1";
            } else {
                $parse_search = ($campo != null) ? " {$campo}:({$this->slugUrl($termo)}) AND permission:1" :
                        $parse_search = "(title_accent:({$termo})"
                        . " OR title:({$this->slugUrl($termo)})"
                        . " OR postedDateTime:({$this->slugUrl($termo)})"
                        . " OR articleId:({$this->slugUrl($termo)})"
                        . " OR url:({$this->slugUrl($termo)})) AND permission:1";
            }

            $query = Zend_Search_Lucene_Search_QueryParser::parse($parse_search);
            $index = Zend_Search_Lucene::open($this->public_dir_indice);
            $results = $index->find($query);

            $data = array();
            if ($index->count()) {
                $count = 0;
                foreach ($results as $result) {

                    if ($result->permission == '1') {

                        $data[$count]["article_url"] = trim(strip_tags($result->url));
                        $data[$count]["article_title"] = $result->title;
                        $data[$count]["article_title_accent"] = $result->title_accent;
                        $data[$count]["article_description"] = trim(strip_tags($query->highlightMatches($result->contents)));
                        $data[$count]["article_date_time"] = $result->postedDateTime;
                        $data[$count]["article_data_brasil"] = $this->formatarData($result->postedDateTime, "ingles_to_brasil");
                        $data[$count]["article_id"] = $result->articleId;
                        $data[$count]["article_permission"] = $result->permission;
                        $data[$count]["article_category"] = $result->category;
                        $data[$count]["article_category_formated"] = $this->formatarCategoria($result->category);

                        $count++;
                    }
                }
                return array(
                    'data' => $data,
                    'total' => $count
                );
            }
        } catch (Exception $exc) {
            echo "Erro de tempo de execução!";
        }
    }

    /**
     *
     * @param type string $termo
     * @param type string $campo
     * @return type try(array) || type string catch(erro)
     * $uses : este é o método que realizará a busca no Lucene
     */
    public function getBusca($termo, $campo = null) {

        try {
            $data = array();
            $data = $this->searchContent($termo, $campo);
            return array(
                'registros' => $data['total'],
                'data' => $data['data'],
                'palavra' => $termo
            );
        } catch (Exception $e) {
            echo "Erro: " . get_class($e) . "\n";
            echo "Causa: " . $e->getMessage() . "\n";
        }
    }

}

Para você poder capturar todas as classes do seu sistema em Zend, é preciso criar duas classes que estendam Zend_Controller_Response_Abstract e Zend_Controller_Request_Abstract  e implementá-las dentro do modelo que você irá buscá-las:


class Request extends Zend_Controller_Request_Abstract {

}

class Response extends Zend_Controller_Response_Abstract {

}

//depois você chamará elas no seu modelo de captura se elas forem requeridas:
require_once APPLICATION_PATH . "/controllers/Request.php";
require_once APPLICATION_PATH . "/controllers/Response.php";

E agora o Model para capturar as páginas do seu site feito em Zend: (observe que é necessário criar duas classes, Request e Response vazias para poder utilizar este modelo adequadamente:

<?php
class Application_Model_Paginas {

    /**
     *
     * @see : Observe que este será o endereço real para o C_URL capturar as páginas
     * @var type string
     */
    private $url_base = 'http://www.seusite.com.br/';
    /**
     *
     * @param type string ($className = nome da classe)
     * @return type string (métodos da Classe)
     * @uses : use este método para capturar os métodos das classes (controllers) do seu sistema
     */
    private function getClass($className) {
        try {

            $classes = array();
//            $className = preg_replace('/(.*)\.php/', '$1', $directory[$key]);
            $classes[$className]['methods'] = get_class_methods($className);
        } catch (Exception $exc) {
            echo $exc->getMessage();
        }
        return $classes;
    }

    /**
     *
     * @param type string $method
     * @return type string
     * @uses : este método elimina os métodos que você não quer que os sistema indexe, pegando somente a lista de métodos com final Action
     * do seu sistema
     * dica: você pode colocar um parâmetro no começo dos métodos que você não deseja indexar como: noIndex
     * exemplo: noIndexAbrirPaginaAction, noIndexListarRegistrosAction, etc...
     */
    private function removerNoAction($method) {

        $metodo = (preg_match('/(.*)Action$/', $method) &&
                !preg_match('/(gerarIndexadorAction|'
                        . 'metodo1Action|'
                        . 'metodo2Action|'
                        . 'metodo3Action)$/', $method) &&
                !preg_match('/^noIndex(.*)$/', $method)) ? $method : null;
        return $metodo;
    }
/**
 *
 * @param type $className = nome da classe
 * @return type array
 * @uses : este método filtra suas classes convertendo o nome como uma categoria,
 * e constrói a URL do método para indexação
 */
    public function getFilterClassMethods($className) {

        $categoria = substr(strtolower(preg_replace('/([A-Z])/', '-$1', preg_replace('/^(.*)Controller$/', '$1', $className))), 1);
        $lista = array();

        $methods = $this->getClass($className);
//        print_r($methods);

        $keys = array_keys($methods);

        //classes extendidas (Request, Response -> Abstract ) para poder instanciar os demais controllers do Zend
        require_once APPLICATION_PATH . "/controllers/Request.php";
        require_once APPLICATION_PATH . "/controllers/Response.php";

        $classMethods = array();
        $methodsArray = array();

        foreach (array_keys($methods) as $class) {

            //inclui a classe que fornecerá seus métodos
            require_once APPLICATION_PATH . "/controllers/{$class}.php";

            try {
//                $c = new $class(new Request(), new Response());
                $classMethods[$class]['methods'] = get_class_methods($class);

                foreach ($classMethods[$class]['methods'] as $metodo) {
                    if ($this->removerNoAction($metodo) != null)
                        $methodsArray[] = array(
                            'metodo' => $metodo,
                            'classe' => $class,
                            'classe_slug' => $this->formatarCategoria($class),
                            'categoria' => preg_replace('/-/', ' ', $this->formatarCategoria($class)),
                            'url' => $this->formataURL($this->formatarCategoria($class), $metodo)
                        );
                }
            } catch (Exception $exc) {
                echo $exc->getTraceAsString();
            }

            return $methodsArray;
        }
    }
/**
 *
 * @param type string $text
 * @return type string
 * @uses : este método converte todo o texto em formato UTF-8
 */
    private function converterUtf8($text) {
        $text = iconv("windows-1252", "UTF-8//TRANSLIT", $text);
        $text = iconv("ISO-8859-1", "UTF-8//TRANSLIT", $text);
        return $text;
    }

    /**
     *
     * @param type string $url_metodo
     * @return type string
     * @uses : este método é o mais crucial para capturar sua HTML,
     * muito cuidado ao utilizá-lo, pois ao indexar suas páginas ele entrará no laço
     * e irá capturar a HTML inteira carregada e retornar ela numa variável
     * certifique-se de que seu servidor esteja com permissão de curl habilitado
     */
    public function capturarUrl($url_metodo) {

        try {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url_metodo);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            $saida = curl_exec($ch);
            curl_close($ch);
        } catch (Exception $e) {
            $saida = file_get_contents($url_metodo);
        }
        return $saida;
    }
/**
 *
 * @param type int $idInicial = inicia a indexação id com número 1
 * @return type array
 * @uses : use este método para capturar as páginas via C_URL, a partir dos métodos
 * dos controller informados abaixo (precisam ser controles existentes no seu sistema
 *
 */
    public function listarPaginasController($idInicial = 1) {

        $classes = array(
            0 => 'IndexController',
            1 => 'ArtigosController',
            2 => 'ContatoController'
        );

        $listarPaginas = array();
        $id = $idInicial;

        foreach ($classes as $classe) {
            $metodos = $this->getFilterClassMethods($classe);

            foreach ($metodos as $metodo) {
                //aqui ele captura a URL e manda a HTML pra indexação lucene
                $content = $this->capturarUrl($this->url_base . $metodo['url']);

                $listarPaginas[] = array(
                    "url" => $metodo['url'],
                    "title" => $this->formatarTitulo($content, true),
                    "title_accent" => $this->formatarTitulo($content),
                    "contents" => $this->removerHTMLContent($content),
                    "category" => $metodo['category'],
                    "postedDateTime" => date('Y-m-d H:i:s'),
                    "articleId" => $id
                );
                $id++;
            }
        }

        return $listarPaginas;
    }
/**
 *
 * @param type string $controller
 * @param type string $metodo
 * @return type string : url
 * constrói a URL do seu sistema
 */
    private function formataURL($controller, $metodo) {
        return '/' . $controller . '/' . strtolower(preg_replace('/([A-Z])/', '-$1', preg_replace('/^(.*)Action$/', '$1', $metodo)));
    }
/**
 *
 * @param type string $string
 * @return type string
 * @uses : remove acentos
 */
    private function removeAcentuacao($string) {
        $acentos = array("À", "Á", "Â", "Ã", "Ä", "Å", "à", "á", "â", "ã", "ä", "å", "Ò", "Ó", "Ô", "Õ", "Ö", "Ø", "ò", "ó", "ô", "õ", "ö", "ø", "È", "É", "Ê", "Ë", "è", "é", "ê", "ë", "Ç", "ç", "Ì", "Í", "Î", "Ï", "ì", "í", "î", "ï", "Ù", "Ú", "Û", "Ü", "ù", "ú", "û", "ü", "ÿ", "Ñ", "ñ", "á", "à", "â", "ã", "é", "è", "ê", "í", "ì", "î", "ó", "ò", "ô", "õ", "ú", "ù", "ü", "û", "ç", "º", "ª", " ");
        $sem_acentos = array("a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "o", "o", "o", "o", "o", "o", "o", "o", "o", "o", "o", "o", "e", "e", "e", "e", "e", "e", "e", "e", "c", "c", "i", "i", "i", "i", "i", "i", "i", "i", "u", "u", "u", "u", "u", "u", "u", "u", "y", "n", "n", "a", "a", "a", "a", "e", "e", "e", "i", "i", "i", "o", "o", "o", "o", "u", "u", "u", "u", "c", "o", "a", " ");
        $string = str_replace($acentos, $sem_acentos, $string);
        return strtolower($string);
    }
/**
 *
 * @param type string $html
 * @return type string
 * @uses : este método converterá sua HTML em texto corrido e removerá toda a acentuação
 */
    private function removerHTMLContent($html) {
        $content = preg_replace("/(\s|\n|\r)/", " ", trim(preg_replace("/\s+/", " ", strip_tags(preg_replace('/]*>(.*?)/is', '', $html)))));
        return $this->removeAcentuacao($content);
    }
/**
 *
 * @param type string $className
 * @return type string
 * @uses : este método transformará seu controle em um título de categoria
 */
    private function formatarCategoria($className) {
        $categoria = substr(strtolower(preg_replace('/([A-Z])/', '-$1', preg_replace('/^(.*)Controller$/', '$1', $className))), 1);
        return $categoria;
    }
/**
 *
 * @param type string $html
 * @param type bool $sem_acento
 * @return type string
 * @uses : este método irá capturar o primeiro título que encontrar na sua HTML entre as tags <h1></h1>
* e retorná-lo como um texto único, e caso não encontre, ele irá salvar como Untitled.
 * caso o parâmetro boleano $sem_acento seja  true, ele irá remover acentos do seu título
 *
 */
private function formatarTitulo($html, $sem_acento = false) {
 $titulo = '';
 $tit = strip_tags(preg_replace('/<h1>(.*)<\/h1>/', '/|#$1|#', $html));
 if ($tit != '' && preg_match('/|#/', $tit)) {
 $contTit = explode('|#', $tit);
 if (count($contTit) > 1) {
 $titulo = $contTit[1];
 }
 } else
 $titulo = 'Untitled';

$titulo = ($titulo != "") ? trim(strip_tags($titulo)) : 'Untitled';
 return ($sem_acento) ? $this->slugUrl($titulo) : $titulo;
 }
/**
 *
 * @return type array
 * @uses : este método cria a listagem de páginas
 */
 public function getContent() {
 return $this->listarPaginasController(1);
 }
/**
 *
 * @param type $pos
 * @return (type array $articlesData || \Application_Model_Artigos)
 * @uses : retorna a lista de páginas contruídas
 */
 public function getPaginas($pos = null) {

$content = $this->getContent();
 $itens = array();
 $id = ($pos != null) ? $pos : 1;

if (!empty($content)) {
 foreach ($content as $content) {
 $itens[] = array(
 "url" => $content['url'],
 "title" => $content['title'],
 "title_accent" => $content['title_accent'],
 "contents" => $content['contents'],
 "category" => $content['category'],
 "postedDateTime" => $content['postedDateTime'],
 "articleId" => $id
 );
 $id++;
 }

$articlesData = array($itens);
 asort($articlesData);
 if ($pos != null) {
 $artigo = (object) $articlesData[$pos];
 return $artigo;
 } else
 return $articlesData;
 } else
 return $this;
 }
/**
 *
 * @param type string $string
 * @param type string $slug
 * @return type string
 * uses: remove acentos e trata os espaços
 */
 public function slugUrl($string, $slug = ' ') {
 $string = $this->removeAcentuacao($string);
 // $string = iconv("UTF-8", "ASCII//TRANSLIT", $string);

$string = strtolower($string);
 if ($slug) {
 $string = preg_replace('/[^a-z0-9]/i', $slug, $string);
 $string = preg_replace('/' . $slug . '{2,}/i', $slug, $string);
 $string = trim($string, $slug);
 }
 return $string;
 }

}

Implementando botão de Zoom (A+ / A- ) em texto com jQuery


<!doctype html>
 <html lang="pt_BR">
   <head>
   <meta charset="UTF-8">
   <title>Zoom em texto by Toca Digital</title>
   <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
   <script>
   $(document).ready(function() {

     var contador = 0;
     //coloca os elementos que irão receber zoom no array
     var obj_tratados = new Array('#texto', '#texto h1', '#texto h2');
     var reset_fonte = new Array();
     var reset_linha = new Array();
     var expandir_entrelinha = 10;

    //captura os tamanhos padrões na tela para todos os elementos do array
      setDefaultZoom(obj_tratados, reset_fonte, reset_linha);

      $('#a_mais,#a_menos,#a_reset').on('click', function() {

        var id = $(this).attr('id');
        var min = 9; //define o menor valor de zoom
        var max = 28; //define o maior valor de zoom

        for (var i in obj_tratados) {

          var tratados = $(obj_tratados[i]);
          var tamanho_fonte = strReplace(tratados.css('fontSize'), 'px', '');
          var tamanho_entrelinha = strReplace(tratados.css('lineHeight'), 'px', '');

         switch (id) {
           case 'a_mais':
              if (tamanho_fonte <= max) {
                   tamanho_fonte++;
                   tamanho_entrelinha++;
                   var val = (tamanho_entrelinha * expandir_entrelinha / 100) + tamanho_entrelinha;
                   tamanho_entrelinha = arredondarValor(val);
                    contador++;
              }
           break;
           case 'a_menos':
              if (tamanho_fonte >= min) {
                  tamanho_fonte--;
                  tamanho_entrelinha--;
                   var val = tamanho_entrelinha - (tamanho_entrelinha * expandir_entrelinha / 100);
                  tamanho_entrelinha = arredondarValor(val);
                  contador++;
              }
          break;
          case 'a_reset': default:
             tamanho_fonte = reset_fonte[i];
             tamanho_entrelinha = reset_linha[i];
          }
        tratados.css({'fontSize': tamanho_fonte + 'px', 'lineHeight': tamanho_entrelinha + 'px'});
       }
       return false;
    });
    function setDefaultZoom(obj_tratados, reset_fonte, reset_linha) {
        for (var i in obj_tratados) {
             var tratados = $(obj_tratados[i]);
             if (contador == 0) {
                  reset_fonte[i] = strReplace(tratados.css('fontSize'), 'px', '');
                  reset_linha[i] = strReplace(tratados.css('lineHeight'), 'px', '');
             }
        }
    }

});
function arredondarValor(valor) {
   if (valor)
       valor = Math.round(valor);
   return valor;
 }

function strReplace(valor, antigo, novo) {
   if (valor)
       valor = valor.replace(antigo, novo);
   return valor;
 }
 </script>

</head>
 <body>
   <span id="controle_zoom">
      <a href="javascript:void(0);" id="a_reset">A </a>&nbsp;|&nbsp;
      <a href="javascript:void(0);" id="a_mais">A+</a>&nbsp;|&nbsp;
      <a href="javascript:void(0);" id="a_menos">A-</a>
  </span>
   <div id="texto">
    <h1>Seu título aqui</h1>
    <h2>Seu subtítulo aqui</h2>
      <p><strong>Lorem Ipsum</strong> é simplesmente uma simulação de texto da indústria tipográfica e de impressos, e vem sendo utilizado desde o século XVI, quando um impressor desconhecido pegou uma bandeja de tipos e os embaralhou para fazer um livro de modelos de tipos. Lorem Ipsum sobreviveu não só a cinco séculos, como também ao salto para a editoração eletrônica, permanecendo essencialmente inalterado. Se popularizou na década de 60, quando a Letraset lançou decalques contendo passagens de Lorem Ipsum, e mais recentemente quando passou a ser integrado a softwares de editoração eletrônica como Aldus PageMaker.</p>
    </div>
  </body>
</html>

Switch to our mobile site