Üst

Rss Beslenme Introduction to WordPress Plugin Development: Build Your First Plugin

Puan 1
Çözümler 0
Katılım
19 Mar 2025
Mesajlar
36
Tepkime puanı
0
XenWp BotXenWp Bot Doğrulanmış Kullanıcı
WordPress powers over 40% of the web, and much of its flexibility comes from plugins. Plugins are self-contained bundles of PHP, JavaScript, and other assets that extend what WordPress can do—powering everything from simple tweaks to complex business features. If you’re a developer new to WordPress, learning how to build plugins is the gateway to customizing and scaling the platform for any need.

In this guide, you’ll learn the essentials of plugin development, set up a local environment using WordPress Studio, and build a fully functional example plugin. By the end, you’ll understand the anatomy of a plugin, how hooks work, and best practices for a maintainable and secure code.

Table of Contents​

Setting up a local development environment​


Before you write a single line of code, you need a local WordPress environment.
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
is the fastest way to get started. Studio is open source, maintained by Automattic, and designed for seamless WordPress development.

Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.


Follow these steps:

Step 1: Download and install Studio​


Visit
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
and download the installer for macOS or Windows.

Step 2: Create your first local site​


To
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
, launch Studio and click Add Site. You’ll see a simple window where you can name your new site. After entering a name and clicking Add Site, Studio automatically configures a complete WordPress environment for you—no command line knowledge needed. Once complete, your new site appears in Studio’s sidebar, providing convenient links to view it in your browser or access the WordPress admin dashboard.

Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.

Step 3: Open your WordPress site and its admin section​


Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
You can also click the “WP Admin” button in Studio to access your site’s dashboard at /wp-admin. You’ll be automatically logged in as an Administrator. This is where you’ll manage plugins, test functionality, and configure settings.

Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.

Step 4: Open the code in your IDE​


Studio provides
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
that detect your installed code editor (like Visual Code or Cursor) and let you open your project in your preferred editor. You can configure your default code editor in Studio’s settings. Once opened in your code editor, you’ll have complete access to browse, edit, and debug the WordPress installation files.

Click VS Code to open your Code Editor


Once you have your local environment for WordPress development set up and running, locate the plugins folder . In your project root, navigate to:



wp-content/
└── plugins/

This is where all plugins live. To build your own, create a new folder (e.g., quick-reading-time) and add your plugin files there. Studio’s server instantly reflects changes when you reload your local site.

Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.

Creating your first plugin​


Every plugin starts as a folder with at least one PHP file. Let’s build a minimal “Hello World” plugin to demystify the process.

  1. In wp-content/plugins/, create a folder called quick-reading-time.
  2. Inside that folder, create a file named quick-reading-time.php.

Your file structure should look like this:



wp-content/
└── plugins/
└── quick-reading-time/
└── quick-reading-time.php

Add the following code to quick-reading-time.php:



<?php
/*
Plugin Name: Quick Reading Time
Description: Displays an estimated reading-time badge beneath post titles.
Version: 1.0
Author: Your Name
License: GPL-2.0+
Text Domain: quick-reading-time
*/

This header is a PHP comment, but WordPress scans it to list your plugin in Plugins → Installed Plugins. Activate it—nothing happens yet (that’s good; nothing is broken).

Tip: Each header field has a purpose. For example, Text Domain enables translation, and License is required for distribution in the Plugin Directory.
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
.

Understanding hooks: actions and filters​


WordPress plugins interact with core events using
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
. There are two types:

  • Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
    : Triggered when WordPress does something (e.g., loading scripts, saving posts).
  • Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
    : Allow you to modify data before it’s displayed or saved.

Let’s add a reading-time badge using
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
:



function qrt_add_reading_time( $content ) {
// Only on single posts in the main loop
if ( ! is_singular( 'post' ) || ! in_the_loop() || ! is_main_query() ) {
return $content;
}

// 1. Strip HTML/shortcodes, count words
$plain = wp_strip_all_tags( strip_shortcodes( get_post()->post_content ) );
$words = str_word_count( $plain );

// 2. Estimate: 200 words per minute
$minutes = max( 1, ceil( $words / 200 ) );

// 3. Build the badge
$badge = sprintf(
'<p class="qrt-badge" aria-label="%s"><span>%s</span></p>',
esc_attr__( 'Estimated reading time', 'quick-reading-time' ),
/* translators: %s = minutes */
esc_html( sprintf( _n( '%s min read', '%s mins read', $minutes, 'quick-reading-time' ), $minutes ) )
);

return $badge . $content;
}
add_filter( 'the_content', 'qrt_add_reading_time' );

This snippet adds a reading time badge to post content using the
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
. It checks context with
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
, [URL='https://developer.wordpress.org/reference/functions/in_the_loop/']in_the_loop()[/URL], and
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
to ensure the badge only appears on single posts in the main loop.

The code strips HTML and shortcodes using
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
and
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
, counts words, and estimates reading time. Output is localized with
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
and
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
. The function is registered with
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
.

With this plugin activated, each post will now also display the reading time:

AD_4nXfx0p_oxtdM_jIUgMCDBjkon1_RU6px17uI74So_DrIc_hlxplkyA7Yq1ayIRlvGxO1DdNP1Xy0MSM9q4M-O5UWD1sIOLoPVEdKXHcrBHP7QQTZQcl2VYQsMqek_8CgK1j5noVw9g

Loading assets the WordPress way​


To style your badge, enqueue a stylesheet using the wp_enqueue_scripts action:



function qrt_enqueue_assets() {
wp_enqueue_style(
'qrt-style',
plugin_dir_url( __FILE__ ) . 'style.css',
array(),
'1.0'
);
}
add_action( 'wp_enqueue_scripts', 'qrt_enqueue_assets' );

Create a style.css file in the same folder:



.qrt-badge span {
margin: 0 0 1rem;
padding: 0.25rem 0.5rem;
display: inline-block;
background: #f5f5f5;
color: #555;
font-size: 0.85em;
border-radius: 4px;
}

Best practice: Only load assets when needed (e.g., on the front end or specific post types) for better performance.

With this change, the reading time info on each post should look like this:

Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.

Optional: Adding a settings screen​


To make the average reading speed configurable, let’s add a settings page and connect it to our plugin logic. We’ll store the user’s preferred words-per-minute (WPM) value in the WordPress options table and use it in our reading time calculation.

Step 1: Register the setting​


Add this code to your plugin file to register a new option and settings field:



// Register the setting during admin_init.
function qrt_register_settings() {
register_setting( 'qrt_settings_group', 'qrt_wpm', array(
'type' => 'integer',
'sanitize_callback' => 'qrt_sanitize_wpm',
'default' => 200,
) );
}
add_action( 'admin_init', 'qrt_register_settings' );

// Sanitize the WPM value.
function qrt_sanitize_wpm( $value ) {
$value = absint( $value );
return ( $value > 0 ) ? $value : 200;
}

This code registers a plugin option (qrt_wpm) for words-per-minute, using
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
on the
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
hook. The value is sanitized with a custom callback using
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
to ensure it’s a positive integer.

Step 2: Add the settings page​


Add a new page under Settings in the WordPress admin:



function qrt_register_settings_page() {
add_options_page(
'Quick Reading Time',
'Quick Reading Time',
'manage_options',
'qrt-settings',
'qrt_render_settings_page'
);
}
add_action( 'admin_menu', 'qrt_register_settings_page' );

This code adds a settings page for your plugin under the WordPress admin “Settings” menu. It uses
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
to register the page, and hooks the function to
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
so it appears in the dashboard. The callback (qrt_render_settings_page) will output the page’s content.

Step 3: Render the settings page​


Display a form for the WPM value and save it using the Settings API:



function qrt_render_settings_page() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
?>
<div class="wrap">
<h1><?php esc_html_e( 'Quick Reading Time Settings', 'quick-reading-time' ); ?></h1>
<form method="post" action="options.php">
<?php
settings_fields( 'qrt_settings_group' );
do_settings_sections( 'qrt_settings_group' );
$wpm = get_option( 'qrt_wpm', 200 );
?>
<table class="form-table" role="presentation">
<tr>
<th scope="row">
<label for="qrt_wpm"><?php esc_html_e( 'Words Per Minute', 'quick-reading-time' ); ?></label>
</th>
<td>
<input name="qrt_wpm" type="number" id="qrt_wpm" value="<?php echo esc_attr( $wpm ); ?>" class="small-text" min="1" />
<p class="description"><?php esc_html_e( 'Average reading speed for your audience.', 'quick-reading-time' ); ?></p>
</td>
</tr>
</table>
<?php submit_button(); ?>
</form>
</div>
<?php
}

This function renders the plugin’s settings page, displaying a form to update the WPM value. It checks user permissions with
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
, outputs the form using
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
,
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
, and retrieves the saved value with
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
. The form submits to the WordPress options system for secure saving.

Step 4: Use the setting in your plugin logic​


Update your reading time calculation to use the saved WPM value:



function qrt_add_reading_time( $content ) {
if ( ! is_singular( 'post' ) || ! in_the_loop() || ! is_main_query() ) {
return $content;
}
$plain = wp_strip_all_tags( strip_shortcodes( get_post()->post_content ) );
$words = str_word_count( $plain );
$wpm = (int) get_option( 'qrt_wpm', 200 );
$minutes = max( 1, ceil( $words / $wpm ) );
$badge = sprintf(
'<p class="qrt-badge" aria-label="%s"><span>%s</span></p>',
esc_attr__( 'Estimated reading time', 'quick-reading-time' ),
esc_html( sprintf( _n( '%s min read', '%s mins read', $minutes, 'quick-reading-time' ), $minutes ) )
);
return $badge . $content;
}

This function adds a reading time badge to post content. It checks context with
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
,
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
, and
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
to ensure it runs only on single posts in the main loop. It strips HTML and shortcodes using
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
and
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
), counts words, and retrieves the WPM value with
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
. The badge is output with proper escaping and localization using
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
,
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
, and
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
).

With these changes, your plugin now provides a user-friendly settings page under Settings → Quick Reading Time. Site administrators can set the average reading speed for their audience, and your plugin will use this value to calculate and display the estimated reading time for each post.

Complete plugin code​


Before we wrap up with best practices, let’s review the complete code for the “Quick Reading Time” plugin you built in this guide. This section brings together all the concepts covered—plugin headers, hooks, asset loading, and settings—into a single, cohesive example. Reviewing the full code helps solidify your understanding and provides a reference for your own projects.

At this stage, you should have a folder named quick-reading-time inside your wp-content/plugins/ directory, and a file called quick-reading-time.php with the following content:



<?php
/*
Plugin Name: Quick Reading Time
Description: Displays an estimated reading-time badge beneath post titles.
Version: 1.0
Author: Your Name
License: GPL-2.0+
Text Domain: quick-reading-time
*/

// Register the WPM setting during admin_init.
function qrt_register_settings() {
register_setting( 'qrt_settings_group', 'qrt_wpm', array(
'type' => 'integer',
'sanitize_callback' => 'qrt_sanitize_wpm',
'default' => 200,
) );
}
add_action( 'admin_init', 'qrt_register_settings' );

// Sanitize the WPM value.
function qrt_sanitize_wpm( $value ) {
$value = absint( $value );
return ( $value > 0 ) ? $value : 200;
}

// Add a settings page under Settings.
function qrt_register_settings_page() {
add_options_page(
'Quick Reading Time',
'Quick Reading Time',
'manage_options',
'qrt-settings',
'qrt_render_settings_page'
);
}
add_action( 'admin_menu', 'qrt_register_settings_page' );

// Render the settings page.
function qrt_render_settings_page() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
?>
<div class="wrap">
<h1><?php esc_html_e( 'Quick Reading Time Settings', 'quick-reading-time' ); ?></h1>
<form method="post" action="options.php">
<?php
settings_fields( 'qrt_settings_group' );
do_settings_sections( 'qrt_settings_group' );
$wpm = get_option( 'qrt_wpm', 200 );
?>
<table class="form-table" role="presentation">
<tr>
<th scope="row">
<label for="qrt_wpm"><?php esc_html_e( 'Words Per Minute', 'quick-reading-time' ); ?></label>
</th>
<td>
<input name="qrt_wpm" type="number" id="qrt_wpm" value="<?php echo esc_attr( $wpm ); ?>" class="small-text" min="1" />
<p class="description"><?php esc_html_e( 'Average reading speed for your audience.', 'quick-reading-time' ); ?></p>
</td>
</tr>
</table>
<?php submit_button(); ?>
</form>
</div>
<?php
}

// Add the reading time badge to post content.
function qrt_add_reading_time( $content ) {
if ( ! is_singular( 'post' ) || ! in_the_loop() || ! is_main_query() ) {
return $content;
}
$plain = wp_strip_all_tags( strip_shortcodes( get_post()->post_content ) );
$words = str_word_count( $plain );
$wpm = (int) get_option( 'qrt_wpm', 200 );
$minutes = max( 1, ceil( $words / $wpm ) );
$badge = sprintf(
'<p class="qrt-badge" aria-label="%s"><span>%s</span></p>',
esc_attr__( 'Estimated reading time', 'quick-reading-time' ),
esc_html( sprintf( _n( '%s min read', '%s mins read', $minutes, 'quick-reading-time' ), $minutes ) )
);
return $badge . $content;
}
add_filter( 'the_content', 'qrt_add_reading_time' );

// Enqueue the plugin stylesheet.
function qrt_enqueue_assets() {
wp_enqueue_style(
'qrt-style',
plugin_dir_url( __FILE__ ) . 'style.css',
array(),
'1.0'
);
}
add_action( 'wp_enqueue_scripts', 'qrt_enqueue_assets' );

You should also have a style.css file in the same folder with the following content to style the badge:



.qrt-badge span {
margin: 0 0 1rem;
padding: 0.25rem 0.5rem;
display: inline-block;
background: #f5f5f5;
color: #555;
font-size: 0.85em;
border-radius: 4px;
}

This plugin demonstrates several foundational concepts in WordPress development:

  • Plugin Header: The block comment at the top registers your plugin with WordPress, making it discoverable and manageable from the admin dashboard.
  • Hooks: The plugin uses both actions (admin_init, admin_menu, wp_enqueue_scripts) and a filter (the_content) to integrate with WordPress at the right moments.
  • Settings API: By registering a custom option and rendering a settings page, the plugin allows site administrators to configure the average reading speed, making the feature flexible and user-friendly.
  • Sanitization and Security: All user input is sanitized, and output is escaped, following best practices to prevent security vulnerabilities.
  • Asset Loading: Styles are loaded using WordPress’s enqueue system, ensuring compatibility and performance.
  • Internationalization: All user-facing strings are wrapped in translation functions, making the plugin ready for localization.

By bringing these elements together, you have a robust, maintainable, and extensible plugin foundation. Use this as a template for your own ideas, and continue exploring the WordPress Plugin Developer Handbook for deeper knowledge.

Best practices for plugin development​


Building a WordPress plugin is more than just making something work—it’s about creating code that is robust, secure, and maintainable for years to come. As your plugin grows or is shared with others, following best practices becomes essential to avoid pitfalls that can lead to bugs, security vulnerabilities, or compatibility issues. The habits you form early in your development journey will shape the quality and reputation of your work.

Let’s explore the foundational principles that set apart professional WordPress plugin development.

  • Prefix everything (e.g., qrt_) to avoid name collisions. WordPress is a global namespace, so unique prefixes for functions, classes, and even option names help prevent conflicts with other plugins or themes.
  • Escape and sanitize all output and input to prevent XSS and security issues. Always validate and clean data before saving it to the database or displaying it in the browser. Use functions like
    Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
    ,
    Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
    , and
    Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
    to keep your plugin safe.
  • Translate strings using
    Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
    , and
    Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
    for localization. Internationalization (i18n) ensures your plugin is accessible to users worldwide. Wrap all user-facing text in translation functions and provide a text domain.
  • Use version control (
    Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
    ) and WP-CLI helpers (
    Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
    ,
    Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
    ). Version control is your safety net, allowing you to track changes, collaborate, and roll back mistakes. WP-CLI tools can automate repetitive tasks and enforce consistency.
  • Ship a readme.txt for the Plugin Directory and changelog. A well-written readme helps users understand your plugin’s features, installation steps, and update history. It’s also required for distribution on WordPress.org.
  • Debugging: Enable
    Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
    and use tools like
    Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
    for troubleshooting. Proactive debugging surfaces issues early, making them easier to fix and improving your plugin’s reliability.
  • Follow the
    Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
    and
    Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
    . These resources are the gold standard for WordPress development, offering guidance on everything from code style to security.

Tip: Adopt these habits early—retrofitting best practices later is much harder. By making them part of your workflow from the start, you’ll save time, reduce stress, and build plugins you can be proud of.

Next steps and resources​


You now have a working plugin that demonstrates the three “golden” hooks:

  • [URL='https://developer.wordpress.org/reference/hooks/the_content/']the_content[/URL] – injects the badge.
  • [URL='https://developer.wordpress.org/reference/hooks/wp_enqueue_scripts/']wp_enqueue_scripts[/URL] – loads the stylesheet.
  • Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
    – (optionally) adds a settings page.

Where you go next is up to you—try adding
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
(
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
),
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
(
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
),
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
, or
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
(
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
). The mental model is the same: find the hook, write a callback, let WordPress run it.

Your plugin journey starts here​


Every plugin—whether 40 KB or 40 MB—starts with a folder, a header, and a hook. Master that foundation, and the rest of the WordPress ecosystem opens wide. Experiment locally, keep your code readable and secure, and iterate in small steps. With practice, the leap from “I wish WordPress could…” to “WordPress does” becomes second nature.

Ready to build your own plugin? Try the steps above, share your results in the comments, or explore more advanced topics in our
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
. Happy coding!

Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
 

Bu Konuyu Görüntüleyen Kullanıcılar (Toplam: 0 | Üyeler: 0 | Ziyaretçiler: 0)

Geri