[Yii Framework] Menu Dinamis dengan RBAC menggunakan Rights Extension

Sebelumnya saya pernah posting tentang penggunaan Rights extension disini. Walau sama-sama digunakan untuk pengaturan hak akses user, tapi menggunakan RBAC dan menggunakan cara manual yang kita buat sendiri cukup berbeda. Dengan RBAC, kita dapat menanamkan lebih dari 1 buah level pada seorang user. Juga dapat menanamkan hak akses seorang user langsung kepada suatu action yang dituju sehingga ini dapat jauh lebih efektif dibandingkan membuat nya tanpa RBAC.

Okeh, sekarang yang jadi permasalahan adalah jika saya ingin membuat sebuah menu dinamis pada RBAC dengan Rights seperti kasus ini. Semisal jika yang login adalah user yang memiliki level ‘Moderator’, maka menu nya akan muncul dan jika bukan moderator maka tidak muncul. Untuk itu, kita dapat membuat nya seperti berikut :

Buatlah sebuah fungsi tambahan pada modules rigths kita di “protected/modules/rights/componenst/RWebUser.php” seperti berikut :

 public function isRole($roleParam)
 {
     $allroles=Rights::getAssignedRoles($this->id);

     foreach ($allroles as $ii)
     {
          if($ii->name==$roleParam)
          return true;
     }
     return false;
 }

Fungsi di atas digunakan untuk mengetahui apakah seorang user yang sedang login memiliki level role dari parameter $roleParam. Jadi misal kita memanggil fungsi “Yii::app()->user->isRole(‘Moderator’)” berarti kita ingin mengecek apakah user yang sedang login saat ini memiliki tipe moderator atau tidak. Maka dari itu ketika membuat menu, kita bisa tambahkan code berikut untuk memastikan suatu menu tersebut hanya dapat dilihat oleh user yang memiliki level “Moderator”:

 array('label'=>'naamaMenu', 'url'=>array('/site/login'),'visible'=>Yii::app()->user->isRole('Moderator')&&!Yii::app()->user->isGuest),

Dengan begitu menu tersebut hanya akan muncul jika aplikasi kita di akses oleh orang yang sudah login dan memiliki level role ‘Moderator’. Tidak hanya itu, kita juga dapat menampilkan menu yang memang dapat diakses oleh seorang user. Misal, saya ingin menampilkan link menu yang mengarah ke halaman “User/admin”. Saya tidak tahu user dengan level apa saja yang dapat mengakses “User/Admin”. Karena tidak mau repot, saya ingin sistem secara otomatis harus menampilkan menu tersebut hanya kepada orang-orang yang memang diizinkan mengakses menu tersebut saja. Maka kita dapat membuat menu sebagai berikut :

 array('label'=>'User Admin', 'url'=>array('/user/admin'), 'visible'=>Yii::app()->user->checkAccess('User.Admin')),

Pada code di atas dapat kita lihat menu tersebut akan visible kepada user yang diizinkan mengakses action “User.Admin” saja. Dengan cara begitu kita tidak perlu repot mencari tahu siapa saja yang diizinkan mengakses suatu menu..

Menarik bukan??

Selesai… Selamat mencoba..

Semoga membantu.. 🙂

[Yii Framework] AJAX (Dependent Dropdownlist) in Multi Value / Grid Form

Biasanya kita menggunakan extension Jappendo untuk mengatasi masalah input one to many atau penginputan banyak data sekaligus.. Selama menggunakan JAppendo, kesulitan saya adalah ketika ingin menerapkan AJAX pada masing-masing inputan yang ada. Sebagai contoh adalah masalah penerapan dependent dropdownlist seperti gambar berikut :

Saya memiliki tabel provinsi dan tabel kabupaten/kota. Inputan di atas bisa saya modifikasi ingin menginput 5 row, 7 row, dll pokoknya bisa saya tambah dan kurangi.. Jika di jappendo kita sudah bisa membuat hal tersebut tentunya.. Tapi permasalahannya adalah jumlah kabupaten di Indonesia adalah ratusan. Sehingga saya ingin ketika saya memilih provinsi maka yang tampil pada kolom kabupaten adalah kabupaten dari provinsi yang telah saya pilih saja.. Dan itu harus berlaku untuk semua row yang ada dimana hasilnya nanti adalah seperti gambar berikut :

Anda dapat lihat pada gambar di atas bahwa masing-masing row menampilkan list kabupaten yang berbeda sesuai dari Provinsi yang telah terpilih masing-masing..  Salah satu buktinya adalah dropdownlist yang berbeda-beda panjangnya..

Okeh, itulah permasalahan yang akan kita bahas. Lalu bagaimana cara mengimplementasikannya?? Pada kasus ini, saya harus selingkuh dari Jappendo untuk berpaling pada jqrelcopy. Hal pertama yang harus kita lakukan adalah mendownload terlebih dahulu extension jqrelcopy lalu masukkan ke dalam folder extension seperti biasa. Kemudian mari kita definisikan jqrelcopy pada code tampilan kita :

 <?php 
   $this->widget('ext.jqrelcopy.JQRelcopy',array(
    'id' => 'copylink',
    'removeText' => 'Remove',   // text yang akan muncul pada link remove
    'removeHtmlOptions' => array('style'=>'color:red'),
    'options' => array(
          'copyClass'=>'newcopy',
          'limit'=>5,  // batas row yang diizinkan pada jqrelcopy
          'clearInputs'=>true,
          'excludeSelector'=>'.skipcopy',
     )
   ));
 ?>

 <a id="copylink" href="#" rel=".yangdicopy">Tambah</a>   // link yang akan digunkan untuk menambahkan row baru. Pada code ini terdapat attirbute (rel=".yangdicopy") yang artinya ketika kita meng klik pada link ini maka akan meng copy tampilan class "yangdicopy"

 <div class="row yangdicopy">
 <?php echo CHtml::dropDownList('provinsi[]','',
         CHtml::listData(ModelProvinsi::model()->findAll(),'kode_daerah', 'nama_daerah'),
         array(
          'onChange' => CHtml::ajax(array(
            'type'=>'POST',
            'dataType'=>'json',
             'url'=>array('namaController/namaAction'),  // action yang dipanggil pada perintah AJAX
            'data' => "js:{haha:$(this).val(),idnya:$(this).attr('id')}",  // memberikan nilai provinsi yang dikirim dan mengirim row yang ke berapa yang sedang digunakan
            'success'=>"function(data){
               var kabu='#kabupaten'+data.idnya;  // mendefinisikan row kabupaten mana yang akan di edit. Ini kita definisikan sendiri dengan algoritma yang kita buat
               $(kabu).html(data.satu);  // menginput daftar kabupaten pada row kabupaten yang terpilih
             }",
          )),'empty'=>'Pilih Provinsi',
      )); ?>
     <?php echo CHtml::dropDownList('kabupaten[]','',array(),array('empty'=>'-- Pilih Kabupaten --')); ?>
 </div>

Code di atas adalah code yang tersaji di halaman tampilan kita.  Seblumnya, kenapa kita tidak menggunakan JAppendo pada kasus ini ? karena jappendo tidak membedakan nama control yang ada pada row. Misal row pertama memiliki id=kabupaten, row ke 2 juga id=kabupaten, row ke 7 juga id=kabupaten sehingga kita kesulitan untuk mengidentifikasinya. Sedangkan pada jqrelcopy tidak pada row pertama id=kabupaten, row ke-2 id=kabupaten2, row ke-7 id=kabupaten7. Nah, dengan begitu kita paling tidak bisa tahu mana yang membedakan masing-masing row.

Pada code di atas sendiri kita menangkap id dari control “provinsi” yang sedang kita pilih. Jadi paling tidak kita tahu kita sekrang sedang memilih provinsi, provinsi2, provinsi7 atau yang mana? Sehingga jika provinsi3 yang dipilih, maka perubahan akan terjadi pada control “kabupten3”. Untuk itulah saya mengirimkan nilai id dari control yang kita pilih ke controller. Kemudian kita lakukan pendeteksian nomornya pada controllernya. Berikut controller yang kita panggil dari AJAX sebelumnya :

public function actionKab()
 {
    $satu='';
    $idnya='';
    if(isset($_POST['haha']))
    {
       $datanya=ModelKabupaten::model()->findAllByAttributes(array('kode_provinsi'=>$_POST['haha'])); // memanggil semua list kabuaten yang dimiliki provinsi yang telah dipilih
       $list=CHtml::listData($datanya,'kode_kab','nama_kab');

       foreach($list as $value=>$name) // menginput semua kabupaten yang telah terpilih untuk dimasukkan ke sebuah nilai
       {
          $satu.=CHtml::tag('option',
             array('value'=>$value),CHtml::encode($name),true);
       }
    }
    if(isset($_POST['idnya']))
    {
       if(strlen($_POST['idnya'])>8)
       {
          $idnya=substr($_POST['idnya'],8); // mengambil angka yang ada pada control yang telah kita pilih. Nama dari id yang dikirim nantinya adalah provinsi/provinsi1/provinsi3/prorinsi100. Kita ingin mengambil nilai yang ada di belakang kata provinsi saja. Maka dari itu kita substring dengan start mulai dari huruf ke-8. Yang artinya kita akan mendapatkan angkanya saja..
      }
      else
      {
          $idnya='';
      }
    }

    echo CJSON::encode(array // mengkonversi nilai yang sudah ada ke dalam format JSON
    (
       'satu'=>$satu,
       'idnya'=>$idnya,
    ));
    Yii::app()->end();
 }

Yak itulah dia codingnya.. Walau harus di akal-akali terlebih dahulu tapi paling tidak bisa berjalan sesuai keinginan kita..

Selesai.. Selamat mencoba..

Semoga membantu… 🙂

[C#] Perhitungan Jarak antara dua titik koordinat

Gara-gara mencari jarak antara 2 koordinat(Latitude, Longitude) jadi tidak tidur 2 hari 2 malam. Ternyata perhitungannya sangat sederhana yaitu menggunakan rumus “Haversine” dimana persamaannya adalah :

Haversine formula: a = sin²(Δlat/2) + cos(lat1).cos(lat2).sin²(Δlong/2)
c = 2.atan2(√a, √(1−a))
d = R.c
dimana R sudah di tentuin yaitu = 6,371 untuk satuan kilometer

Tidak hanya itu saja, ternyata menuangkan rumus ini ke dalam C# cukup sulit, saya memang anti yang namanya Trigonometri tetapi dengan sanggat terpaksa saya harus mengubahnya ke dalam C# sehingga di peroleh seperti ini kira-kira :

public Double Haversine(Double lat1, Double lat2, Double long1, Double long2)
 {
 double dlat = toRad(lat2 - lat1);
 double dlon = toRad(long2 - long1);
 double a = Math.Sin(dlat/2)* Math.Sin(dlat/2) + Math.Sin(dlon / 2) * Math.Sin(dlon/2)*
 Math.Cos(toRad(lat1)) * Math.Cos(toRad(lat2));
 double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
 return 6371 * c;
 }

Bukan main senangnya saya setelah bisa melakukan perhitungannya, tapi kesenangan itu tidak cukup lama setelah saya mencoba mengotak-atik program saya, saya ketemu Method GetDistanceTo(), dan setelah saya coba itu sama saja dengan procedure yang saya temukan. Percuma saja saya melakukan perhitungan dengan Haversine kalo ada yang lebih praktis. Tapi tidak apa-apa lah itung-itung menambah pengetahuan.
menggunakan method GetDistanceTo pada C# :

Asal.Location.GetDistanceTo(Tujuan.Location);

Simpel kan? lebih mudah dari rumus Haversine..

[C#] Mengontrol Isi Textbox Hanya Menerima Angka Saja

Terkadang untuk kita membutuhkan sebuah textbox tetapi isinya hanya boleh diisikan angka (Number Only). Atau sebaliknya hanya menerima inputan huruf bukan angka. Seperti textbox untuk menampung umur tentu itu hanya menerima inputan angka tidak boleh huruf. Untuk contoh Textbox yang hanya menerima inputan angka dapat diperoleh dengan mengikuti langkah-langkah dibawah ini :

1. Terlebih dahulu kita harus mendrag textbox terlebih dahulu dari Toolbox,

2. Setelah itu kita buka propertis dari Textboxnya,

3. Pilih even key press, dan klik 2x

4. kemudian tulis script dibawah ini di dalam metod e.keypress :

if((int)e.keycart<48 || (int)e.keychart>57)
{
(char) e.keychar=0;
}