Bagaimana cara menambahkan kondisi akses ke item menu?

17

Bagaimana saya bisa menambahkan kondisi baru di atas kondisi yang ada yang menentukan apakah item menu terlihat? Ketentuan ini tidak boleh terbatas pada pengaturan izin.

Sebagai contoh use case (belum tentu alasan untuk pertanyaan ini): Misalkan saya memiliki tipe konten yang pengguna hanya diperbolehkan membuat satu node. Saya memiliki item menu untuk menambahkan jenis konten itu. Tetapi jika pengguna telah membuat simpul dari tipe konten itu, saya ingin menyembunyikan item menu. Pikiran pertama saya adalah menjalankan kueri untuk memeriksa keberadaan simpul yang dibuat oleh pengguna saat ini yang merupakan tipe konten tertentu. Jika ada, sembunyikan item menu.

Saya akan berpikir fungsionalitas jenis ini harus masuk hook_menu_alter()dan menambahkan logika yang diperlukan di sana. Tapi saya tidak yakin bagaimana melakukannya tanpa melewati pemeriksaan yang ada, seperti memeriksa apakah pengguna memiliki izin untuk membuat jenis konten itu. Apakah saya harus memasukkan logika itu ke dalam kondisi saya sendiri? Atau dapatkah saya menambah logika akses yang ada tanpa menimpanya?


Sunting: Beberapa orang tampaknya fokus menjawab "bagaimana cara membatasi pengguna untuk membuat satu simpul dari jenis konten". Itu bukan pertanyaan di sini. Pertanyaannya adalah bagaimana cara menambahkan kondisi akses khusus ke item menu.

Chaulky
sumber

Jawaban:

11

Yang perlu Anda lakukan adalah menambahkan callback Anda melalui hook_menu_alter (), dan kemudian di dalam callback Anda, Anda cukup melakukan logika Anda kemudian mengembalikan data melalui callback asli.

Untuk memastikan bahwa Anda tidak menimpa perubahan hook_menu_alter () lainnya, Anda harus meneruskan panggilan balik sebelumnya ke panggilan balik Anda melalui argumen akses.

Ini semua teoretis, tetapi kodenya harus seperti ini:

MYMODULE_menu_alter(&$items) {
  $items['menu']['access arguments'] = array_merge(array($items['menu']['access callback']), $item['menu']['access arguments']);
  $items['menu']['access callback'] = 'MYMODULE_access_callback';
}

MYMODULE_access_callback() {
  $args = func_get_args();

  // Do Stuff.
  if ($something == FALSE) {
    return FALSE;
  }

  $function = array_shift($args);
  return call_user_func_array($function, $args);
}
Menguraikan
sumber
jadi jika saya menetapkan fungsi panggilan balik akses baru, apakah itu pasti menimpa panggilan balik asli?
Chaulky
Ya, Anda hanya dapat memiliki satu panggilan balik akses per item menu, maka pastikan Anda meneruskan kembali ke panggilan balik yang asli. Saya telah melihat modul yang melakukan sesuatu seperti ini, salah satu modul yang berat izinnya, tidak dapat mengingat yang mana.
Menguraikan
apa yang dilakukan array_shift di $ args?
Chaulky
Ini mengeluarkan argumen pertama dari 'argumen akses', yang kami buat sebagai 'akses balik' yang lama. Jadi jika callback lama adalah 'MYMODULE2_access_callback', itulah yang dikembalikan array_shift. Itu juga menghapusnya dari array sehingga kita hanya meneruskan argumen yang diharapkan oleh callback.
Menguraikan
1

Menanggapi komentar di atas, solusi di D7 akan menggunakan:

/**
 * Implements hook_node_access().
 */
function mymodule_node_access($node, $op, $account) {
  $type = is_string($node) ? $node : $node->type;

  if ($op == 'create' && $type == 'mynodetype' && db_query("SELECT 1 FROM {node} WHERE type = :type AND uid = :uid", array(':type' => $type, ':uid' => $account->uid))->fetchField()) {
    // If the user has already created a node of a specific type, they cannot
    // create any more.
    return NODE_ACCESS_DENY;
  }

  // Otherwise do not affect any node access.
  return NODE_ACCESS_IGNORE;
}
Dave Reid
sumber
1
Ini sepertinya tidak ada hubungannya dengan item menu. Saya belum terlalu mengenal D7, tapi sepertinya ini khusus untuk pembuatan simpul. Pertanyaannya difokuskan pada item menu secara umum.
Chaulky
Oh i see ... ini sebagai tanggapan atas komentar saya yang meminta perincian lebih lanjut tentang solusi D7 Anda yang disarankan dalam jawaban Anda yang menunjuk ke modul Batas Node. Masih agak aneh, tapi dihargai.
Chaulky
Karena visibilitas tautan buat mynodetype dikontrol oleh fungsi node_access (), yang akan memanggil pengait ini dalam Drupal 7.
Dave Reid
1

Anda sedang mencari modul API Akses Menu Rantai .

API Akses Menu Rantai memungkinkan modul Anda untuk mem-chain-kan fungsi panggilan balik akses menu-nya sendiri ke entri router menu modul lainnya.

Setidaknya ada satu contoh di Drupal Stack Exchange tentang cara menggunakannya.

Crantok
sumber
-1

Salah satu opsi adalah membuat peran baru yang telah membuat izin konten untuk jenis konten Anda. Setelah pengguna membuat simpul jenis itu, ambil peran itu dan mereka tidak akan bisa membuat lagi.

cjworden
sumber
-1

Mungkin Anda harus mencoba modul Batas Node .

Dari halaman proyek:

Modul Node Limit memungkinkan administrator untuk membatasi jumlah node dari jenis tertentu yang dapat dibuat oleh peran atau pengguna. Misalnya, jika situs memiliki peran "Pengiklan" yang dapat membuat simpul "iklan", maka administrator batas simpul dapat membatasi semua pengguna dalam peran itu ke sejumlah node tertentu. Ia juga dapat membatasi pengguna berdasarkan per pengguna.

Dave Reid
sumber
Membatasi satu simpul hanyalah contoh kasus penggunaan untuk menambahkan metode panggilan balik akses khusus. Juga, Batas Node tidak menghapus item menu, itu hanya mencegah pengguna dari menambahkan node lain dari tipe konten itu.
Chaulky
Itu benar sekarang bahwa saya melihat kembali deskripsi modul. Jika ini pada Drupal 7 itu sebenarnya akan mudah karena Anda dapat menggunakan hook_node_access ($ node, 'create', $ account) yang akan memengaruhi visibilitas tautan tipe node buat sendiri.
Dave Reid
Itu menarik. Saya berencana untuk pindah ke D7 segera. maukah Anda menuliskannya lebih terinci dan memposting jawaban?
Chaulky
Versi D7 dari jawaban yang diposting.
Dave Reid