Перевод текстов посредством Bing API (устарело)

23 июня 2011

Сегодня, в связи с тем что гугл собирается закрывать свой translate api, таки собрался и сотворил класс для перевода текста через SOAP сервис Bing

В связи с тем, что по каким-то странным обстоятельствам нормальной документации нет, а есть только куцый пример на VB (о ужас!) и C# с использованием видимо готовых библиотек пришлось повозиться и подбирать параметры и вид, в котором надо данные отправить сервису, чтоб он не ругался непонятными словами.

В результате родилось вот что:

<?php
class Bing_Translate_API {
 
    function translate($text, $from = 'en', $to = 'ru') {
 
        if (mb_strlen($text)>2000)
        {
            echo "шмахтунг\n";
            return false;
        }
 
        $c=new SoapClient("http://api.bing.net/search.wsdl",array(
            "AppId"=>"bingApiId",
            "Version"=>"2.2"
        ));
 
        $arr=array(
            "parameters"=>array(
                "AppId"=>"bingApiId",
                "Market"=>"en-us",
                "Version"=>"2.2",
                "Sources"=>array(
                    "Translation"
                ),
                "Translation"=>array(
                    "SourceLanguage"=>$from,
                    "TargetLanguage"=>$to
                ),
                "Query"=>$text)
        );
 
        $r=$c->Search($arr);
 
        if (isset($r->parameters->Translation->Results->TranslationResult->TranslatedTerm))
        {
            return $r->parameters->Translation->Results->TranslationResult->TranslatedTerm;
        }
        else
        {
            echo "ахтунг\n";
            return false;
        }
 
 
    }
}
?>

а вызывать пользоваться этим безобразием теперь вообщем-то просто:

<?php
echo Bing_Translate_API::translate("text to translate","en","ru");
?>

Кроме того, выяснилось, что у Bing API есть ограничение на размер запроса примерно в 2кБ текста. А Примерно потому, что через раз он текст с размером 2048 символов не переводил, уж не знаю почему.

BingApiId получать по ссылке http://www.bing.com/developers/

З.Ы. я знаю что код кривой, и при малейшем чихе упадет, но делать ничего не буду, это есть пример 🙂

Опубликовал:

Изобретая велосипеды: xmlrpc

19 апреля 2011

Вчера озаботился возможностью что-то опубликовать в блоке посредством xmlrpc из php.

Проковырявшись в общей сложности часа 4 с библиотекой xmlrpc и встроенной функцией xmlrpc_encode_equest и так и не добившись нормальной работы всего этого безобразия, собрался и сегодня за 1.5 часа сделал свой велосипед 🙂

<?php
/*
 * Велосипед для работы с xmlrpc
 * версия 0.1beta
 *
 * Copyright (c) 2011 mrdaark.
 * Все права защищены
 * 
 */
 
/*
 * Функция для отправки запроса на xmlrpc сервер
 * использует библиотеку curl
 * в качестве параметров:
 * @url - url адрес сервера
 * @request - запрос формируемый с помощью функции xmlrpc_request
 */
function xmlrpc_send($url,$request)
{
    if(!function_exists('curl_init')) {
        die ("Curl PHP package not installed\n");
    }
 
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: text/xml; charset=utf-8"));
    curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
    $response = curl_exec($ch);
    $response = xmlrpc_decode($response);
    curl_close($ch);
    return $response;
}
 
/*
 * Функция формирования xml запроса на xmlrpc
 * в качестве параметров:
 * @method - вызываемый метод
 * @params - массив списка параметров
 */
function xmlrpc_request($method,$params)
{
    $xml ="<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
    $xml.="<methodCall><methodName>".$method."</methodName><params>";
 
    if (is_array($params))
    {
        foreach ($params as $v)
        {
            if (is_numeric($v))
            {
                $xml.="<param><value><int>".$v."</int></value></param>";
            }
            else if (is_string ($v))
            {
                $xml.="<param><value><string>".$v."</string></value></param>";
            }
            else if (is_bool($v))
            {
                $xml.="<param><value><boolean>". ($v ? "1":"0") ."</boolean></value></param>";
            }
            else if (is_array($v))
            {
                $xml.="<param>"._xmlrpc_genstruct($v)."</param>";
            }
        }
    }
    $xml.="</params></methodCall>";
    return $xml;
}
 
/*
 * Функция формирования именованной структуры
 * в качестве параметров:
 * @params - массив списка параметров
 */
function _xmlrpc_genstruct($params)
{
    if (is_array($params))
    {
        $xml="<value><struct>";
        foreach ($params as $k=>$v)
        {
            //формируем поля запроса.
            if (is_numeric($v))
            {
                $xml.="<member><name>".$k."</name><value><int>".$v."</int></value></member>";
            }
            else if (is_string ($v))
            {
                $xml.="<member><name>".$k."</name><value><string>".$v."</string></value></member>";
            }
            else if (is_bool($v))
            {
                $xml.="<member><name>".$k."</name><value><boolean>". ($v ? "1":"0") ."</boolean></value></member>";
            }
            else if (is_array($v))
            {
                $xml.="<member><name>".$k."</name>";
                if (_xmlrpc_is_struct($v))
                {
                    $xml.=_xmlrpc_genstruct($v);
                }
                else
                {
                    $xml.=_xmlrpc_genarray($v);
                }
                $xml.="</member>";
            }
        }
        $xml.="</struct></value>";
        return $xml;
    }
    else
    {
        return "";
    }
}
 
/*
 * Функция формирования неименованного массива
 * в качестве параметров:
 * @params - массив списка параметров
 */
function _xmlrpc_genarray($params)
{
    if (is_array($params))
    {
        //проверим необходимость добавления имени
        $xml="<value><array><data>";
        foreach ($params as $v)
        {
            //формируем поля запроса.
            if (is_numeric($v))
            {
                $xml.="<value><int>".$v."</int></value>";
            }
            else if (is_string ($v))
            {
                $xml.="<value><string>".$v."</string></value>";
            }
            else if (is_bool($v))
            {
                $xml.="<value><boolean>". ($v ? "1":"0") ."</boolean></value>";
            }
            else if (is_array($v))
            {
                if (_xmlrpc_is_struct($v))
                {
                    $xml.=_xmlrpc_genstruct($v);
                }
                else
                {
                    $xml.=_xmlrpc_genarray($v);
                }
            }
        }
        $xml.="</data></array></value>";
        return $xml;
    }
    return "";
}
 
/*
 * Функция проверки переданного массива на
 * предмет необходимости формирования
 * именованной структуры
 * в качестве параметров:
 * @params - массив списка параметров
 */
function _xmlrpc_is_struct($params)
{
    $keys=array_keys($params);
    foreach ($keys as $k=>$v)
    {
        if ($k!=$v)
        {
            return true;
        }
    }
    return false;
}
?>

Пользоваться безобразием просто, вот примерчик постинга в блог на wordpress:

<<?php
require("xmlrpc.php");
//формируем массив с параметрами запроса
$content=array();
$content['title']="Тестовая запись";
$content['categories'] = array("news");
$content['description']="Описание тестовой запись (то, что до тега <!--more-->)";
$content['mt_text_more']="Собственно основная часть постинга";
$content['mt_keywords']="ключевые, слова";
 
//формируем xml запрос
$request=xmlrpc_request("metaWeblog.newPost",
        array(1,"admin","password",$content,false));
 
//отправляем серверу
xmlrpc_send("http://example.com/wordpress/xmlrpc.php",$request);
?>

вроде все просто и понятно. Работает на данный момент только с кодировкой UTF-8. Собственно и затеялось как раз потому, что два предыдущих варианта напрочь отказывались нормально отправлять в UTF-8.

Реализованы не все типы, возможные в xmlrpc, однако мне для постинга в WordPress этого пока хватит, буде кому понадобится еще чего можете меня попинать — допишу, ну или сами, а я добавлю со ссылкой на автора 🙂

P.S. походу wordpress чудит с кавычками. файл исходника xmlrpc.phps

Опубликовал:

Решение задачки для php программистов с хабра

5 апреля 2011

Увидел на хабре задачку при собеседовании для php программистов http://habrahabr.ru/blogs/php/116686/

Решил попробовать сам ее решить, вроде не сложно. вместе с отладкой, сделал за ~20минут, т.е. в норматив не уложился, что херово.

Получилось вот так,  хз насколько это оптимально. Есть идеи что улучшить?

<?php
function read_conf($path)
{
    $f=file_get_contents($path);
    //разбиваем на строки
    $lines=explode("\n",$f);
    $tmp=array();
 
    //режем строки на key=>value
    foreach($lines as $v)
    {
        if (trim($v)!="")
        {
            list($key,$value)=explode("=",$v,2);
            $tmp[trim($key)]=trim($value);
        }
    }
 
    $res=array();
    //режем ключи по параметрам
    foreach ($tmp as $key=>$value)
    {
        $keys=explode(".",$key);
        if (count($keys)!=1)
        {
            //тут будем делать подмассивчики
            $key=array_pop($keys);
            $first_key=array_shift($keys);
            if (!isset($res[$first_key]))
            {
                $res[$first_key]=array();
            }
            $pres=&$res[$first_key];
            while (count($keys)!= 0)
            {
                $tmp_key=array_shift($keys);
                if (!isset($pres[$tmp_key]))
                {
                    $pres[$tmp_key]=array();
                }
                $pres=&$pres[$tmp_key];
            }
            $pres[$key]=$value;
        }
        else
        {
            $res[$key]=$value;
        }
    }
    return $res;
}
print_r(read_conf("conf.ini"));
?>

Опубликовал:

Изобретая велосипеды: PHP шаблонизатор

13 февраля 2009

Началось все с того что мне не нравятся существующие темплейтеры типа smarty. Не прет.

Написал свой, простенький, но для повседневности хватает.

вот такой вот класс:

  1. <?php
  2. class Template {
  3.     private $template;
  4.     private $vars;
  5.     private $blocks;
  6.     private $res;
  7.     private $registry;
  8.  
  9.     function __construct($registry) {
  10.         $this->registry = $registry;
  11.     }
  12.  
  13.     private function getvars($block="")
  14.     {
  15.         $str="";
  16.         if ($block=="")
  17.         {
  18.             $str=$this->res;
  19.         }
  20.         else
  21.         {
  22.             if (isset($this->blocks[$block]))
  23.             {
  24.                 $str=$this->blocks[$block];
  25.             }
  26.         }
  27.         $m=array();
  28.         preg_match_all("/{%(.*)?%}/ismU",$str,$m,PREG_SET_ORDER);
  29.         return $this->assoc($m);
  30.     }
  31.  
  32.     private function assoc($arr)
  33.     {
  34.         $r=array();
  35.         if (count($arr)>0)
  36.         {
  37.             foreach ($arr as $v)
  38.             {
  39.                 $r[$v[1]]=$v[0];
  40.             }
  41.         }
  42.         return $r;
  43.     }
  44.  
  45.     private function getblocks()
  46.     {
  47.         $m=array();
  48.         preg_match_all("/<!--(.*)?-->.*?<!--\/\\1-->/ismU", $this->template, $m ,PREG_SET_ORDER);
  49.         $this->blocks=$this->assoc($m);
  50.     }
  51.  
  52.     private function getinclude($data)
  53.     {
  54.         $m=array();
  55.         preg_match_all("/<!--include:(.*)?-->/ismU", $this->template, $m ,PREG_SET_ORDER);
  56.         foreach ($m as $i)
  57.         {
  58.             $t=new template($this->registry);
  59.             $this->res=str_replace($i[0],$t->compile($data,site_path.$i[1]),$this->res);
  60.             unset($t);
  61.         }
  62.     }
  63.  
  64.     function getphp()
  65.     {
  66.         $m=array();
  67.         preg_match_all("/{--(.*)?--}/ismU", $this->res, $m ,PREG_SET_ORDER);
  68.         $out="";
  69.         foreach ($m as $p)
  70.         {
  71.             ob_start();
  72.             eval ("echo ".$p[1].";");
  73.             $out = ob_get_clean();
  74.             $this->res=str_replace($p[0],$out,$this->res);
  75.         }
  76.     }
  77.  
  78.     private function setvars($tpl,$vars,$d)
  79.     {
  80.         $str=$tpl;
  81.         foreach ($vars as $var => $search)
  82.         {
  83.             if (isset($d[$var]))
  84.             {
  85.                 $str=str_replace($search,$d[$var],$str);
  86.             }
  87.             else
  88.             {
  89.                 $str=str_replace($search,"",$str);
  90.             }
  91.         }
  92.         return $str;
  93.     }
  94.  
  95.     private function compileblock($block,$data)
  96.     {
  97.         $tpl=$this->blocks[$block];
  98.         $res="";
  99.         $vars = $this->getvars($block);
  100.         //print_r($vars);
  101.         foreach($data as $d)
  102.         {
  103.             $res.=$this->setvars($tpl,$vars,$d)."\n\n";
  104.         }
  105.         $this->res=str_replace($tpl,$res,$this->res);
  106.     }
  107.  
  108.     function compile($data,$tplfile)
  109.     {
  110.         $this->template=file_get_contents($tplfile);
  111.         $this->res=$this->template;
  112.         $this->getblocks();
  113.         foreach ($this->blocks as $block => &$v)
  114.         {
  115.             if (isset($data[$block]))
  116.             {
  117.                 $this->compileblock($block,$data[$block]);
  118.             }
  119.             else
  120.             {
  121.                 $this->res=str_replace($this->blocks[$block],"",$this->res);
  122.             }
  123.         }
  124.         $this->res=$this->setvars($this->res,$this->getvars(),$data);
  125.         $this->getinclude($data);
  126.         $this->getphp();
  127.  
  128.         return $this->res;
  129.     }
  130.  
  131.     function html($data,$tplfile)
  132.     {
  133.         echo $this->compile($data,site_path.$tplfile);
  134.     }
  135. }
  136. ?>

Чтобы было проще понять, вот пример шаблона:

  1. <!--include:tpl/header.tpl-->
  2. <table class="adminlist" style="width:300px;">
  3. <tr>
  4. <th class="title" width="3%"><input name="toggle" id="toggle" value="1" onclick="checkAll(1);" type="checkbox" /></th>
  5. <th class="title" width="97%">&nbsp;</th>
  6. </tr>
  7.  
  8. <!--users-->
  9. {--('1'=='{%flag%}') ? '<tr><td colspan="2">{%gname%}</td></tr>':'' --}
  10. <tr class="row0">
  11. <td><input type="checkbox" class="checkbox" name="check_{%id%}" /></td>
  12. <td><a href="/users/edit/{%id%}">{%name%}</a></td></tr>
  13. <!--/users-->
  14.  
  15. {--('write'=='{%right%}') ? '<tr><td colspan="6" style="text-align:center;"><a href="/users/create">Добавить</a></td></tr>':''--}
  16. </table>
  17.  
  18. <!--include:tpl/footer.tpl-->

Как использовать? примерно вот так:

  1. <?php
  2. $d=array();
  3. $d['users'][1]['id']=1;
  4. $d['users'][1]['name']='User 1';
  5. $d['users'][1]['game']='Group 1';
  6. $d['users'][1]['flag']=1;
  7. $d['users'][2]['id']=2;
  8. $d['users'][2]['name']='User 2';
  9. $d['users'][2]['game']='Group 1';
  10. $d['users'][2]['flag']=0;
  11. $d['users'][3]['id']=3;
  12. $d['users'][3]['name']='User 3';
  13. $d['users'][3]['game']='Group 2';
  14. $d['users'][3]['flag']=1;
  15. $d['right']='right';
  16.  
  17. $template = new Template($registry);
  18. $template->html($d,'tpl/usersform.tpl');
  19.  
  20. ?>

Поподробнее про теги шаблона:
{%name%} — переменная
<!—include:file.tpl—> — включение внешнего шаблона (количество включений ограничено только оперативной памятью 🙂
повторяющиеся блоки оформляются так
<!—blockname—>
{%name%}
<!—/blockname—>
где blockname — это массив значений в передаваемом параметре
условия задаются вот так:
{—(‘1’=='{%flag%}’) ? ‘{%var1%}’:'{%var2%}’ —}

ссылочка на файлик класса: template.phps

Опубликовал: